diff --git a/infra/app/app-config/env-config/main.tf b/infra/app/app-config/env-config/main.tf index a44cda83..a7263269 100644 --- a/infra/app/app-config/env-config/main.tf +++ b/infra/app/app-config/env-config/main.tf @@ -7,10 +7,4 @@ locals { prefix = terraform.workspace == "default" ? "" : "${terraform.workspace}-" bucket_name = "${local.prefix}${var.project_name}-${var.app_name}-${var.environment}" - - network_config = module.project_config.network_configs[var.network_name] -} - -module "project_config" { - source = "../../../project-config" } diff --git a/infra/app/app-config/env-config/notifications.tf b/infra/app/app-config/env-config/notifications.tf index 52464c23..b351c73e 100644 --- a/infra/app/app-config/env-config/notifications.tf +++ b/infra/app/app-config/env-config/notifications.tf @@ -1,6 +1,6 @@ # Notifications configuration locals { - notifications_config = var.enable_notifications && var.domain_name != null && local.network_config.domain_config.hosted_zone != null ? { + notifications_config = var.enable_notifications ? { # Pinpoint app name. name = "${var.app_name}-${var.environment}" diff --git a/infra/app/app-config/main.tf b/infra/app/app-config/main.tf index ce4ba29c..4791259a 100644 --- a/infra/app/app-config/main.tf +++ b/infra/app/app-config/main.tf @@ -30,14 +30,7 @@ locals { # 3. Adds environment variables for the app client to the service enable_identity_provider = false - # Whether or not the application should deploy a notification service. - # - # To use this in a particular environment, domain_name must also be set. - # The domain name in set in infra//app-config/.tf - # The domain name the same domain as, of a subdomain of, the hosted zone in that environment. - # The hosted zone is set in infra/project-config/networks.tf - # If either (domain name or hosteed zone) is not set in an environment, notifications will not actually be enabled. - # + # Whether or not the application should deploy a notification service # If enabled: # 1. Creates an AWS Pinpoint application # 2. Configures email notifications using AWS SES diff --git a/infra/app/service/identity_provider.tf b/infra/app/service/identity_provider.tf deleted file mode 100644 index 13becda3..00000000 --- a/infra/app/service/identity_provider.tf +++ /dev/null @@ -1,58 +0,0 @@ -locals { - # If this is a temporary environment, re-use an existing Cognito user pool. Otherwise, create a new one. - identity_provider_user_pool_id = module.app_config.enable_identity_provider ? ( - local.is_temporary ? module.existing_identity_provider[0].user_pool_id : module.identity_provider[0].user_pool_id - ) : null - identity_provider_environment_variables = module.app_config.enable_identity_provider ? { - COGNITO_USER_POOL_ID = local.identity_provider_user_pool_id, - COGNITO_CLIENT_ID = module.identity_provider_client[0].client_id - } : {} -} - -# If the app has `enable_identity_provider` set to true AND this is not a temporary -# environment, then create a new identity provider. -module "identity_provider" { - count = module.app_config.enable_identity_provider && !local.is_temporary ? 1 : 0 - source = "../../modules/identity-provider/resources" - - is_temporary = local.is_temporary - - name = local.identity_provider_config.identity_provider_name - password_minimum_length = local.identity_provider_config.password_policy.password_minimum_length - temporary_password_validity_days = local.identity_provider_config.password_policy.temporary_password_validity_days - verification_email_message = local.identity_provider_config.verification_email.verification_email_message - verification_email_subject = local.identity_provider_config.verification_email.verification_email_subject - domain_name = local.network_config.domain_config.hosted_zone - sender_email = local.notifications_config == null ? null : local.notifications_config.sender_email - sender_display_name = local.notifications_config == null ? null : local.notifications_config.sender_display_name - reply_to_email = local.notifications_config == null ? null : local.notifications_config.reply_to_email - - # This module both explicitly requires the notifications module, - # because its `aws_sesv2_email_identity` resource to be imported. - depends_on = [ - module.notifications, - ] -} - -# If the app has `enable_identity_provider` set to true AND this *is* a temporary -# environment, then use an existing identity provider. -module "existing_identity_provider" { - count = module.app_config.enable_identity_provider && local.is_temporary ? 1 : 0 - source = "../../modules/identity-provider/data" - - name = local.identity_provider_config.identity_provider_name -} - -# If the app has `enable_identity_provider` set to true, create a new identity provider -# client for the service. A new client is created for all environments, including -# temporary environments. -module "identity_provider_client" { - count = module.app_config.enable_identity_provider ? 1 : 0 - source = "../../modules/identity-provider-client/resources" - - callback_urls = local.identity_provider_config.client.callback_urls - logout_urls = local.identity_provider_config.client.logout_urls - name = "${local.prefix}${local.identity_provider_config.identity_provider_name}" - - user_pool_id = local.identity_provider_user_pool_id -} diff --git a/infra/app/service/main.tf b/infra/app/service/main.tf index 74933c75..c3d220d4 100644 --- a/infra/app/service/main.tf +++ b/infra/app/service/main.tf @@ -50,6 +50,17 @@ locals { notifications_config = local.environment_config.notifications_config network_config = module.project_config.network_configs[local.environment_config.network_name] + + # Identity provider locals. + # If this is a temporary environment, re-use an existing Cognito user pool. + # Otherwise, create a new one. + identity_provider_user_pool_id = module.app_config.enable_identity_provider ? ( + local.is_temporary ? module.existing_identity_provider[0].user_pool_id : module.identity_provider[0].user_pool_id + ) : null + identity_provider_environment_variables = module.app_config.enable_identity_provider ? { + COGNITO_USER_POOL_ID = local.identity_provider_user_pool_id, + COGNITO_CLIENT_ID = module.identity_provider_client[0].client_id + } : {} } terraform { @@ -58,7 +69,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.81.0, < 6.0.0" + version = ">= 5.35.0, < 6.0.0" } } @@ -214,3 +225,45 @@ module "storage" { name = local.storage_config.bucket_name is_temporary = local.is_temporary } + +# If the app has `enable_identity_provider` set to true AND this is not a temporary +# environment, then create a new identity provider. +module "identity_provider" { + count = module.app_config.enable_identity_provider && !local.is_temporary ? 1 : 0 + source = "../../modules/identity-provider/resources" + + is_temporary = local.is_temporary + + name = local.identity_provider_config.identity_provider_name + password_minimum_length = local.identity_provider_config.password_policy.password_minimum_length + temporary_password_validity_days = local.identity_provider_config.password_policy.temporary_password_validity_days + verification_email_message = local.identity_provider_config.verification_email.verification_email_message + verification_email_subject = local.identity_provider_config.verification_email.verification_email_subject + + sender_email = local.notifications_config == null ? null : local.notifications_config.sender_email + sender_display_name = local.notifications_config == null ? null : local.notifications_config.sender_display_name + reply_to_email = local.notifications_config == null ? null : local.notifications_config.reply_to_email +} + +# If the app has `enable_identity_provider` set to true AND this *is* a temporary +# environment, then use an existing identity provider. +module "existing_identity_provider" { + count = module.app_config.enable_identity_provider && local.is_temporary ? 1 : 0 + source = "../../modules/identity-provider/data" + + name = local.identity_provider_config.identity_provider_name +} + +# If the app has `enable_identity_provider` set to true, create a new identity provider +# client for the service. A new client is created for all environments, including +# temporary environments. +module "identity_provider_client" { + count = module.app_config.enable_identity_provider ? 1 : 0 + source = "../../modules/identity-provider-client/resources" + + callback_urls = local.identity_provider_config.client.callback_urls + logout_urls = local.identity_provider_config.client.logout_urls + name = "${local.prefix}${local.identity_provider_config.identity_provider_name}" + + user_pool_id = local.identity_provider_user_pool_id +} diff --git a/infra/app/service/notifications.tf b/infra/app/service/notifications.tf index 82aab8f5..423f5c3b 100644 --- a/infra/app/service/notifications.tf +++ b/infra/app/service/notifications.tf @@ -1,40 +1,40 @@ locals { # If this is a temporary environment, re-use an existing email identity. Otherwise, create a new one. - domain_identity_arn = local.notifications_config != null ? ( + domain_identity_arn = module.app_config.enable_notifications ? ( !local.is_temporary ? module.notifications_email_domain[0].domain_identity_arn : module.existing_notifications_email_domain[0].domain_identity_arn ) : null - notifications_environment_variables = local.notifications_config != null ? { + notifications_environment_variables = module.app_config.enable_notifications ? { AWS_PINPOINT_APP_ID = module.notifications[0].app_id, AWS_PINPOINT_SENDER_EMAIL = local.notifications_config.sender_email } : {} - notifications_app_name = local.notifications_config != null ? "${local.prefix}${local.notifications_config.name}" : "" + notifications_app_name = module.app_config.enable_notifications ? "${local.prefix}${local.notifications_config.name}" : "" } # If the app has `enable_notifications` set to true AND this is not a temporary # environment, then create a email notification identity. module "notifications_email_domain" { - count = local.notifications_config != null && !local.is_temporary ? 1 : 0 + count = module.app_config.enable_notifications && !local.is_temporary ? 1 : 0 source = "../../modules/notifications-email-domain/resources" - domain_name = local.network_config.domain_config.hosted_zone + domain_name = local.service_config.domain_name } # If the app has `enable_notifications` set to true AND this *is* a temporary # environment, then create a email notification identity. module "existing_notifications_email_domain" { - count = local.notifications_config != null && local.is_temporary ? 1 : 0 + count = module.app_config.enable_notifications && local.is_temporary ? 1 : 0 source = "../../modules/notifications-email-domain/data" - domain_name = local.network_config.domain_config.hosted_zone + domain_name = local.service_config.domain_name } # If the app has `enable_notifications` set to true, create a new email notification # AWS Pinpoint app for the service. A new app is created for all environments, including # temporary environments. module "notifications" { - count = local.notifications_config != null ? 1 : 0 + count = module.app_config.enable_notifications ? 1 : 0 source = "../../modules/notifications/resources" name = local.notifications_app_name diff --git a/infra/modules/identity-provider/resources/main.tf b/infra/modules/identity-provider/resources/main.tf index 1cbb6c85..7787b000 100644 --- a/infra/modules/identity-provider/resources/main.tf +++ b/infra/modules/identity-provider/resources/main.tf @@ -4,14 +4,6 @@ ## - Configures MFA ############################################################################################ -locals { - dash_domain = var.domain_name != null ? replace(var.domain_name, ".", "-") : null -} - -data "aws_sesv2_email_identity" "main" { - email_identity = var.domain_name -} - resource "aws_cognito_user_pool" "main" { name = var.name @@ -37,12 +29,11 @@ resource "aws_cognito_user_pool" "main" { # Use this SES email to send cognito emails. If we're not using SES for emails then use null. # Optionally configures the FROM address and the REPLY-TO address. # Optionally configures using the Cognito default email or using SES. - source_arn = data.aws_sesv2_email_identity.main.arn - configuration_set = local.dash_domain - email_sending_account = data.aws_sesv2_email_identity.main.arn != null ? "DEVELOPER" : "COGNITO_DEFAULT" + source_arn = var.email_identity_arn + email_sending_account = var.email_identity_arn != null ? "DEVELOPER" : "COGNITO_DEFAULT" # Customize the name that users see in the "From" section of their inbox, so that it's clearer who the email is from. # This name also needs to be updated manually in the Cognito console for each environment's Advanced Security emails. - from_email_address = data.aws_sesv2_email_identity.main.arn != null ? (var.sender_display_name != null ? "${var.sender_display_name} <${var.sender_email}>" : var.sender_email) : null + from_email_address = var.email_identity_arn != null ? (var.sender_display_name != null ? "${var.sender_display_name} <${var.sender_email}>" : var.sender_email) : null reply_to_email_address = var.reply_to_email } diff --git a/infra/modules/identity-provider/resources/variables.tf b/infra/modules/identity-provider/resources/variables.tf index 659e8364..a8b54f21 100644 --- a/infra/modules/identity-provider/resources/variables.tf +++ b/infra/modules/identity-provider/resources/variables.tf @@ -1,6 +1,6 @@ -variable "domain_name" { - description = "The domain name to configure SES" +variable "email_identity_arn" { type = string + description = "The arn of the SESv2 email identity to use to send emails" default = null } diff --git a/infra/modules/notifications-email-domain/resources/main.tf b/infra/modules/notifications-email-domain/resources/main.tf index f89cc8ce..318587c0 100644 --- a/infra/modules/notifications-email-domain/resources/main.tf +++ b/infra/modules/notifications-email-domain/resources/main.tf @@ -10,17 +10,16 @@ locals { # Verify email sender identity. # Docs: https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-email-manage-verify.html resource "aws_sesv2_email_identity" "sender_domain" { - email_identity = var.domain_name + email_identity = local.dash_domain configuration_set_name = aws_sesv2_configuration_set.email.configuration_set_name } # The configuration set applied to messages that is sent through this email channel. resource "aws_sesv2_configuration_set" "email" { - configuration_set_name = local.dash_domain + configuration_set_name = var.domain_name delivery_options { - max_delivery_seconds = 300 - tls_policy = "REQUIRE" + tls_policy = "REQUIRE" } reputation_options {