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 = []
+}