diff --git a/README.md b/README.md index 14fe36e..ff9ade3 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Full contributing [guidelines are covered here](.github/contributing.md). | [additional\_iam\_policy\_statements](#input\_additional\_iam\_policy\_statements) | Map of dynamic policy statements to attach to Lambda Function role | `any` | `{}` | no | | [allowed\_aws\_principals\_for\_sns\_subscribe](#input\_allowed\_aws\_principals\_for\_sns\_subscribe) | List of AWS principals allowed to subscribe to the SNS topic (only applicable to org deployments). | `list(string)` | `[]` | no | | [cloudtrail\_bucket\_name](#input\_cloudtrail\_bucket\_name) | Bucket containing the Cloudtrail logs that you want to process. ControlTower bucket name follows this naming convention `aws-controltower-logs-{{account_id}}-{{region}}` | `string` | `""` | no | +| [cloudtrail\_bucket\_notifications\_sns\_arn](#input\_cloudtrail\_bucket\_notifications\_sns\_arn) | SNS topic ARN for bucket notifications. If not provided, a new SNS topic will be created along with the bucket notifications configuration. | `string` | `null` | no | | [cloudtrail\_log\_group](#input\_cloudtrail\_log\_group) | CloudWatch Log group for CloudTrail events. | `string` | `""` | no | | [create\_iam\_role](#input\_create\_iam\_role) | Determines whether a an IAM role is created or to use an existing IAM role | `bool` | `true` | no | | [event\_batch\_size](#input\_event\_batch\_size) | Batch events into chunks of `event_batch_size` | `number` | `100` | no | @@ -117,7 +118,6 @@ Full contributing [guidelines are covered here](.github/contributing.md). | [aws_iam_policy_document.lambda_permissions](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.sns_topic_policy_bucket_notifications](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | -| [aws_s3_bucket.cloudtrail_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_bucket) | data source | ---- ### Default excluded scoped actions diff --git a/deployment_organization.tf b/deployment_organization.tf index 1df5830..637f8cb 100644 --- a/deployment_organization.tf +++ b/deployment_organization.tf @@ -8,20 +8,11 @@ # Ref: https://aws.amazon.com/blogs/compute/fanout-s3-event-notifications-to-multiple-endpoints/ -#-------------------------------------------------------------------------------------- -# aws_s3_bucket -#-------------------------------------------------------------------------------------- -data "aws_s3_bucket" "cloudtrail_bucket" { - count = var.standalone ? 0 : 1 - - bucket = var.cloudtrail_bucket_name -} - #-------------------------------------------------------------------------------------- # aws_sns_topic #-------------------------------------------------------------------------------------- resource "aws_sns_topic" "bucket_notifications" { - count = var.standalone ? 0 : 1 + count = var.standalone || var.cloudtrail_bucket_notifications_sns_arn != null ? 0 : 1 name = var.naming_prefix # Cannot use AWS managed KMS key with S3 bucket notifications @@ -38,13 +29,13 @@ locals { } } data "aws_iam_policy_document" "sns_topic_policy_bucket_notifications" { - count = var.standalone ? 0 : 1 + count = var.standalone || var.cloudtrail_bucket_notifications_sns_arn != null ? 0 : 1 statement { sid = "AllowS3BucketNotificationToSNSPublish" actions = ["SNS:Publish"] effect = "Allow" - resources = [aws_sns_topic.bucket_notifications[0].arn] + resources = [try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn)] principals { type = "Service" identifiers = ["s3.amazonaws.com"] @@ -52,7 +43,7 @@ data "aws_iam_policy_document" "sns_topic_policy_bucket_notifications" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [data.aws_s3_bucket.cloudtrail_bucket[0].arn] + values = ["arn:aws:s3:::${var.cloudtrail_bucket_name}"] } condition { test = "StringEquals" @@ -61,13 +52,13 @@ data "aws_iam_policy_document" "sns_topic_policy_bucket_notifications" { } } dynamic "statement" { - for_each = !var.standalone ? local.allowed_aws_principals_for_sns_subscribe : {} + for_each = var.standalone || var.cloudtrail_bucket_notifications_sns_arn != null ? {} : local.allowed_aws_principals_for_sns_subscribe content { sid = "AllowAWSPrincipalToSNSSubscribe${statement.key}" actions = ["sns:Subscribe"] effect = "Allow" - resources = [aws_sns_topic.bucket_notifications[0].arn] + resources = [try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn)] principals { type = "AWS" identifiers = [statement.value] @@ -77,9 +68,9 @@ data "aws_iam_policy_document" "sns_topic_policy_bucket_notifications" { } resource "aws_sns_topic_policy" "bucket_notifications" { - count = var.standalone ? 0 : 1 + count = var.standalone || var.cloudtrail_bucket_notifications_sns_arn != null ? 0 : 1 - arn = aws_sns_topic.bucket_notifications[0].arn + arn = try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn) policy = data.aws_iam_policy_document.sns_topic_policy_bucket_notifications[0].json } @@ -88,12 +79,12 @@ resource "aws_sns_topic_policy" "bucket_notifications" { # aws_s3_bucket_notification #-------------------------------------------------------------------------------------- resource "aws_s3_bucket_notification" "bucket_notification" { - count = var.standalone ? 0 : 1 + count = var.standalone || var.cloudtrail_bucket_notifications_sns_arn != null ? 0 : 1 - bucket = data.aws_s3_bucket.cloudtrail_bucket[0].id + bucket = var.cloudtrail_bucket_name topic { - topic_arn = aws_sns_topic.bucket_notifications[0].arn + topic_arn = try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn) events = ["s3:ObjectCreated:*"] filter_suffix = ".json.gz" } @@ -129,7 +120,7 @@ data "aws_iam_policy_document" "bucket_notifications" { condition { test = "ArnEquals" variable = "aws:SourceArn" - values = [aws_sns_topic.bucket_notifications[0].arn] + values = [try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn)] } } } @@ -147,7 +138,7 @@ resource "aws_sqs_queue_policy" "bucket_notifications" { resource "aws_sns_topic_subscription" "bucket_notifications" { count = var.standalone ? 0 : 1 - topic_arn = aws_sns_topic.bucket_notifications[0].arn + topic_arn = try(aws_sns_topic.bucket_notifications[0].arn, var.cloudtrail_bucket_notifications_sns_arn) protocol = "sqs" endpoint = aws_sqs_queue.bucket_notifications[0].arn } diff --git a/main.tf b/main.tf index d6c4b82..f4b1458 100644 --- a/main.tf +++ b/main.tf @@ -12,7 +12,7 @@ data "aws_iam_policy_document" "lambda_permissions" { content { sid = "S3AccessBucket" actions = ["s3:ListBucket"] - resources = [data.aws_s3_bucket.cloudtrail_bucket[0].arn] + resources = ["arn:aws:s3:::${var.cloudtrail_bucket_name}"] } } @@ -21,7 +21,7 @@ data "aws_iam_policy_document" "lambda_permissions" { content { sid = "S3AccessBucketObject" actions = ["s3:GetObject"] - resources = ["${data.aws_s3_bucket.cloudtrail_bucket[0].arn}/*"] + resources = ["arn:aws:s3:::${var.cloudtrail_bucket_name}/*"] } } diff --git a/variables.tf b/variables.tf index aaf192e..b8c65bf 100644 --- a/variables.tf +++ b/variables.tf @@ -89,6 +89,12 @@ variable "naming_prefix" { default = "clickops-notifier" } +variable "cloudtrail_bucket_notifications_sns_arn" { + type = string + description = "SNS topic ARN for bucket notifications. If not provided, a new SNS topic will be created along with the bucket notifications configuration." + default = null +} + variable "tags" { type = map(string) description = "Tags to add to resources in addition to the default_tags for the provider"