From f71cc6661603a6d6361f54bf5105da66ecbcb092 Mon Sep 17 00:00:00 2001 From: Jayakishore Roy Date: Tue, 31 Jan 2023 13:50:08 -0500 Subject: [PATCH 1/2] feat: enabling delivery status logging for config SNS topic Comply with SNS.2 in AWS Foundational Security Best Practices controls https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html#fsbp-sns-2 --- config_baselines.tf | 70 ++++++++++++++++++++++++++++ main.tf | 1 + modules/config-baseline/main.tf | 15 ++++++ modules/config-baseline/variables.tf | 13 +++++- variables.tf | 12 +++++ 5 files changed, 110 insertions(+), 1 deletion(-) 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/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. # -------------------------------------------------------------------------------------------------- From 5b47c45764d1fdb5cf2eb9e1d1ff397497be1f92 Mon Sep 17 00:00:00 2001 From: Jayakishore Roy Date: Tue, 31 Jan 2023 14:09:07 -0500 Subject: [PATCH 2/2] docs: updated readme with new variables --- README.md | 2 ++ modules/config-baseline/README.md | 2 ++ 2 files changed, 4 insertions(+) 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/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