diff --git a/cloudtrail/README.md b/cloudtrail/README.md index 200a961..d25d4cf 100644 --- a/cloudtrail/README.md +++ b/cloudtrail/README.md @@ -153,9 +153,14 @@ No modules. | [aws_s3_bucket_server_side_encryption_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | | [aws_sns_topic.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | | [aws_sns_topic_policy.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | +| [aws_sns_topic_subscription.additional_cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | | [aws_sns_topic_subscription.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource | +| [aws_sqs_queue.additional_cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.additional_cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue.cloudtrail](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue_policy.additional_cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [aws_sqs_queue_policy.additional_cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [aws_sqs_queue_policy.cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [aws_sqs_queue_policy.cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [null_resource.policy_delay](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | @@ -163,6 +168,8 @@ No modules. | [random_uuid.splunk_cloudtrail](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/uuid) | resource | | [aws_arn.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/arn) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.additional_cloudtrail_deadletter](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.additional_cloudtrail_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudtrail_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -182,6 +189,7 @@ No modules. | [access\_log\_bucket\_prefix](#input\_access\_log\_bucket\_prefix) | Server Access Log bucket prefix, to which the Object Logging bucket name will be appended to make the target\_prefix | `string` | `"s3"` | no | | [account\_alias](#input\_account\_alias) | AWS Account Alias | `string` | `""` | no | | [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no | +| [additional\_sqs\_names](#input\_additional\_sqs\_names) | List of additional SQS queues to create and subscribe to the SNS topic (if enabled) | `list(string)` | `[]` | no | | [cloudtrail\_bucket\_prefix](#input\_cloudtrail\_bucket\_prefix) | Access log bucket prefix, to which the bucket name will be appended to make the target\_prefix | `string` | `"cloudtrail"` | no | | [component\_tags](#input\_component\_tags) | Additional tags for Components (s3, kms, ddb) | `map(map(string))` |
{
"ddb": {},
"kms": {},
"s3": {}
}
| no | | [enable\_organization](#input\_enable\_organization) | Enable CloudTrail as an organization trail. This will only work in the organization master account | `bool` | `false` | no | @@ -196,4 +204,10 @@ No modules. ## Outputs -No outputs. +| Name | Description | +|------|-------------| +| [additional\_sqs\_arn](#output\_additional\_sqs\_arn) | Additional SQS ARNs (main, deadletter) | +| [s3\_bucket\_arn](#output\_s3\_bucket\_arn) | Created S3 Bucket ARN | +| [s3\_bucket\_id](#output\_s3\_bucket\_id) | Created S3 Bucket ID | +| [sns\_arn](#output\_sns\_arn) | SNS ARN | +| [sqs\_arn](#output\_sqs\_arn) | Main SQS ARNs (main, deadletter) | diff --git a/cloudtrail/additional-sqs.tf b/cloudtrail/additional-sqs.tf new file mode 100644 index 0000000..d66d6c9 --- /dev/null +++ b/cloudtrail/additional-sqs.tf @@ -0,0 +1,103 @@ +locals { + additional_sqs_names = var.enable_sqs ? toset(var.additional_sqs_names) : {} +} + +resource "aws_sqs_queue" "additional_cloudtrail_deadletter" { + for_each = local.additional_sqs_names + name = format("%v-deadletter", each.key) + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = lookup(local._defaults["sqs_deadletter"], "message_retention_seconds", 1 * 86400) + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 3600 + + kms_master_key_id = data.aws_kms_key.incoming_key.id + kms_data_key_reuse_period_seconds = 300 + + tags = merge( + local.base_tags, + var.tags, + tomap({ Name = format("%v-deadletter", each.key) }), + ) +} + +resource "aws_sqs_queue_policy" "additional_cloudtrail_deadletter" { + for_each = local.additional_sqs_names + queue_url = var.enable_sqs ? aws_sqs_queue.additional_cloudtrail_deadletter[each.key].id : null + policy = data.aws_iam_policy_document.additional_cloudtrail_deadletter.json +} + +data "aws_iam_policy_document" "additional_cloudtrail_deadletter" { + for_each = local.additional_sqs_names + statement { + sid = "AllowSNSSendMessage" + effect = "Allow" + actions = ["sqs:SendMessage"] + resources = [var.enable_sqs ? aws_sqs_queue.additional_cloudtrail_deadletter[each.key].arn : ""] + principals { + type = "AWS" + identifiers = ["*"] + } + condition { + test = "ArnEquals" + variable = "aws:SourceArn" + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] + } + } +} + +resource "aws_sqs_queue" "additional_cloudtrail" { + for_each = local.additional_sqs_names + name = each.key + delay_seconds = 0 + max_message_size = 262144 + message_retention_seconds = lookup(local._defaults["sqs_deadletter"], "message_retention_seconds", 7 * 86400) + receive_wait_time_seconds = 15 + visibility_timeout_seconds = 7200 + + redrive_policy = jsonencode({ + deadLetterTargetArn = var.enable_sqs ? aws_sqs_queue.additional_cloudtrail_deadletter[each.key].arn : null + maxReceiveCount = 100 + }) + + kms_master_key_id = data.aws_kms_key.incoming_key.id + kms_data_key_reuse_period_seconds = 300 + + tags = merge( + local.base_tags, + var.tags, + tomap({ Name = each.key }), + ) +} + +resource "aws_sqs_queue_policy" "additional_cloudtrail_sqs" { + for_each = local.additional_sqs_names + queue_url = var.enable_sqs ? aws_sqs_queue.additional_cloudtrail[each.key].id : null + policy = data.aws_iam_policy_document.additional_cloudtrail_sqs.json +} + +data "aws_iam_policy_document" "additional_cloudtrail_sqs" { + for_each = local.additional_sqs_names + statement { + sid = "AllowSNSSendMessage" + effect = "Allow" + actions = ["sqs:SendMessage"] + resources = [var.enable_sqs ? aws_sqs_queue.additional_cloudtrail[each.key].arn : ""] + principals { + type = "AWS" + identifiers = ["*"] + } + condition { + test = "ArnEquals" + variable = "aws:SourceArn" + values = [var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : ""] + } + } +} + +resource "aws_sns_topic_subscription" "additional_cloudtrail_sqs" { + for_each = var.enable_sns ? local.additional_sqs_names : {} + protocol = "sqs" + topic_arn = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null + endpoint = var.enable_sqs ? aws_sqs_queue.additional_cloudtrail[each.key].arn : null +} diff --git a/cloudtrail/outputs.tf b/cloudtrail/outputs.tf new file mode 100644 index 0000000..980524b --- /dev/null +++ b/cloudtrail/outputs.tf @@ -0,0 +1,31 @@ +output "s3_bucket_arn" { + description = "Created S3 Bucket ARN" + value = aws_s3_bucket.this.arn +} + +output "s3_bucket_id" { + description = "Created S3 Bucket ID" + value = aws_s3_bucket.this.id +} + +output "sqs_arn" { + description = "Main SQS ARNs (main, deadletter)" + value = { + "main" = aws_sqs_queue.cloudtrail.arn + "deadletter" = aws_sqs_queue.cloudtrail_deadletter.arn + } +} + +output "additional_sqs_arn" { + description = "Additional SQS ARNs (main, deadletter)" + value = { for k in local.additional_sqs_names : k => { + "name" = k + "main" = lookup(aws_sqs_queue.additional_cloudtrail, k, { arn : null }).arn + "deadletter" = lookup(aws_sqs_queue.additional_cloudtrail_deadletter, k, { arn : null }).arn + } } +} + +output "sns_arn" { + description = "SNS ARN" + value = var.enable_sns ? aws_sns_topic.cloudtrail[0].arn : null +} diff --git a/cloudtrail/variables.tf b/cloudtrail/variables.tf index 65a5a1e..d317f0a 100644 --- a/cloudtrail/variables.tf +++ b/cloudtrail/variables.tf @@ -83,3 +83,9 @@ variable "organization_id" { type = string default = "" } + +variable "additional_sqs_names" { + description = "List of additional SQS queues to create and subscribe to the SNS topic (if enabled)" + type = list(string) + default = [] +}