From 3ec89f3a7eb3ba3595fc305a492d3ae519e8546d Mon Sep 17 00:00:00 2001 From: Kevin Boyer Date: Fri, 20 Dec 2024 13:26:39 -0500 Subject: [PATCH 1/4] fix: Setup Terraform in CI/CD workflows (#816) --- .github/workflows/build-and-publish.yml | 3 +++ .github/workflows/check-infra-deploy-status.yml | 7 +++---- .github/workflows/ci-infra-service.yml | 6 ++---- .github/workflows/pr-environment-checks.yml | 7 ++----- .github/workflows/pr-environment-destroy.yml | 7 ++----- .github/workflows/template-only-ci-infra.yml | 8 ++++---- 6 files changed, 16 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index acdc5d27..d55e591b 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -58,6 +58,9 @@ jobs: with: ref: ${{ inputs.ref }} + - name: Set up Terraform + uses: ./.github/actions/setup-terraform + - name: Configure AWS credentials uses: ./.github/actions/configure-aws-credentials with: diff --git a/.github/workflows/check-infra-deploy-status.yml b/.github/workflows/check-infra-deploy-status.yml index 4cac7e2f..4367978d 100644 --- a/.github/workflows/check-infra-deploy-status.yml +++ b/.github/workflows/check-infra-deploy-status.yml @@ -44,10 +44,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.8.3 - terraform_wrapper: false + + - name: Set up Terraform + uses: ./.github/actions/setup-terraform - name: Configure AWS credentials uses: ./.github/actions/configure-aws-credentials diff --git a/.github/workflows/ci-infra-service.yml b/.github/workflows/ci-infra-service.yml index 28d80584..874ae378 100644 --- a/.github/workflows/ci-infra-service.yml +++ b/.github/workflows/ci-infra-service.yml @@ -30,10 +30,8 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.8.3 - terraform_wrapper: false + - name: Set up Terraform + uses: ./.github/actions/setup-terraform - uses: actions/setup-go@v5 with: diff --git a/.github/workflows/pr-environment-checks.yml b/.github/workflows/pr-environment-checks.yml index b723a2a8..665ed271 100644 --- a/.github/workflows/pr-environment-checks.yml +++ b/.github/workflows/pr-environment-checks.yml @@ -42,11 +42,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.8.3 - terraform_wrapper: false + - name: Set up Terraform + uses: ./.github/actions/setup-terraform - name: Configure AWS credentials uses: ./.github/actions/configure-aws-credentials diff --git a/.github/workflows/pr-environment-destroy.yml b/.github/workflows/pr-environment-destroy.yml index 346b8c11..e750b43c 100644 --- a/.github/workflows/pr-environment-destroy.yml +++ b/.github/workflows/pr-environment-destroy.yml @@ -28,11 +28,8 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.8.3 - terraform_wrapper: false + - name: Set up Terraform + uses: ./.github/actions/setup-terraform - name: Configure AWS credentials uses: ./.github/actions/configure-aws-credentials diff --git a/.github/workflows/template-only-ci-infra.yml b/.github/workflows/template-only-ci-infra.yml index 79a7f834..5a990fc6 100644 --- a/.github/workflows/template-only-ci-infra.yml +++ b/.github/workflows/template-only-ci-infra.yml @@ -33,10 +33,10 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.8.3 - terraform_wrapper: false + + - name: Set up Terraform + uses: ./.github/actions/setup-terraform + - uses: actions/setup-go@v5 with: go-version: ">=1.19.0" From 1f9abd2530c1fdb316b80f427f9cec50e9d03060 Mon Sep 17 00:00:00 2001 From: Ryan Lewis <93001277+rylew1@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:47:47 -0500 Subject: [PATCH 2/4] E2E informational to run make command to show report (#815) ## Ticket Resolves #814 ## Changes - Add informational to use make command to show reports when done running e2e tests --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 6f571694..1dd89361 100644 --- a/Makefile +++ b/Makefile @@ -123,6 +123,7 @@ e2e-test: e2e-build -v $(PWD)/e2e/blob-report:/e2e/blob-report \ $(E2E_IMAGE_NAME) \ $(E2E_ARGS) + @echo "Run 'make e2e-show-report' to view the test report" e2e-test-native: ## Run end-to-end tests natively @:$(call check_defined, APP_NAME, You must pass in a specific APP_NAME) From 160c0def3a8aae8a683acff67db151e6e30e945d Mon Sep 17 00:00:00 2001 From: Kai Siren Date: Fri, 20 Dec 2024 13:45:38 -0800 Subject: [PATCH 3/4] pfml-starter-kit-app/pull/237/ --- infra/app/app-config/env-config/main.tf | 6 ++ .../app-config/env-config/notifications.tf | 2 +- infra/app/app-config/main.tf | 9 ++- infra/app/service/identity_provider.tf | 58 +++++++++++++++++++ infra/app/service/main.tf | 55 +----------------- infra/app/service/notifications.tf | 16 ++--- .../identity-provider/resources/main.tf | 15 ++++- .../identity-provider/resources/variables.tf | 4 +- .../resources/main.tf | 7 ++- 9 files changed, 100 insertions(+), 72 deletions(-) create mode 100644 infra/app/service/identity_provider.tf diff --git a/infra/app/app-config/env-config/main.tf b/infra/app/app-config/env-config/main.tf index a7263269..a44cda83 100644 --- a/infra/app/app-config/env-config/main.tf +++ b/infra/app/app-config/env-config/main.tf @@ -7,4 +7,10 @@ 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 b351c73e..52464c23 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 ? { + notifications_config = var.enable_notifications && var.domain_name != null && local.network_config.domain_config.hosted_zone != null ? { # 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 4791259a..ce4ba29c 100644 --- a/infra/app/app-config/main.tf +++ b/infra/app/app-config/main.tf @@ -30,7 +30,14 @@ 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 + # 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. + # # 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 new file mode 100644 index 00000000..13becda3 --- /dev/null +++ b/infra/app/service/identity_provider.tf @@ -0,0 +1,58 @@ +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 c3d220d4..74933c75 100644 --- a/infra/app/service/main.tf +++ b/infra/app/service/main.tf @@ -50,17 +50,6 @@ 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 { @@ -69,7 +58,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.35.0, < 6.0.0" + version = ">= 5.81.0, < 6.0.0" } } @@ -225,45 +214,3 @@ 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 423f5c3b..82aab8f5 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 = module.app_config.enable_notifications ? ( + domain_identity_arn = local.notifications_config != null ? ( !local.is_temporary ? module.notifications_email_domain[0].domain_identity_arn : module.existing_notifications_email_domain[0].domain_identity_arn ) : null - notifications_environment_variables = module.app_config.enable_notifications ? { + notifications_environment_variables = local.notifications_config != null ? { AWS_PINPOINT_APP_ID = module.notifications[0].app_id, AWS_PINPOINT_SENDER_EMAIL = local.notifications_config.sender_email } : {} - notifications_app_name = module.app_config.enable_notifications ? "${local.prefix}${local.notifications_config.name}" : "" + notifications_app_name = local.notifications_config != null ? "${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 = module.app_config.enable_notifications && !local.is_temporary ? 1 : 0 + count = local.notifications_config != null && !local.is_temporary ? 1 : 0 source = "../../modules/notifications-email-domain/resources" - domain_name = local.service_config.domain_name + domain_name = local.network_config.domain_config.hosted_zone } # 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 = module.app_config.enable_notifications && local.is_temporary ? 1 : 0 + count = local.notifications_config != null && local.is_temporary ? 1 : 0 source = "../../modules/notifications-email-domain/data" - domain_name = local.service_config.domain_name + domain_name = local.network_config.domain_config.hosted_zone } # 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 = module.app_config.enable_notifications ? 1 : 0 + count = local.notifications_config != null ? 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 7787b000..1cbb6c85 100644 --- a/infra/modules/identity-provider/resources/main.tf +++ b/infra/modules/identity-provider/resources/main.tf @@ -4,6 +4,14 @@ ## - 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 @@ -29,11 +37,12 @@ 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 = var.email_identity_arn - email_sending_account = var.email_identity_arn != null ? "DEVELOPER" : "COGNITO_DEFAULT" + 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" # 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 = var.email_identity_arn != null ? (var.sender_display_name != null ? "${var.sender_display_name} <${var.sender_email}>" : var.sender_email) : null + 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 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 a8b54f21..659e8364 100644 --- a/infra/modules/identity-provider/resources/variables.tf +++ b/infra/modules/identity-provider/resources/variables.tf @@ -1,6 +1,6 @@ -variable "email_identity_arn" { +variable "domain_name" { + description = "The domain name to configure SES" 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 318587c0..f89cc8ce 100644 --- a/infra/modules/notifications-email-domain/resources/main.tf +++ b/infra/modules/notifications-email-domain/resources/main.tf @@ -10,16 +10,17 @@ 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 = local.dash_domain + email_identity = var.domain_name 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 = var.domain_name + configuration_set_name = local.dash_domain delivery_options { - tls_policy = "REQUIRE" + max_delivery_seconds = 300 + tls_policy = "REQUIRE" } reputation_options { From 1c7b9c236d0f1ea38400476e49c37942e1358b24 Mon Sep 17 00:00:00 2001 From: Kai Siren Date: Fri, 20 Dec 2024 13:45:51 -0800 Subject: [PATCH 4/4] Revert "pfml-starter-kit-app/pull/237/" This reverts commit 160c0def3a8aae8a683acff67db151e6e30e945d. --- infra/app/app-config/env-config/main.tf | 6 -- .../app-config/env-config/notifications.tf | 2 +- infra/app/app-config/main.tf | 9 +-- infra/app/service/identity_provider.tf | 58 ------------------- infra/app/service/main.tf | 55 +++++++++++++++++- infra/app/service/notifications.tf | 16 ++--- .../identity-provider/resources/main.tf | 15 +---- .../identity-provider/resources/variables.tf | 4 +- .../resources/main.tf | 7 +-- 9 files changed, 72 insertions(+), 100 deletions(-) delete mode 100644 infra/app/service/identity_provider.tf 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 {