diff --git a/infrastructure/dns_email_auth.tf b/infrastructure/dns_email_auth.tf
deleted file mode 100644
index 126bfbc1..00000000
--- a/infrastructure/dns_email_auth.tf
+++ /dev/null
@@ -1,9 +0,0 @@
-# resource "aws_route53_record" "dmarc" {
-# count = local.is_shared_workspace ? 1 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = "_dmarc.${var.domain}"
-# type = "TXT"
-# ttl = 300
-#
-# records = ["v=DMARC1; p=none; adkim=s; aspf=s"]
-# }
diff --git a/infrastructure/iam.tf b/infrastructure/iam.tf
index 71f445cf..b9d54aa6 100644
--- a/infrastructure/iam.tf
+++ b/infrastructure/iam.tf
@@ -355,37 +355,37 @@ resource "aws_iam_policy" "s3_document_data_policy_post_document_review_lambda"
})
}
-# data "aws_iam_policy_document" "reporting_ses" {
-# statement {
-# sid = "SESAccess"
-# effect = "Allow"
-#
-# actions = [
-# "ses:SendEmail",
-# "ses:SendRawEmail"
-# ]
-#
-# resources = [
-# "arn:aws:ses:${var.region}:${data.aws_caller_identity.current.account_id}:identity/*",
-# "arn:aws:ses:${var.region}:${data.aws_caller_identity.current.account_id}:configuration-set/${aws_ses_configuration_set.reporting.name}"
-# ]
-#
-# condition {
-# test = "StringEquals"
-# variable = "ses:FromAddress"
-# values = [local.reporting_ses_from_address_value]
-# }
-# }
-# }
-#
-# data "aws_iam_policy_document" "ses_feedback_s3_put" {
-# statement {
-# effect = "Allow"
-# actions = [
-# "s3:PutObject"
-# ]
-# resources = [
-# "${module.ses-feedback-store.bucket_arn}/ses-feedback/*"
-# ]
-# }
-# }
+data "aws_iam_policy_document" "reporting_ses" {
+ statement {
+ sid = "SESAccess"
+ effect = "Allow"
+
+ actions = [
+ "ses:SendEmail",
+ "ses:SendRawEmail"
+ ]
+
+ resources = [
+ "arn:aws:ses:${var.region}:${data.aws_caller_identity.current.account_id}:identity/*",
+ "arn:aws:ses:${var.region}:${data.aws_caller_identity.current.account_id}:configuration-set/${aws_ses_configuration_set.reporting.name}"
+ ]
+
+ condition {
+ test = "StringEquals"
+ variable = "ses:FromAddress"
+ values = [module.ses.report_email_address]
+ }
+ }
+}
+
+data "aws_iam_policy_document" "ses_feedback_s3_put" {
+ statement {
+ effect = "Allow"
+ actions = [
+ "s3:PutObject"
+ ]
+ resources = [
+ "${module.ses-feedback-store.bucket_arn}/ses-feedback/*"
+ ]
+ }
+}
diff --git a/infrastructure/kms_sns.tf b/infrastructure/kms_sns.tf
index f1296348..aec8efb1 100644
--- a/infrastructure/kms_sns.tf
+++ b/infrastructure/kms_sns.tf
@@ -4,7 +4,6 @@ module "sns_encryption_key" {
kms_key_description = "Custom KMS Key to enable server side encryption for sns subscriptions"
environment = var.environment
owner = var.owner
- # service_identifiers = ["sns.amazonaws.com", "cloudwatch.amazonaws.com", "ses.amazonaws.com"]
- service_identifiers = ["sns.amazonaws.com", "cloudwatch.amazonaws.com"]
+ service_identifiers = ["sns.amazonaws.com", "cloudwatch.amazonaws.com", "ses.amazonaws.com"]
kms_deletion_window = var.kms_deletion_window
}
diff --git a/infrastructure/lambda-report-distribution.tf b/infrastructure/lambda-report-distribution.tf
index 7ab0e5c3..4134dfe9 100644
--- a/infrastructure/lambda-report-distribution.tf
+++ b/infrastructure/lambda-report-distribution.tf
@@ -1,30 +1,30 @@
-# module "report-distribution-lambda" {
-# source = "./modules/lambda"
-# name = "ReportDistribution"
-# handler = "handlers.report_distribution_handler.lambda_handler"
-# lambda_timeout = 300
-#
-# iam_role_policy_documents = [
-# module.ndr-report-store.s3_read_policy_document,
-# module.bulk_upload_contact_lookup_table.dynamodb_read_policy_document,
-# data.aws_iam_policy_document.reporting_ses.json,
-# data.aws_iam_policy.aws_lambda_vpc_access_execution_role.policy,
-# ]
-#
-# lambda_environment_variables = {
-# APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
-# APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
-# APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
-# WORKSPACE = terraform.workspace
-#
-# REPORT_BUCKET_NAME = module.ndr-report-store.bucket_id
-# CONTACT_TABLE_NAME = module.bulk_upload_contact_lookup_table.table_name
-#
-# PRM_MAILBOX_EMAIL = data.aws_ssm_parameter.prm_mailbox_email.value
-# SES_FROM_ADDRESS = local.reporting_ses_from_address_value
-# SES_CONFIGURATION_SET = aws_ses_configuration_set.reporting.name
-# }
-#
-# is_gateway_integration_needed = false
-# is_invoked_from_gateway = false
-# }
+module "report-distribution-lambda" {
+ source = "./modules/lambda"
+ name = "ReportDistribution"
+ handler = "handlers.report_distribution_handler.lambda_handler"
+ lambda_timeout = 300
+
+ iam_role_policy_documents = [
+ module.ndr-report-store.s3_read_policy_document,
+ module.bulk_upload_contact_lookup_table.dynamodb_read_policy_document,
+ data.aws_iam_policy_document.reporting_ses.json,
+ data.aws_iam_policy.aws_lambda_vpc_access_execution_role.policy,
+ ]
+
+ lambda_environment_variables = {
+ APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
+ APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
+ APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
+ WORKSPACE = terraform.workspace
+
+ REPORT_BUCKET_NAME = module.ndr-report-store.bucket_id
+ CONTACT_TABLE_NAME = module.bulk_upload_contact_lookup_table.table_name
+
+ PRM_MAILBOX_EMAIL = data.aws_ssm_parameter.prm_mailbox_email.value
+ SES_FROM_ADDRESS = module.ses.report_email_address
+ SES_CONFIGURATION_SET = aws_ses_configuration_set.reporting.name
+ }
+
+ is_gateway_integration_needed = false
+ is_invoked_from_gateway = false
+}
diff --git a/infrastructure/lambda-send-feedback.tf b/infrastructure/lambda-send-feedback.tf
index 43f16c48..3a46ef96 100644
--- a/infrastructure/lambda-send-feedback.tf
+++ b/infrastructure/lambda-send-feedback.tf
@@ -105,7 +105,7 @@ module "send-feedback-lambda" {
depends_on = [
aws_api_gateway_rest_api.ndr_doc_store_api,
module.send-feedback-gateway,
- module.ndr-feedback-mailbox,
+ module.ses,
module.ndr-app-config
]
}
diff --git a/infrastructure/lambda-ses-feedback-monitor.tf b/infrastructure/lambda-ses-feedback-monitor.tf
index 8ec7b88a..bb340f20 100644
--- a/infrastructure/lambda-ses-feedback-monitor.tf
+++ b/infrastructure/lambda-ses-feedback-monitor.tf
@@ -1,32 +1,28 @@
-# module "ses-feedback-monitor-lambda" {
-# source = "./modules/lambda"
-# name = "SesFeedbackMonitor"
-# handler = "handlers.ses_feedback_monitor_handler.lambda_handler"
-# lambda_timeout = 60
-#
-# iam_role_policy_documents = [
-# data.aws_iam_policy_document.ses_feedback_s3_put.json,
-# data.aws_iam_policy_document.reporting_ses.json,
-# data.aws_iam_policy.aws_lambda_vpc_access_execution_role.policy,
-# ]
-#
-# lambda_environment_variables = {
-# APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
-# APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
-# APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
-# WORKSPACE = terraform.workspace
-#
-# SES_FEEDBACK_BUCKET_NAME = module.ses-feedback-store.bucket_id
-# SES_FEEDBACK_PREFIX = "ses-feedback/"
-# PRM_MAILBOX_EMAIL = data.aws_ssm_parameter.prm_mailbox_email.value
-# SES_FROM_ADDRESS = local.reporting_ses_from_address_value
-# ALERT_ON_EVENT_TYPES = "BOUNCE,REJECT"
-# }
-#
-# is_gateway_integration_needed = false
-# is_invoked_from_gateway = false
-#
-# depends_on = [
-# module.ses-feedback-store
-# ]
-# }
+module "ses-feedback-monitor-lambda" {
+ source = "./modules/lambda"
+ name = "SesFeedbackMonitor"
+ handler = "handlers.ses_feedback_monitor_handler.lambda_handler"
+ lambda_timeout = 60
+
+ iam_role_policy_documents = [
+ data.aws_iam_policy_document.ses_feedback_s3_put.json,
+ data.aws_iam_policy_document.reporting_ses.json,
+ data.aws_iam_policy.aws_lambda_vpc_access_execution_role.policy,
+ ]
+
+ lambda_environment_variables = {
+ APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id
+ APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id
+ APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id
+ WORKSPACE = terraform.workspace
+
+ SES_FEEDBACK_BUCKET_NAME = module.ses-feedback-store.bucket_id
+ SES_FEEDBACK_PREFIX = "ses-feedback/"
+ PRM_MAILBOX_EMAIL = data.aws_ssm_parameter.prm_mailbox_email.value
+ SES_FROM_ADDRESS = module.ses.report_email_address
+ ALERT_ON_EVENT_TYPES = "BOUNCE,REJECT"
+ }
+
+ is_gateway_integration_needed = false
+ is_invoked_from_gateway = false
+}
diff --git a/infrastructure/modules/ses/README.md b/infrastructure/modules/ses/README.md
index c2e1478f..44717710 100644
--- a/infrastructure/modules/ses/README.md
+++ b/infrastructure/modules/ses/README.md
@@ -42,21 +42,26 @@ module "ses_identity" {
| Name | Type |
|------|------|
+| [aws_route53_record.dmarc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_route53_record.ndr_ses_dkim_record](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
+| [aws_route53_record.ses_mail_from_mx](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
+| [aws_route53_record.ses_mail_from_spf](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource |
| [aws_ses_domain_dkim.ndr_dkim](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_dkim) | resource |
| [aws_ses_domain_identity.ndr_ses](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity) | resource |
| [aws_ses_domain_identity_verification.ndr_ses_domain_verification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_identity_verification) | resource |
+| [aws_ses_domain_mail_from.reporting](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ses_domain_mail_from) | resource |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| [domain](#input\_domain) | The root domain name to be registered with SES and used for verification. | `string` | n/a | yes |
-| [domain\_prefix](#input\_domain\_prefix) | The subdomain or prefix used to construct the full SES identity domain. | `string` | n/a | yes |
-| [enable](#input\_enable) | Whether to enable the creation of SES identity, DKIM, and DNS records. | `bool` | n/a | yes |
+| [is\_sandbox](#input\_is\_sandbox) | Whether the workspace being created is a sandbox. | `bool` | n/a | yes |
| [zone\_id](#input\_zone\_id) | The Route53 hosted zone ID where DNS verification records will be created. | `string` | n/a | yes |
## Outputs
-No outputs.
+| Name | Description |
+|------|-------------|
+| [report\_email\_address](#output\_report\_email\_address) | n/a |
diff --git a/infrastructure/modules/ses/main.tf b/infrastructure/modules/ses/main.tf
index 73df60e2..00216014 100644
--- a/infrastructure/modules/ses/main.tf
+++ b/infrastructure/modules/ses/main.tf
@@ -1,29 +1,65 @@
resource "aws_ses_domain_identity" "ndr_ses" {
- domain = var.domain
- count = var.enable ? 1 : 0
+ domain = var.is_sandbox ? "${terraform.workspace}.dev.${var.domain}" : "${terraform.workspace}.${var.domain}"
}
resource "aws_ses_domain_dkim" "ndr_dkim" {
- domain = aws_ses_domain_identity.ndr_ses[0].domain
+ domain = aws_ses_domain_identity.ndr_ses.domain
- count = var.enable ? 1 : 0
- depends_on = [aws_ses_domain_identity.ndr_ses[0]]
+ depends_on = [aws_ses_domain_identity.ndr_ses]
}
resource "aws_route53_record" "ndr_ses_dkim_record" {
+ count = 3
+
zone_id = var.zone_id
- name = "${aws_ses_domain_dkim.ndr_dkim[0].dkim_tokens[count.index]}._domainkey.${var.domain_prefix}"
+ name = var.is_sandbox ? "${aws_ses_domain_dkim.ndr_dkim.dkim_tokens[count.index]}._domainkey.${terraform.workspace}.dev" : "${aws_ses_domain_dkim.ndr_dkim.dkim_tokens[count.index]}._domainkey.${terraform.workspace}"
type = "CNAME"
ttl = 1800
- records = ["${aws_ses_domain_dkim.ndr_dkim[0].dkim_tokens[count.index]}.dkim.amazonses.com"]
+ records = ["${aws_ses_domain_dkim.ndr_dkim.dkim_tokens[count.index]}.dkim.amazonses.com"]
- count = var.enable ? 3 : 0
- depends_on = [aws_ses_domain_dkim.ndr_dkim[0]]
+ depends_on = [aws_ses_domain_dkim.ndr_dkim]
}
resource "aws_ses_domain_identity_verification" "ndr_ses_domain_verification" {
- domain = aws_ses_domain_identity.ndr_ses[0].domain
+ domain = aws_ses_domain_identity.ndr_ses.domain
+
+ depends_on = [aws_route53_record.ndr_ses_dkim_record]
+}
+
+resource "aws_ses_domain_mail_from" "reporting" {
+ domain = aws_ses_domain_identity.ndr_ses.domain
+ mail_from_domain = "mail.${aws_ses_domain_identity.ndr_ses.domain}"
+
+ behavior_on_mx_failure = "UseDefaultValue"
+}
+
+resource "aws_route53_record" "ses_mail_from_mx" {
+ zone_id = var.zone_id
+ name = "mail.${aws_ses_domain_identity.ndr_ses.domain}"
+ type = "MX"
+ ttl = 600
+
+ records = [
+ "10 feedback-smtp.eu-west-2.amazonses.com"
+ ]
+}
+
+resource "aws_route53_record" "ses_mail_from_spf" {
+ zone_id = var.zone_id
+ name = "mail.${aws_ses_domain_identity.ndr_ses.domain}"
+ type = "TXT"
+ ttl = 600
+
+ records = [
+ "v=spf1 include:amazonses.com -all"
+ ]
+}
+
+resource "aws_route53_record" "dmarc" {
+ zone_id = var.zone_id
+ name = "_dmarc.${aws_ses_domain_identity.ndr_ses.domain}"
+ type = "TXT"
+ ttl = 300
- count = var.enable ? 1 : 0
- depends_on = [aws_route53_record.ndr_ses_dkim_record[0]]
+ records = ["v=DMARC1; p=none; adkim=s; aspf=s"]
}
diff --git a/infrastructure/modules/ses/moved-1.6.15.tf b/infrastructure/modules/ses/moved-1.6.15.tf
new file mode 100644
index 00000000..07792817
--- /dev/null
+++ b/infrastructure/modules/ses/moved-1.6.15.tf
@@ -0,0 +1,14 @@
+moved {
+ from = aws_ses_domain_identity.ndr_ses[0]
+ to = aws_ses_domain_identity.ndr_ses
+}
+
+moved {
+ from = aws_ses_domain_dkim.ndr_dkim[0]
+ to = aws_ses_domain_dkim.ndr_dkim
+}
+
+moved {
+ from = aws_ses_domain_identity_verification.ndr_ses_domain_verification[0]
+ to = aws_ses_domain_identity_verification.ndr_ses_domain_verification
+}
diff --git a/infrastructure/modules/ses/output.tf b/infrastructure/modules/ses/output.tf
new file mode 100644
index 00000000..c2193880
--- /dev/null
+++ b/infrastructure/modules/ses/output.tf
@@ -0,0 +1,3 @@
+output "report_email_address" {
+ value = "ndr-reports@${aws_ses_domain_identity.ndr_ses.domain}"
+}
diff --git a/infrastructure/modules/ses/variable.tf b/infrastructure/modules/ses/variable.tf
index c60bc911..8234cebe 100644
--- a/infrastructure/modules/ses/variable.tf
+++ b/infrastructure/modules/ses/variable.tf
@@ -1,8 +1,3 @@
-variable "domain_prefix" {
- description = "The subdomain or prefix used to construct the full SES identity domain."
- type = string
-}
-
variable "domain" {
description = "The root domain name to be registered with SES and used for verification."
type = string
@@ -13,7 +8,7 @@ variable "zone_id" {
type = string
}
-variable "enable" {
- description = "Whether to enable the creation of SES identity, DKIM, and DNS records."
+variable "is_sandbox" {
+ description = "Whether the workspace being created is a sandbox."
type = bool
}
diff --git a/infrastructure/modules/sns/README.md b/infrastructure/modules/sns/README.md
index 226ce239..9f2c4d9e 100644
--- a/infrastructure/modules/sns/README.md
+++ b/infrastructure/modules/sns/README.md
@@ -79,8 +79,10 @@ module "sns_topic" {
| Name | Type |
|------|------|
| [aws_sns_topic.sns_topic](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
+| [aws_sns_topic_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_policy) | resource |
| [aws_sns_topic_subscription.sns_subscription_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
| [aws_sns_topic_subscription.sns_subscription_single](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic_subscription) | resource |
+| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
## Inputs
@@ -89,6 +91,7 @@ module "sns_topic" {
| [delivery\_policy](#input\_delivery\_policy) | Attach delivery or IAM policy. (Legacy name; used as topic policy JSON in this module.) | `string` | n/a | yes |
| [enable\_deduplication](#input\_enable\_deduplication) | Prevent content based duplication in notification queue. | `bool` | `false` | no |
| [enable\_fifo](#input\_enable\_fifo) | Attach first in first out policy to notification queue. | `bool` | `false` | no |
+| [enable\_ses\_publish](#input\_enable\_ses\_publish) | If true, module appends a statement allowing ses.amazonaws.com to SNS:Publish to this topic. | `bool` | `false` | no |
| [is\_topic\_endpoint\_list](#input\_is\_topic\_endpoint\_list) | Whether to use the topic\_endpoint\_list instead of a single topic\_endpoint. | `bool` | `false` | no |
| [raw\_message\_delivery](#input\_raw\_message\_delivery) | Whether to enable raw message delivery for the SNS subscription. | `bool` | `false` | no |
| [sns\_encryption\_key\_id](#input\_sns\_encryption\_key\_id) | The ARN (or ID) of the KMS key used for encrypting the SNS topic. | `string` | n/a | yes |
@@ -96,6 +99,7 @@ module "sns_topic" {
| [topic\_endpoint](#input\_topic\_endpoint) | A single endpoint (e.g., SQS queue or Lambda function ARN) to subscribe to the topic. | `any` | `null` | no |
| [topic\_endpoint\_list](#input\_topic\_endpoint\_list) | A list of endpoints (e.g., SQS ARNs) to subscribe to the topic. | `any` | `[]` | no |
| [topic\_name](#input\_topic\_name) | Name of the SNS topic. | `string` | n/a | yes |
+| [topic\_policy\_json](#input\_topic\_policy\_json) | Optional SNS topic access policy JSON. If set, it overrides delivery\_policy. | `string` | `null` | no |
| [topic\_protocol](#input\_topic\_protocol) | The protocol to use for the subscription (e.g., 'sqs', 'lambda'). | `string` | n/a | yes |
## Outputs
diff --git a/infrastructure/modules/sns/main.tf b/infrastructure/modules/sns/main.tf
index 5fac11a7..a1b51ae6 100644
--- a/infrastructure/modules/sns/main.tf
+++ b/infrastructure/modules/sns/main.tf
@@ -1,49 +1,50 @@
-# locals {
-# base_topic_policy_json = var.topic_policy_json != null ? var.topic_policy_json : var.delivery_policy
-# base_topic_policy_obj = jsondecode(local.base_topic_policy_json)
-# normalized_statements = [
-# for s in try(local.base_topic_policy_obj["Statement"], []) : merge(
-# s,
-# {
-# Resource = (
-# try(s["Resource"], null) == "*" || try(s["Resource"], null) == null
-# ? aws_sns_topic.sns_topic.arn
-# : s["Resource"]
-# )
-# }
-# )
-# ]
-#
-# ses_publish_statement = var.enable_ses_publish ? {
-# Sid = "AllowSESPublish"
-# Effect = "Allow"
-# Principal = {
-# Service = "ses.amazonaws.com"
-# }
-# Action = "SNS:Publish"
-# Resource = aws_sns_topic.sns_topic.arn
-# Condition = {
-# StringEquals = {
-# "AWS:SourceAccount" = var.ses_source_account_id
-# }
-# }
-# } : null
-#
-# effective_topic_policy_obj = merge(
-# local.base_topic_policy_obj,
-# {
-# Statement = concat(
-# local.normalized_statements,
-# var.enable_ses_publish ? [local.ses_publish_statement] : []
-# )
-# }
-# )
-# effective_topic_policy_json = jsonencode(local.effective_topic_policy_obj)
-# }
+data "aws_caller_identity" "current" {}
+
+locals {
+ base_topic_policy_json = var.topic_policy_json != null ? var.topic_policy_json : var.delivery_policy
+ base_topic_policy_obj = jsondecode(local.base_topic_policy_json)
+ normalized_statements = [
+ for s in try(local.base_topic_policy_obj["Statement"], []) : merge(
+ s,
+ {
+ Resource = (
+ try(s["Resource"], null) == "*" || try(s["Resource"], null) == null
+ ? aws_sns_topic.sns_topic.arn
+ : s["Resource"]
+ )
+ }
+ )
+ ]
+
+ ses_publish_statement = var.enable_ses_publish ? {
+ Sid = "AllowSESPublish"
+ Effect = "Allow"
+ Principal = {
+ Service = "ses.amazonaws.com"
+ }
+ Action = "SNS:Publish"
+ Resource = aws_sns_topic.sns_topic.arn
+ Condition = {
+ StringEquals = {
+ "AWS:SourceAccount" = data.aws_caller_identity.current.account_id
+ }
+ }
+ } : null
+
+ effective_topic_policy_obj = merge(
+ local.base_topic_policy_obj,
+ {
+ Statement = concat(
+ local.normalized_statements,
+ var.enable_ses_publish ? [local.ses_publish_statement] : []
+ )
+ }
+ )
+ effective_topic_policy_json = jsonencode(local.effective_topic_policy_obj)
+}
resource "aws_sns_topic" "sns_topic" {
name_prefix = "${terraform.workspace}-sns-${var.topic_name}"
- policy = var.delivery_policy
fifo_topic = var.enable_fifo
content_based_deduplication = var.enable_deduplication
kms_master_key_id = var.sns_encryption_key_id
@@ -53,10 +54,10 @@ resource "aws_sns_topic" "sns_topic" {
sqs_success_feedback_sample_rate = try(var.sqs_feedback.success_sample_rate, null)
}
-# resource "aws_sns_topic_policy" "this" {
-# arn = aws_sns_topic.sns_topic.arn
-# policy = local.effective_topic_policy_json
-# }
+resource "aws_sns_topic_policy" "this" {
+ arn = aws_sns_topic.sns_topic.arn
+ policy = local.effective_topic_policy_json
+}
resource "aws_sns_topic_subscription" "sns_subscription_single" {
count = var.is_topic_endpoint_list ? 0 : 1
@@ -65,7 +66,7 @@ resource "aws_sns_topic_subscription" "sns_subscription_single" {
endpoint = var.topic_endpoint
raw_message_delivery = var.raw_message_delivery
- # depends_on = [aws_sns_topic_policy.this]
+ depends_on = [aws_sns_topic_policy.this]
}
resource "aws_sns_topic_subscription" "sns_subscription_list" {
@@ -75,7 +76,7 @@ resource "aws_sns_topic_subscription" "sns_subscription_list" {
endpoint = each.value
raw_message_delivery = var.raw_message_delivery
- # depends_on = [aws_sns_topic_policy.this]
+ depends_on = [aws_sns_topic_policy.this]
}
output "arn" {
diff --git a/infrastructure/modules/sns/variable.tf b/infrastructure/modules/sns/variable.tf
index eb585720..428e3629 100644
--- a/infrastructure/modules/sns/variable.tf
+++ b/infrastructure/modules/sns/variable.tf
@@ -60,20 +60,14 @@ variable "is_topic_endpoint_list" {
default = false
}
-# variable "topic_policy_json" {
-# description = "Optional SNS topic access policy JSON. If set, it overrides delivery_policy."
-# type = string
-# default = null
-# }
-#
-# variable "enable_ses_publish" {
-# description = "If true, module appends a statement allowing ses.amazonaws.com to SNS:Publish to this topic."
-# type = bool
-# default = false
-# }
-#
-# variable "ses_source_account_id" {
-# description = "AWS account ID used in the AWS:SourceAccount condition for SES publishing."
-# type = string
-# default = ""
-# }
+variable "topic_policy_json" {
+ description = "Optional SNS topic access policy JSON. If set, it overrides delivery_policy."
+ type = string
+ default = null
+}
+
+variable "enable_ses_publish" {
+ description = "If true, module appends a statement allowing ses.amazonaws.com to SNS:Publish to this topic."
+ type = bool
+ default = false
+}
diff --git a/infrastructure/moved-resources-v1.6.14.tf b/infrastructure/moved-resources-v1.6.14.tf
deleted file mode 100644
index daae1209..00000000
--- a/infrastructure/moved-resources-v1.6.14.tf
+++ /dev/null
@@ -1,4 +0,0 @@
-moved {
- from = module.route53_fargate_ui.aws_route53_record.ndr_fargate_record
- to = module.route53_fargate_ui.aws_route53_record.ndr_fargate_record_cname[0]
-}
diff --git a/infrastructure/moved-resources-v1.6.15.tf b/infrastructure/moved-resources-v1.6.15.tf
new file mode 100644
index 00000000..660190c5
--- /dev/null
+++ b/infrastructure/moved-resources-v1.6.15.tf
@@ -0,0 +1,4 @@
+moved {
+ from = module.ndr-feedback-mailbox
+ to = module.ses
+}
diff --git a/infrastructure/ses.tf b/infrastructure/ses.tf
index f133de78..dcfbad93 100644
--- a/infrastructure/ses.tf
+++ b/infrastructure/ses.tf
@@ -1,12 +1,6 @@
-locals {
- domain_prefix = terraform.workspace == "ndr-test" ? "" : terraform.workspace
- domain = terraform.workspace == "ndr-test" ? var.domain : "${terraform.workspace}.${var.domain}"
-}
-
-module "ndr-feedback-mailbox" {
- source = "./modules/ses"
- domain_prefix = local.domain_prefix
- domain = local.domain
- zone_id = module.route53_fargate_ui.zone_id
- enable = !local.is_sandbox
+module "ses" {
+ source = "./modules/ses"
+ domain = var.domain
+ zone_id = module.route53_fargate_ui.zone_id
+ is_sandbox = local.is_sandbox
}
diff --git a/infrastructure/ses_feedback_events.tf b/infrastructure/ses_feedback_events.tf
index b578c535..4805a65d 100644
--- a/infrastructure/ses_feedback_events.tf
+++ b/infrastructure/ses_feedback_events.tf
@@ -1,23 +1,22 @@
-# resource "aws_ses_configuration_set" "reporting" {
-# name = "${terraform.workspace}-reporting"
-# }
-#
-# resource "aws_ses_event_destination" "reporting_to_sns" {
-# name = "sns-feedback"
-# configuration_set_name = aws_ses_configuration_set.reporting.name
-# enabled = true
-#
-# matching_types = [
-# "bounce",
-# "reject"
-# ]
-#
-# sns_destination {
-# topic_arn = module.ses_feedback_topic.arn
-# }
-#
-# depends_on = [
-# module.ses_feedback_topic,
-# aws_lambda_permission.allow_sns_invoke_ses_feedback_monitor
-# ]
-# }
+resource "aws_ses_configuration_set" "reporting" {
+ name = "${terraform.workspace}-reporting"
+}
+
+resource "aws_ses_event_destination" "reporting_to_sns" {
+ name = "sns-feedback"
+ configuration_set_name = aws_ses_configuration_set.reporting.name
+ enabled = true
+
+ matching_types = [
+ "bounce",
+ "reject"
+ ]
+
+ sns_destination {
+ topic_arn = module.ses_feedback_topic.arn
+ }
+
+ depends_on = [
+ aws_lambda_permission.allow_sns_invoke_ses_feedback_monitor
+ ]
+}
diff --git a/infrastructure/ses_reporting.tf b/infrastructure/ses_reporting.tf
deleted file mode 100644
index bfb964f9..00000000
--- a/infrastructure/ses_reporting.tf
+++ /dev/null
@@ -1,78 +0,0 @@
-# resource "aws_ses_domain_identity" "reporting" {
-# count = local.is_shared_workspace ? 1 : 0
-# domain = var.domain
-# }
-#
-# resource "aws_route53_record" "ses_domain_verification" {
-# count = local.is_shared_workspace ? 1 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = "_amazonses.${var.domain}"
-# type = "TXT"
-# ttl = 600
-# records = [aws_ses_domain_identity.reporting[0].verification_token]
-# }
-#
-# resource "aws_ses_domain_identity_verification" "reporting" {
-# count = local.is_shared_workspace ? 1 : 0
-# domain = aws_ses_domain_identity.reporting[0].domain
-# depends_on = [aws_route53_record.ses_domain_verification]
-# }
-#
-# resource "aws_ses_domain_dkim" "reporting" {
-# count = local.is_shared_workspace ? 1 : 0
-# domain = aws_ses_domain_identity.reporting[0].domain
-# }
-#
-# resource "aws_route53_record" "ses_dkim" {
-# count = local.is_shared_workspace ? 3 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = "${aws_ses_domain_dkim.reporting[0].dkim_tokens[count.index]}._domainkey.${var.domain}"
-# type = "CNAME"
-# ttl = 600
-#
-# records = ["${aws_ses_domain_dkim.reporting[0].dkim_tokens[count.index]}.dkim.amazonses.com"]
-# }
-#
-# resource "aws_ses_domain_mail_from" "reporting" {
-# count = local.is_shared_workspace ? 1 : 0
-# domain = aws_ses_domain_identity.reporting[0].domain
-# mail_from_domain = "mail.${var.domain}"
-#
-# behavior_on_mx_failure = "UseDefaultValue"
-# }
-#
-# resource "aws_route53_record" "ses_mail_from_mx" {
-# count = local.is_shared_workspace ? 1 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = "mail.${var.domain}"
-# type = "MX"
-# ttl = 600
-#
-# records = [
-# "10 feedback-smtp.${var.region}.amazonses.com"
-# ]
-# }
-#
-# resource "aws_route53_record" "ses_mail_from_spf" {
-# count = local.is_shared_workspace ? 1 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = "mail.${var.domain}"
-# type = "TXT"
-# ttl = 600
-#
-# records = [
-# "v=spf1 include:amazonses.com -all"
-# ]
-# }
-#
-# resource "aws_route53_record" "spf_root" {
-# count = local.is_shared_workspace ? 1 : 0
-# zone_id = module.route53_fargate_ui.zone_id
-# name = var.domain
-# type = "TXT"
-# ttl = 300
-#
-# records = [
-# "v=spf1 include:amazonses.com -all"
-# ]
-# }
diff --git a/infrastructure/sns_ses_feedback.tf b/infrastructure/sns_ses_feedback.tf
index 979807a4..0e9e4fbf 100644
--- a/infrastructure/sns_ses_feedback.tf
+++ b/infrastructure/sns_ses_feedback.tf
@@ -1,43 +1,42 @@
-# module "ses_feedback_topic" {
-# source = "./modules/sns"
-# topic_name = "ses-feedback-events"
-# topic_protocol = "lambda"
-# topic_endpoint = module.ses-feedback-monitor-lambda.lambda_arn
-# sns_encryption_key_id = module.sns_encryption_key.kms_arn
-# raw_message_delivery = false
-#
-# delivery_policy = jsonencode({
-# Version = "2012-10-17"
-# Statement = [
-# {
-# Sid = "DefaultOwnerPermissions"
-# Effect = "Allow"
-# Principal = {
-# AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
-# }
-# Action = [
-# "sns:GetTopicAttributes",
-# "sns:SetTopicAttributes",
-# "sns:AddPermission",
-# "sns:RemovePermission",
-# "sns:DeleteTopic",
-# "sns:Subscribe",
-# "sns:ListSubscriptionsByTopic",
-# "sns:Publish"
-# ]
-# Resource = "*"
-# }
-# ]
-# })
-#
-# enable_ses_publish = true
-# ses_source_account_id = data.aws_caller_identity.current.account_id
-# }
-#
-# resource "aws_lambda_permission" "allow_sns_invoke_ses_feedback_monitor" {
-# statement_id = "AllowSNSInvokeSesFeedbackMonitor"
-# action = "lambda:InvokeFunction"
-# function_name = module.ses-feedback-monitor-lambda.lambda_arn
-# principal = "sns.amazonaws.com"
-# source_arn = module.ses_feedback_topic.arn
-# }
+module "ses_feedback_topic" {
+ source = "./modules/sns"
+ topic_name = "ses-feedback-events"
+ topic_protocol = "lambda"
+ topic_endpoint = module.ses-feedback-monitor-lambda.lambda_arn
+ sns_encryption_key_id = module.sns_encryption_key.kms_arn
+ raw_message_delivery = false
+
+ delivery_policy = jsonencode({
+ Version = "2012-10-17"
+ Statement = [
+ {
+ Sid = "DefaultOwnerPermissions"
+ Effect = "Allow"
+ Principal = {
+ AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
+ }
+ Action = [
+ "sns:GetTopicAttributes",
+ "sns:SetTopicAttributes",
+ "sns:AddPermission",
+ "sns:RemovePermission",
+ "sns:DeleteTopic",
+ "sns:Subscribe",
+ "sns:ListSubscriptionsByTopic",
+ "sns:Publish"
+ ]
+ Resource = "*"
+ }
+ ]
+ })
+
+ enable_ses_publish = true
+}
+
+resource "aws_lambda_permission" "allow_sns_invoke_ses_feedback_monitor" {
+ statement_id = "AllowSNSInvokeSesFeedbackMonitor"
+ action = "lambda:InvokeFunction"
+ function_name = module.ses-feedback-monitor-lambda.lambda_arn
+ principal = "sns.amazonaws.com"
+ source_arn = module.ses_feedback_topic.arn
+}
diff --git a/infrastructure/ssm_reporting.tf b/infrastructure/ssm_reporting.tf
deleted file mode 100644
index 4fe98965..00000000
--- a/infrastructure/ssm_reporting.tf
+++ /dev/null
@@ -1,14 +0,0 @@
-# # locals {
-# # reporting_from_domain = (local.is_production
-# # ? var.domain
-# # : "${var.shared_infra_workspace}.${var.domain}"
-# # )
-# locals {
-# reporting_from_domain = (
-# local.is_production && terraform.workspace != "pre-prod"
-# ? var.domain
-# : "${var.shared_infra_workspace}.${var.domain}"
-# )
-#
-# reporting_ses_from_address_value = "ndr-reports@${local.reporting_from_domain}"
-# }
diff --git a/infrastructure/step-function-reporting.tf b/infrastructure/step-function-reporting.tf
index ded274c6..2970509f 100644
--- a/infrastructure/step-function-reporting.tf
+++ b/infrastructure/step-function-reporting.tf
@@ -21,7 +21,7 @@ data "aws_iam_policy_document" "reporting_sfn_permissions" {
actions = ["lambda:InvokeFunction"]
resources = [
module.report-orchestration-lambda.lambda_arn,
- # module.report-distribution-lambda.lambda_arn,
+ module.report-distribution-lambda.lambda_arn,
]
}
}
@@ -53,53 +53,51 @@ resource "aws_sfn_state_machine" "reporting_daily_reports" {
"keys.$" = "$.Payload.keys"
},
ResultPath = "$",
- # Next = "Process Reports (Map)"
- End = true
+ Next = "Process Reports (Map)"
},
- # "Process Reports (Map)" = {
- # Type = "Map",
- # ItemsPath = "$.keys",
- # MaxConcurrency = 25,
- #
- # ItemSelector = {
- # "bucket.$" = "$.bucket",
- # "key.$" = "$$.Map.Item.Value"
- # },
- #
- # ItemProcessor = {
- # ProcessorConfig = {
- # Mode = "INLINE"
- # },
- # StartAt = "Distribute One Report",
- # States = {
- # "Distribute One Report" = {
- # Type = "Task",
- # Resource = "arn:aws:states:::lambda:invoke",
- # Parameters = {
- # FunctionName = module.report-distribution-lambda.lambda_arn,
- # Payload = {
- # "action" = "process_one",
- # "bucket.$" = "$.bucket",
- # "key.$" = "$.key"
- # }
- # },
- # Retry = [
- # {
- # ErrorEquals = ["States.ALL"],
- # IntervalSeconds = 2,
- # MaxAttempts = 3,
- # BackoffRate = 2.0,
- # JitterStrategy = "FULL"
- # }
- # ],
- # End = true
- # }
- # }
- # },
- # End = true
- # }
+ "Process Reports (Map)" = {
+ Type = "Map",
+ ItemsPath = "$.keys",
+ MaxConcurrency = 25,
+
+ ItemSelector = {
+ "bucket.$" = "$.bucket",
+ "key.$" = "$$.Map.Item.Value"
+ },
+ ItemProcessor = {
+ ProcessorConfig = {
+ Mode = "INLINE"
+ },
+ StartAt = "Distribute One Report",
+ States = {
+ "Distribute One Report" = {
+ Type = "Task",
+ Resource = "arn:aws:states:::lambda:invoke",
+ Parameters = {
+ FunctionName = module.report-distribution-lambda.lambda_arn,
+ Payload = {
+ "action" = "process_one",
+ "bucket.$" = "$.bucket",
+ "key.$" = "$.key"
+ }
+ },
+ Retry = [
+ {
+ ErrorEquals = ["States.ALL"],
+ IntervalSeconds = 2,
+ MaxAttempts = 3,
+ BackoffRate = 2.0
+ JitterStrategy = "FULL"
+ }
+ ],
+ End = true
+ }
+ }
+ },
+ End = true
+ }
}
})
-}
\ No newline at end of file
+}