diff --git a/README.md b/README.md
index 55b5c742..c1ae55ba 100644
--- a/README.md
+++ b/README.md
@@ -173,6 +173,8 @@ This module is composed of several submodules and each of which can be used inde
| [config\_s3\_bucket\_key\_prefix](#input\_config\_s3\_bucket\_key\_prefix) | The prefix used when writing AWS Config snapshots into the S3 bucket. | `string` | no |
| [config\_sns\_topic\_kms\_master\_key\_id](#input\_config\_sns\_topic\_kms\_master\_key\_id) | To enable SNS Topic encryption enter value with the ID of a custom master KMS key that is used for encryption | `string` | no |
| [config\_sns\_topic\_name](#input\_config\_sns\_topic\_name) | The name of the SNS Topic to be used to notify configuration changes. | `string` | no |
+| [config\_sns\_feedback\_iam\_role\_name](#input\_config\_sns\_feedback\_iam\_role\_name) | The name of the IAM Role which which SNS will use to log delivery status. | `string` | no |
+| [config\_sns\_feedback\_iam\_role\_policy\_name](#input\_config\_sns\_feedback\_iam\_role\_policy\_name) | The name of the IAM Role Policy which SNS will use to log delivery status. | `string` | no |
| [console\_signin\_failures\_enabled](#input\_console\_signin\_failures\_enabled) | The boolean flag whether the console\_signin\_failures alarm is enabled or not. No resources are created when set to false. | `bool` | no |
| [create\_password\_policy](#input\_create\_password\_policy) | Define if the password policy should be created. | `bool` | no |
| [create\_support\_role](#input\_create\_support\_role) | Define if the support role should be created. | `bool` | no |
diff --git a/config_baselines.tf b/config_baselines.tf
index 8e7278ea..6587b531 100644
--- a/config_baselines.tf
+++ b/config_baselines.tf
@@ -94,6 +94,59 @@ resource "aws_iam_role_policy_attachment" "recorder_read_policy" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AWS_ConfigRole"
}
+# --------------------------------------------------------------------------------------------------
+# Create an IAM Role for AWS SNS to log delivery status in CloudWatch Logs
+# References:
+# - https://docs.aws.amazon.com/sns/latest/dg/sns-topic-attributes.html#topics-attrib
+# - https://aws.amazon.com/premiumsupport/knowledge-center/monitor-sns-texts-cloudwatch/
+# --------------------------------------------------------------------------------------------------
+
+resource "aws_iam_role" "feedback" {
+ count = var.config_baseline_enabled ? 1 : 0
+
+ name = var.config_sns_feedback_iam_role_name
+ path = "/"
+ assume_role_policy = data.aws_iam_policy_document.sns_assume_role_policy[0].json
+}
+
+data "aws_iam_policy_document" "sns_assume_role_policy" {
+ count = var.config_baseline_enabled ? 1 : 0
+
+ statement {
+ effect = "Allow"
+ actions = ["sts:AssumeRole"]
+
+ principals {
+ type = "Service"
+ identifiers = ["sns.${data.aws_partition.current.dns_suffix}"]
+ }
+ }
+}
+
+resource "aws_iam_role_policy" "feedback_role_policy" {
+ count = var.config_baseline_enabled ? 1 : 0
+
+ name = var.config_sns_feedback_iam_role_policy_name
+ role = one(aws_iam_role.feedback[*].id)
+ policy = data.aws_iam_policy_document.feedback_role_policy[0].json
+}
+
+data "aws_iam_policy_document" "feedback_role_policy" {
+ count = var.config_baseline_enabled ? 1 : 0
+
+ statement {
+ effect = "Allow"
+ actions = [
+ "logs:CreateLogGroup",
+ "logs:CreateLogStream",
+ "logs:PutLogEvents",
+ "logs:PutMetricFilter",
+ "logs:PutRetentionPolicy"
+ ]
+ resources = ["*"]
+ }
+}
+
# --------------------------------------------------------------------------------------------------
# AWS Config Baseline
# Needs to be set up in each region.
@@ -115,6 +168,7 @@ module "config_baseline_ap-northeast-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-northeast-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -136,6 +190,7 @@ module "config_baseline_ap-northeast-2" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-northeast-2"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -157,6 +212,7 @@ module "config_baseline_ap-northeast-3" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-northeast-3"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -178,6 +234,7 @@ module "config_baseline_ap-south-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-south-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -199,6 +256,7 @@ module "config_baseline_ap-southeast-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-southeast-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -220,6 +278,7 @@ module "config_baseline_ap-southeast-2" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ap-southeast-2"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -241,6 +300,7 @@ module "config_baseline_ca-central-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "ca-central-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -262,6 +322,7 @@ module "config_baseline_eu-central-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "eu-central-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -283,6 +344,7 @@ module "config_baseline_eu-north-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "eu-north-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -304,6 +366,7 @@ module "config_baseline_eu-west-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "eu-west-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -325,6 +388,7 @@ module "config_baseline_eu-west-2" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "eu-west-2"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -346,6 +410,7 @@ module "config_baseline_eu-west-3" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "eu-west-3"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -367,6 +432,7 @@ module "config_baseline_sa-east-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "sa-east-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -388,6 +454,7 @@ module "config_baseline_us-east-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "us-east-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -409,6 +476,7 @@ module "config_baseline_us-east-2" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "us-east-2"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -430,6 +498,7 @@ module "config_baseline_us-west-1" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "us-west-1"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
@@ -451,6 +520,7 @@ module "config_baseline_us-west-2" {
sns_topic_name = var.config_sns_topic_name
sns_topic_kms_master_key_id = var.config_sns_topic_kms_master_key_id
include_global_resource_types = var.config_global_resources_all_regions ? true : var.region == "us-west-2"
+ sns_feedback_iam_role = one(aws_iam_role.feedback[*].arn)
tags = var.tags
diff --git a/main.tf b/main.tf
index 1b807f35..7d6adcf3 100644
--- a/main.tf
+++ b/main.tf
@@ -25,6 +25,7 @@ terraform {
}
data "aws_caller_identity" "current" {}
+data "aws_partition" "current" {}
locals {
is_individual_account = var.account_type == "individual"
diff --git a/modules/config-baseline/README.md b/modules/config-baseline/README.md
index caf34f2d..8908c4da 100644
--- a/modules/config-baseline/README.md
+++ b/modules/config-baseline/README.md
@@ -29,6 +29,8 @@ Enable AWS Config in all regions to automatically take configuration snapshots.
| [s3\_key\_prefix](#input\_s3\_key\_prefix) | The prefix for the specified S3 bucket. | `string` | no |
| [sns\_topic\_kms\_master\_key\_id](#input\_sns\_topic\_kms\_master\_key\_id) | To enable SNS Topic encryption enter value with the ID of a custom master KMS key that is used for encryption | `string` | no |
| [sns\_topic\_name](#input\_sns\_topic\_name) | The name of the SNS Topic to be used to notify configuration changes. | `string` | no |
+| [sns\_feedback\_iam\_role](#input\_sns\_feedback\_iam\_role) | The ARN of the IAM Role which SNS will use to log delivery status. | `string` | yes |
+| [sns\_feedback\_sample\_rate](#input\_sns\_feedback\_sample\_rate) | Percentage of messages to sample for delivery status logging. | `number` | no |
| [tags](#input\_tags) | Specifies object tags key and value. This applies to all resources created by this module. | `map(string)` | no |
## Outputs
diff --git a/modules/config-baseline/main.tf b/modules/config-baseline/main.tf
index f8c92248..eaa6bab4 100644
--- a/modules/config-baseline/main.tf
+++ b/modules/config-baseline/main.tf
@@ -8,6 +8,21 @@ data "aws_region" "current" {}
resource "aws_sns_topic" "config" {
name = var.sns_topic_name
kms_master_key_id = var.sns_topic_kms_master_key_id
+ application_failure_feedback_role_arn = var.sns_feedback_iam_role
+ application_success_feedback_role_arn = var.sns_feedback_iam_role
+ application_success_feedback_sample_rate = var.sns_feedback_sample_rate
+ lambda_failure_feedback_role_arn = var.sns_feedback_iam_role
+ lambda_success_feedback_role_arn = var.sns_feedback_iam_role
+ lambda_success_feedback_sample_rate = var.sns_feedback_sample_rate
+ http_failure_feedback_role_arn = var.sns_feedback_iam_role
+ http_success_feedback_role_arn = var.sns_feedback_iam_role
+ http_success_feedback_sample_rate = var.sns_feedback_sample_rate
+ sqs_failure_feedback_role_arn = var.sns_feedback_iam_role
+ sqs_success_feedback_role_arn = var.sns_feedback_iam_role
+ sqs_success_feedback_sample_rate = var.sns_feedback_sample_rate
+ firehose_failure_feedback_role_arn = var.sns_feedback_iam_role
+ firehose_success_feedback_role_arn = var.sns_feedback_iam_role
+ firehose_success_feedback_sample_rate = var.sns_feedback_sample_rate
tags = var.tags
}
diff --git a/modules/config-baseline/variables.tf b/modules/config-baseline/variables.tf
index 07b33a57..4c17daae 100644
--- a/modules/config-baseline/variables.tf
+++ b/modules/config-baseline/variables.tf
@@ -53,7 +53,18 @@ variable "include_global_resource_types" {
variable "tags" {
description = "Specifies object tags key and value. This applies to all resources created by this module."
type = map(string)
- default = {
+ default = {
"Terraform" = "true"
}
}
+
+variable "sns_feedback_iam_role" {
+ type = string
+ description = "The ARN of the IAM Role which SNS will use to log delivery status"
+}
+
+variable "sns_feedback_sample_rate" {
+ type = number
+ description = "Percentage of messages to sample for delivery status logging"
+ default = 100
+}
diff --git a/variables.tf b/variables.tf
index a942f3c9..ee2734e5 100644
--- a/variables.tf
+++ b/variables.tf
@@ -319,6 +319,18 @@ variable "config_global_resources_all_regions" {
default = false
}
+variable "config_sns_feedback_iam_role_name" {
+ description = "The name of the IAM Role which which SNS will use to log delivery status"
+ type = string
+ default = "Config-Feedback"
+}
+
+variable "config_sns_feedback_iam_role_policy_name" {
+ description = "The name of the IAM Role Policy which SNS will use to log delivery status"
+ type = string
+ default = "Config-Feedback-Policy"
+}
+
# --------------------------------------------------------------------------------------------------
# Variables for cloudtrail-baseline module.
# --------------------------------------------------------------------------------------------------