Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(aws): consolidated cloudtrail + multitenancy #45

Merged
merged 1 commit into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 49 additions & 9 deletions aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ provider "aws" {}
provider "lacework" {}

module "aws_config" {
source = "./modules/config"
source = "github.com/lacework/terraform-provisioning/aws/modules/config"
}

module "aws_cloudtrail" {
source = "./modules/cloudtrail"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"
bucket_force_destroy = true
use_existing_iam_role = true
iam_role_name = module.aws_config.iam_role_name
Expand All @@ -53,11 +53,11 @@ provider "aws" {}
provider "lacework" {}

module "aws_config" {
source = "./modules/config"
source = "github.com/lacework/terraform-provisioning/aws/modules/config"
}

module "aws_cloudtrail" {
source = "./modules/cloudtrail"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"

use_existing_cloudtrail = true
bucket_name = "lacework-ct-bucket-8805c0bf"
Expand All @@ -80,11 +80,11 @@ provider "aws" {}
provider "lacework" {}

module "aws_config" {
source = "./modules/config"
source = "github.com/lacework/terraform-provisioning/aws/modules/config"
}

module "aws_cloudtrail" {
source = "./modules/cloudtrail"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"

use_existing_cloudtrail = true
bucket_name = "lacework-ct-bucket-8805c0bf"
Expand All @@ -98,6 +98,41 @@ module "aws_cloudtrail" {

**NOTE: This example assumes that your CloudTrail is already sending delivery notifications to the provided SNS topic.**

### Enable New Consolidated CloudTrail Configuration
This example enables a new Consolidated CloudTrail and IAM Role for Lacework, then configures both integrations with Lacework,
finally, it configures a new CloudTrail in an AWS sub-account that points to the main CloudTrail.

```hcl
provider "lacework" {
alias = "main"
}

provider "aws" {
alias = "main"
}

module "main_cloudtrail" {
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"
providers = {
aws = aws.main
lacework = lacework.main
}
consolidated_trail = true
}

provider "aws" {
alias = "sub_account"
}

resource "aws_cloudtrail" "lw_sub_account_cloudtrail" {
provider = aws.sub_account
name = "lacework-sub-trail"
is_multi_region_trail = true
s3_bucket_name = module.main_cloudtrail.bucket_name
sns_topic_name = module.main_cloudtrail.sns_arn
}
```

## Inputs

| Name | Description | Type | Default | Required |
Expand All @@ -113,13 +148,18 @@ module "aws_cloudtrail" {
| prefix | The prefix that will be use at the beginning of every generated resource | `string` | lacework-ct | no |
| sns_topic_name | SNS topic name. Can be used when generating a new resource or when using an existing resource. | `string` | "" | no |
| sqs_queue_name | SQS queue name. Can be used when generating a new resource or when using an existing resource. | `string` | "" | no |
| sqs_queues | List of SQS queues to configure in the Lacework cross-account policy. | `list(string)` | `[]` | no |
| consolidated_trail | Set this to `true` to configure a consolidated cloudtrail. | `bool` | `false` | no |
| use_existing_cloudtrail | Set this to `true` to use an existing cloudtrail. When set to `true` you must provide both the `bucket_name` and `sns_topic_name` | `bool` | `false` | no |
| use_existing_iam_role | Set this to `true` to use an existing IAM role. When set to `true` you must provide both the `iam_role_name` and `iam_role_external_id` | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| external_id | Dynamically generated external_id |
| iam_role_name | IAM Role name generated |
| iam_role_arn | IAM Role arn |
| external_id | Dynamically generated External ID configured into the IAM role |
| iam_role_name | IAM Role name generated |
| iam_role_arn | IAM Role arn |
| bucket_name | S3 Bucket name |
| sqs_name | SQS Queue name |
| sns_arn | SNS Topic Arn |
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ provider "lacework" { }
provider "aws" { }

module "aws_cloudtrail" {
source = "../../"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
provider "lacework" {
alias = "main"
}

provider "aws" {
alias = "main"
}

variable "aws_accounts" {
type = list(string)
default = [
"123456789011",
// ... list all accounts
"123456789019",
]
}

resource "aws_sqs_queue" "lw_ct_sqs_sub_accounts" {
provider = aws.main
count = length(var.aws_accounts)
name = "lw-ct-sqs-${var.aws_accounts[count.index]}"
}

module "main_cloudtrail" {
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"
providers = {
aws = aws.main
lacework = lacework.main
}
consolidated_trail = true
sqs_queues = aws_sqs_queue.lw_ct_sqs_sub_accounts.*.arn
}

resource "lacework_integration_aws_ct" "main" {
provider = lacework.main
name = "TF consolidated"
queue_url = aws_sqs_queue.lacework_ct_sqs_sub_accounts.0.id
credentials {
role_arn = module.main_cloudtrail.iam_role_arn
external_id = module.main_cloudtrail.external_id
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
provider "lacework" {
alias = "sub_tenant"
}

provider "aws" {
alias = "sub_account"
}

resource "aws_cloudtrail" "lw_sub_account_cloudtrail" {
provider = aws.sub_account
name = "lacework-sub-trail"
is_multi_region_trail = true
s3_bucket_name = module.main_cloudtrail.bucket_name
sns_topic_name = module.main_cloudtrail.sns_arn
}

resource "lacework_integration_aws_ct" "sub_account" {
provider = lacework.sub_tenant
name = "TF consolidated"
queue_url = aws_sqs_queue.lw_ct_sqs_sub_accounts.1.id
credentials {
role_arn = module.main_cloudtrail.iam_role_arn
external_id = module.main_cloudtrail.external_id
}
depends_on = [aws_cloudtrail.lw_sub_account_cloudtrail]
}
28 changes: 28 additions & 0 deletions aws/modules/cloudtrail/examples/consolidated-cloudtrail/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
provider "lacework" {
alias = "main"
}

provider "aws" {
alias = "main"
}

module "main_cloudtrail" {
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"
providers = {
aws = aws.main
lacework = lacework.main
}
consolidated_trail = true
}

provider "aws" {
alias = "sub_account"
}

resource "aws_cloudtrail" "lw_sub_account_cloudtrail" {
provider = aws.sub_account
name = "lacework-sub-trail"
is_multi_region_trail = true
s3_bucket_name = module.main_cloudtrail.bucket_name
sns_topic_name = module.main_cloudtrail.sns_arn
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ provider "lacework" { }
provider "aws" { }

module "aws_cloudtrail" {
source = "../../"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"

# Use an existing CloudTrail
use_existing_cloudtrail = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ provider "lacework" { }
provider "aws" { }

module "aws_cloudtrail" {
source = "../../"
source = "github.com/lacework/terraform-provisioning/aws/modules/cloudtrail"

# Use an existing CloudTrail
use_existing_cloudtrail = true
Expand Down
65 changes: 39 additions & 26 deletions aws/modules/cloudtrail/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,45 @@ resource "aws_cloudtrail" "lacework_cloudtrail" {
depends_on = [aws_s3_bucket.cloudtrail_bucket]
}

# we need the identity of the caller to get their account_id for the s3 bucket
data "aws_caller_identity" "current" {}
resource "aws_s3_bucket" "cloudtrail_bucket" {
count = var.use_existing_cloudtrail ? 0 : 1
bucket = local.bucket_name
force_destroy = var.bucket_force_destroy
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck20150319",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::${local.bucket_name}"
},
{
"Sid": "AWSCloudTrailWrite20150319",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::${local.bucket_name}/AWSLogs/${data.aws_caller_identity.current.account_id}/*",
"Condition": {
"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}
}
}
]
policy = data.aws_iam_policy_document.cloudtrail_s3_policy.json
}
POLICY

# we need the identity of the caller to get their account_id for the s3 bucket
data "aws_caller_identity" "current" {}
data "aws_iam_policy_document" "cloudtrail_s3_policy" {
version = "2012-10-17"

statement {
sid = "AWSCloudTrailAclCheck20150319"
actions = ["s3:GetBucketAcl"]
resources = ["arn:aws:s3:::${local.bucket_name}"]

principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}
}

statement {
sid = "AWSCloudTrailWrite20150319"
actions = ["s3:PutObject"]
resources = var.consolidated_trail ? (["arn:aws:s3:::${local.bucket_name}/AWSLogs/*"]) : (["arn:aws:s3:::${local.bucket_name}/AWSLogs/${data.aws_caller_identity.current.account_id}/*"])

principals {
type = "Service"
identifiers = ["cloudtrail.amazonaws.com"]
}

condition {
test = "StringEquals"
variable = "s3:x-amz-acl"
values = ["bucket-owner-full-control"]
}
}
}

# we use this data source to point to the S3 ARN for the cross-account policy,
Expand Down Expand Up @@ -151,7 +160,7 @@ data "aws_iam_policy_document" "cross_account_policy" {

statement {
sid = "ConsumeNotifications"
resources = [aws_sqs_queue.lacework_cloudtrail_sqs_queue.arn]
resources = flatten([var.sqs_queues, [aws_sqs_queue.lacework_cloudtrail_sqs_queue.arn]])
actions = [
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
Expand Down Expand Up @@ -213,6 +222,10 @@ resource "time_sleep" "wait_5_seconds" {
}

resource "lacework_integration_aws_ct" "default" {
// do not create a CT integration if the user provides multiple
// SQS queues to configure, it means that they want to fan-out
// with a lambda function that acks like a gateway
count = length(var.sqs_queues) > 0 ? 0 : 1
name = var.lacework_integration_name
queue_url = aws_sqs_queue.lacework_cloudtrail_sqs_queue.id
credentials {
Expand Down
29 changes: 29 additions & 0 deletions aws/modules/cloudtrail/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
output "bucket_name" {
value = local.bucket_name
description = "S3 Bucket name"
}

output "sqs_name" {
value = local.sqs_queue_name
description = "SQS Queue name"
}

output "sns_arn" {
value = aws_sns_topic.lacework_cloudtrail_sns_topic.arn
description = "SNS Topic ARN"
}

output "external_id" {
value = local.external_id
description = "The External ID configured into the IAM role"
}

output "iam_role_name" {
value = local.iam_role_name
description = "IAM Role name"
}

output "iam_role_arn" {
value = module.lacework_ct_iam_role.arn
description = "IAM Role ARN"
}
12 changes: 12 additions & 0 deletions aws/modules/cloudtrail/variables.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
variable "consolidated_trail" {
type = bool
default = false
description = "Set this to true to configure a consolidated cloudtrail"
}

variable "use_existing_iam_role" {
type = bool
default = false
Expand Down Expand Up @@ -62,6 +68,12 @@ variable "cross_account_policy_name" {
default = ""
}

variable "sqs_queues" {
type = list(string)
default = []
description = "List of SQS queues to configure in the Lacework cross-account policy"
}

variable "lacework_integration_name" {
type = string
default = "TF cloudtrail"
Expand Down
9 changes: 6 additions & 3 deletions aws/modules/config/output.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
output "external_id" {
value = module.lacework_cfg_iam_role.external_id
value = module.lacework_cfg_iam_role.external_id
description = "The External ID configured into the IAM role"
}

output "iam_role_name" {
value = module.lacework_cfg_iam_role.name
value = module.lacework_cfg_iam_role.name
description = "IAM Role name"
}

output "iam_role_arn" {
value = module.lacework_cfg_iam_role.arn
value = module.lacework_cfg_iam_role.arn
description = "IAM Role ARN"
}