From 2d47e39f973f7b2fc4ab5a3c9c18085aaa1244d1 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 29 Mar 2021 14:39:53 -0400 Subject: [PATCH 1/7] v1.8.1: add sns event setup for ses --- CHANGELOG.md | 4 +++ common/defaults.tf | 3 ++ common/version.tf | 2 +- ses-domain/README.md | 10 +++++++ ses-domain/main.tf | 33 ++++++++++++++++++--- ses-domain/policies.tf | 65 +++++++++++++++++++++++++++++++++++++++++ ses-domain/variables.tf | 17 +++++++++++ 7 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 ses-domain/policies.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 7973725..5f30ea9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,3 +55,7 @@ * v1.8.0 -- 20210329 - iam-account-settings created + +* v1.8.1 -- 20210329 + - ses-domain + - add code for setting up sns event notification for bounce, complaint diff --git a/common/defaults.tf b/common/defaults.tf index bc32b74..8d1ef16 100644 --- a/common/defaults.tf +++ b/common/defaults.tf @@ -14,6 +14,9 @@ locals { "us-west-1" = "027434742980" "us-west-2" = "797873946194" } + "ses" = { + "event_types" = ["bounce", "delivery", "complaint"] + } } } diff --git a/common/version.tf b/common/version.tf index c36b41b..1f44b67 100644 --- a/common/version.tf +++ b/common/version.tf @@ -1,3 +1,3 @@ locals { - _module_version = "1.8.0" + _module_version = "1.8.1" } diff --git a/ses-domain/README.md b/ses-domain/README.md index a40c021..094c0d9 100644 --- a/ses-domain/README.md +++ b/ses-domain/README.md @@ -45,6 +45,7 @@ module "ses" { ## once validated, get out of sandbox and set mail from address # enable_production = true # enable_mail_from = true + # enable_ses_events = true ## optional, changing this is not recommended # ses_domain_name = "123456789012.postal.census.gov" @@ -95,6 +96,7 @@ module "ses" { profile = var.profile enable_production = true enable_mail_from = true + enable_ses_events = true } ``` then run `tf-apply` @@ -171,10 +173,15 @@ No modules. | [aws_ses_domain_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) | resource | | [aws_ses_domain_identity_verification.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity_verification) | resource | | [aws_ses_domain_mail_from.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_mail_from) | resource | +| [aws_ses_identity_notification_topic.ses_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_identity_notification_topic) | resource | +| [aws_sns_topic.ses_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | +| [aws_sns_topic_policy.ses_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource | | [null_resource.this_output](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [null_resource.to_production](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | 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.ses_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_kms_alias.sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | | [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | | [external_external.ses_dns_txt](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external) | data source | @@ -186,6 +193,7 @@ No modules. | [account\_id](#input\_account\_id) | AWS Account ID (default will pull from current user) | `string` | `""` | no | | [enable\_mail\_from](#input\_enable\_mail\_from) | SES Enable set of Mail From domain ses\_mail\_from.DOMAIN | `bool` | `false` | no | | [enable\_production](#input\_enable\_production) | SES Enable calling of AWS CLI to move from sandbox to production | `bool` | `false` | no | +| [enable\_sns\_events](#input\_enable\_sns\_events) | SES Enable event notificaton to SNS for bounce, complaint, and/or delivery (specified by ses\_event\_notification\_types). | `bool` | `false` | no | | [override\_prefixes](#input\_override\_prefixes) | Override built-in prefixes by component (efs, s3, ebs, kms, role, policy, security-group). This should be used primarily for common infrastructure things | `map(string)` | `{}` | no | | [profile](#input\_profile) | AWS Config profile (required for calling the aws cli) | `string` | `""` | no | | [region](#input\_region) | AWS Region (default takes from current executing region) | `string` | `""` | no | @@ -193,7 +201,9 @@ No modules. | [ses\_base\_dkim\_domain\_name](#input\_ses\_base\_dkim\_domain\_name) | SES Base DKIM Domain Name | `string` | `"dkim.amazonses.com"` | no | | [ses\_base\_domain\_name](#input\_ses\_base\_domain\_name) | SES Base Domain Name | `string` | `"aws.mail.census.gov"` | no | | [ses\_domain\_name](#input\_ses\_domain\_name) | SES Fully Qualified Domain Name (default: {account\_id}.aws.mail.census.gov) | `string` | `""` | no | +| [ses\_event\_notification\_types](#input\_ses\_event\_notification\_types) | SNS Notification types for SNS. Valid values are bounce, complaint, and delivery. | `list(string)` |
[
"bounce",
"complaint"
]
| no | | [ses\_mail\_from](#input\_ses\_mail\_from) | SES mail from domain prepended to ses\_domain\_name. See enable\_mail\_from for enabling this. | `string` | `"bounce"` | no | +| [ses\_sns\_topic\_name](#input\_ses\_sns\_topic\_name) | SNS Topic name for event handling. The region name will be appended. | `string` | `"inf-ses-events"` | no | | [ses\_use\_case\_description](#input\_ses\_use\_case\_description) | SES use case description (for move to production) | `string` | `""` | no | | [ses\_website\_url](#input\_ses\_website\_url) | SES website URL (for move to production) | `string` | `"https://census.gov"` | no | | [tags](#input\_tags) | AWS Tags to apply to appropriate resources (S3, KMS). Do not include safeguard tags here, use the data\_safeguard field for such things. | `map(string)` | `{}` | no | diff --git a/ses-domain/main.tf b/ses-domain/main.tf index b3a97ef..6eb2b8c 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -46,6 +46,7 @@ * ## once validated, get out of sandbox and set mail from address * # enable_production = true * # enable_mail_from = true +* # enable_ses_events = true * * ## optional, changing this is not recommended * # ses_domain_name = "123456789012.postal.census.gov" @@ -96,6 +97,7 @@ * profile = var.profile * enable_production = true * enable_mail_from = true +* enable_ses_events = true * } * ``` * then run `tf-apply` @@ -156,10 +158,13 @@ locals { ses_available = local.account_environment == "ew" ? length(regexall("us-", local.region)) > 0 : length(regexall("gov-west", local.region)) > 0 - ses_domain = var.ses_domain_name != "" ? var.ses_domain_name : format("%v.%v", local.account_id, var.ses_base_domain_name) - ses_dns_txt_name = format("_amazonses.%v", aws_ses_domain_identity.this.domain) - ses_dns_ttl = 600 - ses_dns_value = aws_ses_domain_identity.this.verification_token + ses_domain = var.ses_domain_name != "" ? var.ses_domain_name : format("%v.%v", local.account_id, var.ses_base_domain_name) + ses_dns_txt_name = format("_amazonses.%v", aws_ses_domain_identity.this.domain) + ses_dns_ttl = 600 + ses_dns_value = aws_ses_domain_identity.this.verification_token + ses_sns_topic = format("%v-%v", var.ses_sns_topic, local.region) + ses_event_types = [for x in var.ses_event_notification_types : x if contains(lookup(local._defaults["ses"]["event_types"], []), x)] + enable_sns_events = var.enable_sns_events && length(local.ses_event_types) > 0 ses_output = templatefile("${path.module}/ses_dns.md.tpl", { domain = local.ses_domain @@ -241,3 +246,23 @@ resource "null_resource" "to_production" { } } } + +resource "aws_sns_topic" "ses_event" { + count = local.enable_sns_events ? 1 : 0 + name = local.ses_sns_topic + kms_master_key_id = "alias/aws/sns" +} + +resource "aws_sns_topic_policy" "ses_event" { + count = local.enable_sns_events ? 1 : 0 + arn = aws_sns_topic.ses_event.arn + policy = data.aws_iam_document_policy.ses_event.json +} + +resource "aws_ses_identity_notification_topic" "ses_event" { + for_each = toset(local.ses_event_types) + topic_arn = aws_sns_topic.ses_event.arn + notification_type = each.key + identity = aws_ses_domain_identity.this.domain + include_original_headers = true +} diff --git a/ses-domain/policies.tf b/ses-domain/policies.tf new file mode 100644 index 0000000..d980a28 --- /dev/null +++ b/ses-domain/policies.tf @@ -0,0 +1,65 @@ +data "aws_kms_alias" "sns" { + name = "alias/aws/sns" +} + +data "aws_iam_policy_document" "ses_event" { + statement { + effect = "Alow" + actions = [ + "kms:GenerateDataKey*", + "kms:Decrypt", + ] + resources = [aws_kms_alias.sns.arn] + principals { + type = "Service" + identifiers = ["ses.amazonaws.com"] + } + } + statement { + effect = "Alow" + actions = ["sns:Publish"] + resources = [aws_sns_topic.ses_event.arn] + principals { + type = "Service" + identifiers = ["ses.amazonaws.com"] + } + } +} + +# { +# "Statement": [{ +# "Effect": "Allow", +# "Action": [ +# "kms:GenerateDataKey", +# "kms:Decrypt" +# ], +# "Resource": "arn:aws:kms:us-east-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab" +# }, { +# "Effect": "Allow", +# "Action": [ +# "sns:Publish" +# ], +# "Resource": "arn:aws:sns:*:123456789012:MyTopic" +# }] +# } +# Enable compatibility between event sources from AWS services and encrypted topics +# Several AWS services publish events to Amazon SNS topics. To allow these event sources to work with encrypted topics, you must perform the following steps. +# +# Use a customer managed CMK. For more information, see Creating Keys in the AWS Key Management Service Developer Guide. +# +# To allow the AWS service to have the kms:GenerateDataKey* and kms:Decrypt permissions, add the following statement to the CMK policy. +# +# { +# "Statement": [{ +# "Effect": "Allow", +# "Principal": { +# "Service": "service.amazonaws.com" +# }, +# "Action": [ +# "kms:GenerateDataKey*", +# "kms:Decrypt" +# ], +# "Resource": "*" +# }] +# } +# diff --git a/ses-domain/variables.tf b/ses-domain/variables.tf index 60ebcc6..31977f2 100644 --- a/ses-domain/variables.tf +++ b/ses-domain/variables.tf @@ -46,6 +46,17 @@ variable "ses_mail_from" { default = "bounce" } +variable "ses_sns_topic_name" { + description = "SNS Topic name for event handling. The region name will be appended." + type = string + default = "inf-ses-events" +} + +variable "ses_event_notification_types" { + description = "SNS Notification types for SNS. Valid values are bounce, complaint, and delivery." + type = list(string) + default = ["bounce", "complaint"] +} variable "region" { description = "AWS Region (default takes from current executing region)" @@ -73,3 +84,9 @@ variable "enable_mail_from" { type = bool default = false } + +variable "enable_sns_events" { + description = "SES Enable event notificaton to SNS for bounce, complaint, and/or delivery (specified by ses_event_notification_types)." + type = bool + default = false +} From 2cf2009ae2d2575eb2274c6532c0d31ea5a84167 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 29 Mar 2021 14:42:22 -0400 Subject: [PATCH 2/7] fix --- ses-domain/README.md | 4 ++-- ses-domain/main.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ses-domain/README.md b/ses-domain/README.md index 094c0d9..991afcf 100644 --- a/ses-domain/README.md +++ b/ses-domain/README.md @@ -45,7 +45,7 @@ module "ses" { ## once validated, get out of sandbox and set mail from address # enable_production = true # enable_mail_from = true - # enable_ses_events = true + # enable_sns_events = true ## optional, changing this is not recommended # ses_domain_name = "123456789012.postal.census.gov" @@ -96,7 +96,7 @@ module "ses" { profile = var.profile enable_production = true enable_mail_from = true - enable_ses_events = true + enable_sns_events = true } ``` then run `tf-apply` diff --git a/ses-domain/main.tf b/ses-domain/main.tf index 6eb2b8c..7bd52fb 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -46,7 +46,7 @@ * ## once validated, get out of sandbox and set mail from address * # enable_production = true * # enable_mail_from = true -* # enable_ses_events = true +* # enable_sns_events = true * * ## optional, changing this is not recommended * # ses_domain_name = "123456789012.postal.census.gov" @@ -97,7 +97,7 @@ * profile = var.profile * enable_production = true * enable_mail_from = true -* enable_ses_events = true +* enable_sns_events = true * } * ``` * then run `tf-apply` From 09e2a7f633d8f5467ce503ca850d576ae9ff6165 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 29 Mar 2021 14:46:37 -0400 Subject: [PATCH 3/7] fix --- ses-domain/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ses-domain/main.tf b/ses-domain/main.tf index 7bd52fb..21f9312 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -162,7 +162,7 @@ locals { ses_dns_txt_name = format("_amazonses.%v", aws_ses_domain_identity.this.domain) ses_dns_ttl = 600 ses_dns_value = aws_ses_domain_identity.this.verification_token - ses_sns_topic = format("%v-%v", var.ses_sns_topic, local.region) + ses_sns_topic = format("%v-%v", var.ses_sns_topic_name, local.region) ses_event_types = [for x in var.ses_event_notification_types : x if contains(lookup(local._defaults["ses"]["event_types"], []), x)] enable_sns_events = var.enable_sns_events && length(local.ses_event_types) > 0 From def8d2c0093709644cda0080d185f0976817c206 Mon Sep 17 00:00:00 2001 From: badra001 Date: Mon, 29 Mar 2021 14:48:39 -0400 Subject: [PATCH 4/7] fix --- ses-domain/main.tf | 2 +- ses-domain/policies.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ses-domain/main.tf b/ses-domain/main.tf index 21f9312..652937c 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -261,7 +261,7 @@ resource "aws_sns_topic_policy" "ses_event" { resource "aws_ses_identity_notification_topic" "ses_event" { for_each = toset(local.ses_event_types) - topic_arn = aws_sns_topic.ses_event.arn + topic_arn = aws_sns_topic.ses_event[0].arn notification_type = each.key identity = aws_ses_domain_identity.this.domain include_original_headers = true diff --git a/ses-domain/policies.tf b/ses-domain/policies.tf index d980a28..a3f5b6d 100644 --- a/ses-domain/policies.tf +++ b/ses-domain/policies.tf @@ -18,7 +18,7 @@ data "aws_iam_policy_document" "ses_event" { statement { effect = "Alow" actions = ["sns:Publish"] - resources = [aws_sns_topic.ses_event.arn] + resources = [aws_sns_topic.ses_event[0].arn] principals { type = "Service" identifiers = ["ses.amazonaws.com"] From 521fd925e9a1176a952471377ac464bd4c2a49d0 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 30 Mar 2021 07:36:20 -0400 Subject: [PATCH 5/7] fix --- ses-domain/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ses-domain/main.tf b/ses-domain/main.tf index 652937c..ce7d9ca 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -256,7 +256,7 @@ resource "aws_sns_topic" "ses_event" { resource "aws_sns_topic_policy" "ses_event" { count = local.enable_sns_events ? 1 : 0 arn = aws_sns_topic.ses_event.arn - policy = data.aws_iam_document_policy.ses_event.json + policy = data.aws_iam_policy_document.ses_event.json } resource "aws_ses_identity_notification_topic" "ses_event" { From 0306a420de1ed2f605b70844edae38c1d55218df Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 31 Mar 2021 08:30:26 -0400 Subject: [PATCH 6/7] add data. to kms alias --- ses-domain/policies.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ses-domain/policies.tf b/ses-domain/policies.tf index a3f5b6d..bc43991 100644 --- a/ses-domain/policies.tf +++ b/ses-domain/policies.tf @@ -9,7 +9,7 @@ data "aws_iam_policy_document" "ses_event" { "kms:GenerateDataKey*", "kms:Decrypt", ] - resources = [aws_kms_alias.sns.arn] + resources = [data.aws_kms_alias.sns.arn] principals { type = "Service" identifiers = ["ses.amazonaws.com"] From b49326cacdbe2f8dfda8265c8b0bbf52b6cf1346 Mon Sep 17 00:00:00 2001 From: badra001 Date: Wed, 31 Mar 2021 08:32:52 -0400 Subject: [PATCH 7/7] fix --- ses-domain/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ses-domain/main.tf b/ses-domain/main.tf index ce7d9ca..97eb5f3 100644 --- a/ses-domain/main.tf +++ b/ses-domain/main.tf @@ -255,7 +255,7 @@ resource "aws_sns_topic" "ses_event" { resource "aws_sns_topic_policy" "ses_event" { count = local.enable_sns_events ? 1 : 0 - arn = aws_sns_topic.ses_event.arn + arn = aws_sns_topic.ses_event[0].arn policy = data.aws_iam_policy_document.ses_event.json }