Skip to content

Commit

Permalink
Match to docs (#2)
Browse files Browse the repository at this point in the history
* Removed an empty file, and added a `.gitignore` file to not track artifacts of running `terraform init/plan/apply`

* Ran `terraform 0.12-compatibility` to do a basic 0.11->0.12 conversion.

* Put proper years in license

* Changed input variable structure. This allows for cleaner extension of config if we decide to cover more cloud providers in the future.

* Removed commented out old parameters. Added comments.

* Updated README to reflect new input variable names/structure. Renamed one varable back to its original name. Deleted an obsolete screenshot from the documentation/README.

* Fix a typo in the README and a typo in the variable definition

* Use proper 0.12 syntax

* Fix variable types to string

* Fix more 0.12 syntax issues

* Restructured configuration due to limitations in terraform variable definition syntax.

See: hashicorp/terraform#19898

* Fix a place I didn't correctly rename a variable reference

* Updated code comments and README with correct variable information, and a few typo fixes along the way.

* Add dependency documention for required Terraform providers.

* Fix some docs, and add the defaults for the optional settings

* Remove largely unneeded variable. This also aligns the terraform module more closely to the CloudFormation template.
  • Loading branch information
olhado authored and patcable committed Dec 27, 2019
1 parent a8d9bbd commit 94a3808
Show file tree
Hide file tree
Showing 13 changed files with 324 additions and 216 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.terraform/
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2017 Threat Stack, Inc.
Copyright 2017-2019 Threat Stack, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
184 changes: 151 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# tf_threatstack_aws_integration
Setup Threat Stack <-> AWS integration module
# tf_threatstack_control_plane_monitoring_integration
Setup Threat Stack <-> Control Plane Monitoring integration module

This module provides the ability to setup Threat Stack integration via Terraform. This module will setup the following:
This module provides the ability to define the Threat Stack integration infrastructure via Terraform. Currently only AWS Cloudtrail is supported, and it automates the [AWS Manual Integration Setup](https://threatstack.zendesk.com/hc/en-us/articles/206512364-AWS-Manual-Integration-Setup)

This module will create and manage the following:

* AWS CloudTrail
* multi-region trail
Expand All @@ -13,61 +15,177 @@ This module provides the ability to setup Threat Stack integration via Terraform
* AWS SQS queue Threat Stack will check for events
* Cross account IAM role for Threat Stack

## Dependencies

This Terraform module currently depends on the following providers as dependencies:

* `template` ~> 2.1
* `aws` ~> 2.0

## Usage
To use this module you need to create a Terraform configuration that utilizes this module. A basic example configuration would look as follows (Be sure to adjust the git ref in the source value appropriately):
> **This version of the module is compatible with Terraform 0.12+.** Terraform 0.11 and earlier are not supported, and this module will not work. For a pre-0.12-compatible version of this module, see [v1.0.0 of this module](https://github.com/threatstack/threatstack-terraform/tree/v1.0.0).
To use, a user-created module should be defined that _imports_ this module (via the `source` parameter on the `module` setting. Terraform will download and use the source module with the `terraform init` command, so there is no need to download it separately for use. The minimum configuration for the user would look as follows (Be sure to adjust the git ref in the source value appropriately):

```hcl
module "threatstack_aws_integration" {
source = "github.com/threatstack/tf_threatstack_aws_integration?ref=v1.0.0"
aws_account = "<AWS_ACCOUNT_NAME>"
aws_account_id = "<AWS_ACCOUNT_ID>"
aws_region = "us-east-1"
threatstack_account_id = "<THREATSTACK_AWS_ACCOUNT_ID>"
threatstack_external_id = "<THREATSTACK_AWS_EXTERNAL_ID>"
module "threatstack_aws_integration" { # THe name of the module here is arbitrary and can be whatever makes it easily identifiable to the end-user
source = "github.com/threatstack/threatstack-terraform?ref=<integration_version>"
threatstack = {
account_id = "<THREATSTACK_AWS_ACCOUNT_ID>"
external_id = "<THREATSTACK_AWS_EXTERNAL_ID>"
}
aws_account_info = {
account_id = "<AWS_ACCOUNT_ID>"
region = "us-east-1"
}
}
```

## Threat Stack Setup
In Threat Stack click `Add Profile` under _AWS Profiles_ fill in the relevant output values on the _Integrations_ page under _Settings_ and get the Threat Stack _Account ID_ and _External ID_. Use these values for the `threatstack_account_id` and `threatstack_external_id`. Run Terraform and get the outputs from it.

![Terraform output](https://github.com/threatstack/tf_threatstack_aws_integration/raw/master/doc/terraform_output.png "Terraform output")
In Threat Stack click `Add Account` under _AWS Accounts_ fill in the relevant output values on the _Integrations_ page under _Settings_ and get the Threat Stack _Account ID_ and _External ID_. Use these values for the `threatstack.account_id` and `threatstack.external_id` input variables (see below). Run Terraform and get the outputs from it.

With the output values, fill in the Threat Stack profile screen.
![Terraform output](https://github.com/threatstack/threatstack-terraform/raw/master/doc/terraform_output.png "Terraform output")

![Threat Stack setup](https://github.com/threatstack/tf_threatstack_aws_integration/raw/master/doc/threat_stack_setup.png "Threat Stack setup screen")
Record the Terraform output values, and use them to complete the configuration of the Threat Stack platform's side integration. See sections 3 & 6 of the [AWS Manual Integration Setup](https://threatstack.zendesk.com/hc/en-us/articles/206512364-AWS-Manual-Integration-Setup) page for details.

## Variables
* ___aws_account:___ Name of AWS account. Used to find remote state information and is prepended to bucket names.

* ___aws_account_id:___ Account ID, used for CloudTrail integration.
The module's input variables are defined in their own Terraform variable objects. They are as follows:

* ___threatstack:___ **(REQUIRED)** Threat Stack-specific settings to deploy the integration. The defaults are null, so the integration will fail if not set.

* ___aws_account_info:___ **(REQUIRED)** AWS account specifics to deploy the integration. The defaults are null, so the integration will fail if not set.

* ___aws_flags:___ **(Optional)** The flags have defaults, so the module can work without these explicitly set.

* ___aws_optional_conf:___ **(Optional)** The settings have defaults, so the module can work without these explicitly set.


#### Threat Stack configuration

All of the Threat Stack configuration is required. Not explicitly defining these values when using this module will cause the integration to not work as expected.

The Threat Stack configuration is defined as follows:

```hcl
module "threatstack_aws_integration" {
source = "github.com/threatstack/threatstack-terraform?ref=<integration_version>"
# Strings generated from the Threat Stack Add Account page
threatstack = {
account_id = string
external_id = string
}
}
```

* ___aws_region:___ AWS region. Used to find remote state.
* ___threatstack.account_id:___ Threat Stack account ID associated with the Threat Stack org. Used to find remote state information and is prepended to bucket names.

* ___aws_cloudtrail_name (optional):___ Name of CloudTrail trail.
* ___threatstack.external_id:___ Account ID, used for CloudTrail integration.

* ___aws_iam_role_name (optional):___ Name of cross account IAM role grating access for Threat Stack to AWS environment.

* ___aws_sns_topic_name (optional):___ Name of SNS topic used by CloudTrail.
#### AWS configuration

* ___aws_sns_topic_display_name (optional):___ SNS topic display name.
This Terraform input variable is split into 3 sections: required settings, flag settings, and optional settings

* ___aws_sqs_queue_name (optional):___ Name of SQS queue to forward events to.
##### Required settings

* ___s3_bucket_name (optional):___ Name of bucket to create to store logs. Pay attention to the fact that domain name and account name will be prepended to thebucket to help prevent name collisions.
```hcl
module "threatstack_aws_integration" {
source = "github.com/threatstack/threatstack-terraform?ref=<integration_version>"
aws_account_info = {
# ...
account_id = string
region = string
#...
}
}
```

* ___aws_account_info.account_id:___ Account ID, used for CloudTrail integration.

* ___aws_account_info.region:___ AWS region. Used to find remote state.

##### Flag settings

```hcl
module "threatstack_aws_integration" {
source = "github.com/threatstack/threatstack-terraform?ref=<integration_version>"
aws_flags = {
# ...
enable_logging = bool # Defaults to `true`
enable_log_file_validation = bool # Defaults to `true`
include_global_service_events = bool # Defaults to `true`
is_multi_region_trail = bool # Defaults to `true`
s3_force_destroy = bool # Defaults to `false`
#...
}
}
```
* ___aws_flags.enable_logging (optional):___ Enable logging, set to 'false' to pause logging.

* ___aws_flags.enable_log_file_validation (optional):___ Create signed digest file to validated contents of logs.

* ___aws_flags.include_global_service_events (optional):___ Include evnets from global services such as IAM.

* ___aws_flags.is_multi_region_trail (optional):___ Whether the trail is created in all regions or just the current region.

* ___aws_flags.s3_force_destroy (optional):___ Bucket destroy will fail if the bucket is not empty. Set to `"true"` if you REALLY want to destroy logs on teardown.


##### Optional settings

```hcl
module "threatstack_aws_integration" {
source = "github.com/threatstack/threatstack-terraform?ref=<integration_version>"
aws_optional_conf = {
# ...
cloudtrail_name = string # Defaults to "ThreatStackIntegration"
iam_role_name = string # Defaults to "ThreatStackIntegration"
sns_topic_name = string # Defaults to "ThreatStackIntegration"
sns_topic_display_name = string # Defaults to "Threat Stack integration topic."
sqs_queue_name = string # Defaults to "ThreatStackIntegration"
s3_bucket_name = string # Defaults to "threatstack-integration"
s3_force_destroy = string # Defaults to "/"
#...
}
}
```

* ___s3_bucket_prefix (optional):___ S3 prefix path for logs. Useful is using a bucket used by other services. (Not recommended)
* ___aws_optional_conf.cloudtrail_name (optional):___ Name of CloudTrail trail.

* ___s3_force_destroy (optional):___ Bucket destroy will fail if the bucket is not empty. Set to `"true"` if you REALLY want to destroy logs on teardown.
* ___aws_optional_conf.iam_role_name (optional):___ Name of cross account IAM role gating access for Threat Stack to AWS environment.

* ___enable_logging (optional):___ Enable logging, set to 'false' to pause logging.
* ___aws_optional_conf.sns_topic_name (optional):___ Name of SNS topic used by CloudTrail.

* ___enable_log_file_validation (optional):___ Create signed digest file to validated contents of logs.
* ___aws_optional_conf.sns_topic_display_name (optional):___ SNS topic display name.

* ___include_global_service_events (optional):___ Include evnets from global services such as IAM.
* ___aws_optional_conf.sqs_queue_name (optional):___ Name of SQS queue to forward events to.

* ___is_multi_region_trail (optional):___ Whether the trail is created in all regions or just the current region.
* ___aws_optional_conf.s3_bucket_name (optional):___ Name of bucket to create to store logs. Pay attention to the fact that account name will be prepended to the provided bucket name to help prevent name collisions.

* ___aws_optional_conf.s3_bucket_prefix (optional):___ S3 prefix path for logs. Useful is using a bucket used by other services. (Not recommended)

## Outputs
* ___cloudtrail_arn:___ ARN of CloudTrail.
Expand All @@ -78,7 +196,7 @@ With the output values, fill in the Threat Stack profile screen.

* ___cloudwatch_log_group_arn:___ ARN of CloudWatch log group for cloudTrail events.

* ___iam_role_arn:___ ARN of cross account IAM role granting Threat Stack access to environment. (Enter this value into Threat Stack when setting up.)
* ___iam_role_arn:___ ARN of cross account IAM role granting Threat Stack access to environment. **(Enter this value into Threat Stack when setting up.)**

* ___iam_role_name:___ Name of cross account IAM role granting Threat Stack access to environment.

Expand All @@ -88,12 +206,12 @@ With the output values, fill in the Threat Stack profile screen.

* ___s3_bucket_arn:___ ARN of bucket for CloudTrail events.

* ___s3_bucket_id:___ Name of bucket for CloudTrail events. (Enter this value into Threat Stack when setting up.)
* ___s3_bucket_id:___ Name of bucket for CloudTrail events. **(Enter this value into Threat Stack when setting up.)**

* ___sns_topic_arn:___ ARN of SNS topic where CloudTrail events are forwarded to.

* ___sqs_queue_arn:___ ARN of SQS queue Threat Stack reads events from.

* ___sqs_queue_id:___ SQS queue ID / endpoint.

* ___sqs_queue_source:___ Name of SQS queue Threat Stack reads events from. (Enter this value into Threat Stack when setting up.)
* ___sqs_queue_source:___ Name of SQS queue Threat Stack reads events from. **(Enter this value into Threat Stack when setting up.)**
55 changes: 29 additions & 26 deletions aws_cloudtrail.tf
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
// AWS Cloudtrail
data "template_file" "aws_iam_cloudtrail_to_cloudwatch_assume_role_policy" {
template = "${file("${path.module}/aws_iam_cloudtrail_to_cloudwatch_assume_role_policy.tpl")}"
template = file(
"${path.module}/aws_iam_cloudtrail_to_cloudwatch_assume_role_policy.tpl",
)
}

data "template_file" "aws_iam_cloudtrail_to_cloudwatch_policy" {
template = "${file("${path.module}/aws_iam_cloudtrail_to_cloudwatch_policy.tpl")}"
vars {
aws_account_id = "${var.aws_account_id}"
aws_cloudtrail_name = "${var.aws_cloudtrail_name}"
aws_region = "${var.aws_region}"
template = file("${path.module}/aws_iam_cloudtrail_to_cloudwatch_policy.tpl")
vars = {
aws_account_id = var.aws_account_info.account_id
aws_cloudtrail_name = var.aws_optional_conf.cloudtrail_name
aws_region = var.aws_account_info.region
}
}


resource "aws_cloudwatch_log_group" "ct" {
name = "/aws/cloudtrail/${var.aws_cloudtrail_name}"
tags {
name = "/aws/cloudtrail/${var.aws_optional_conf.cloudtrail_name}"
tags = {
terraform = "true"
}
depends_on = ["aws_iam_role_policy.ct", "aws_s3_bucket_policy.bucket"]
depends_on = [
aws_iam_role_policy.ct,
aws_s3_bucket_policy.bucket,
]
}

resource "aws_iam_role" "ct" {
name = "${var.aws_cloudtrail_name}-CloudTrailToCloudWatch"
assume_role_policy = "${data.template_file.aws_iam_cloudtrail_to_cloudwatch_assume_role_policy.rendered}"
name = "${var.aws_optional_conf.cloudtrail_name}-CloudTrailToCloudWatch"
assume_role_policy = data.template_file.aws_iam_cloudtrail_to_cloudwatch_assume_role_policy.rendered
}

resource "aws_iam_role_policy" "ct" {
name = "CloudTrailToCloudWatch"
role = "${aws_iam_role.ct.id}"
policy = "${data.template_file.aws_iam_cloudtrail_to_cloudwatch_policy.rendered}"

name = "CloudTrailToCloudWatch"
role = aws_iam_role.ct.id
policy = data.template_file.aws_iam_cloudtrail_to_cloudwatch_policy.rendered
}

resource "aws_cloudtrail" "ct" {
name = "${var.aws_cloudtrail_name}"
s3_bucket_name = "${aws_s3_bucket.bucket.id}"
enable_logging = "${var.enable_logging}"
enable_log_file_validation = "${var.enable_log_file_validation}"
include_global_service_events = "${var.include_global_service_events}"
is_multi_region_trail = "${var.is_multi_region_trail}"
cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.ct.arn}"
cloud_watch_logs_role_arn = "${aws_iam_role.ct.arn}"
sns_topic_name = "${aws_sns_topic.sns.arn}"
depends_on = ["aws_s3_bucket_policy.bucket"]
name = var.aws_optional_conf.cloudtrail_name
s3_bucket_name = aws_s3_bucket.bucket.id
enable_logging = var.aws_flags.enable_logging
enable_log_file_validation = var.aws_flags.enable_log_file_validation
include_global_service_events = var.aws_flags.include_global_service_events
is_multi_region_trail = var.aws_flags.is_multi_region_trail
cloud_watch_logs_group_arn = aws_cloudwatch_log_group.ct.arn
cloud_watch_logs_role_arn = aws_iam_role.ct.arn
sns_topic_name = aws_sns_topic.sns.arn
depends_on = [aws_s3_bucket_policy.bucket]
}

29 changes: 14 additions & 15 deletions aws_iam_role.tf
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
// AWS Iam role for cross account access

data "template_file" "aws_iam_assume_role_policy" {
template = "${file("${path.module}/aws_iam_assume_role_policy.tpl")}"
vars {
threatstack_account_id = "${var.threatstack_account_id}"
threatstack_external_id = "${var.threatstack_external_id}"
template = file("${path.module}/aws_iam_assume_role_policy.tpl")
vars = {
threatstack_account_id = var.threatstack.account_id
threatstack_external_id = var.threatstack.external_id
}
}

data "template_file" "aws_iam_role_policy" {
template = "${file("${path.module}/aws_iam_role_policy.tpl")}"
vars {
sqs_queue_arn = "${aws_sqs_queue.sqs.arn}"
s3_resource = "${aws_s3_bucket.bucket.arn}/*"
template = file("${path.module}/aws_iam_role_policy.tpl")
vars = {
sqs_queue_arn = aws_sqs_queue.sqs.arn
s3_resource = "${aws_s3_bucket.bucket.arn}/*"
}
}


resource "aws_iam_role" "role" {
name = "${var.aws_iam_role_name}"
assume_role_policy = "${data.template_file.aws_iam_assume_role_policy.rendered}"
depends_on = ["aws_iam_role_policy.ct"]
name = var.aws_optional_conf.iam_role_name
assume_role_policy = data.template_file.aws_iam_assume_role_policy.rendered
depends_on = [aws_iam_role_policy.ct]
}

resource "aws_iam_role_policy" "role" {
name = "${var.aws_iam_role_name}"
role = "${aws_iam_role.role.id}"
name = var.aws_optional_conf.iam_role_name
role = aws_iam_role.role.id

policy = "${data.template_file.aws_iam_role_policy.rendered}"
policy = data.template_file.aws_iam_role_policy.rendered
}

Loading

0 comments on commit 94a3808

Please sign in to comment.