Skip to content

[PRM-737] Switch email sending from SMTP to SES#120

Draft
chrisbloe wants to merge 4 commits intomainfrom
PRM-737
Draft

[PRM-737] Switch email sending from SMTP to SES#120
chrisbloe wants to merge 4 commits intomainfrom
PRM-737

Conversation

@chrisbloe
Copy link
Contributor

No description provided.

@github-actions
Copy link

Report for email_and_alerting on environment: dev

Terraform Format and Style 🖌success

Format Output


Terraform Initialization ⚙️success

Initialization Output

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 6.0"...
- Installing hashicorp/aws v6.37.0...
- Installed hashicorp/aws v6.37.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Terraform Validation 🤖success

Validation Output

Success! The configuration is valid.


Terraform Plan 📖success

Show Plan (4 to add, 8 to change, 1 to destroy)


Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
  - destroy

Terraform will perform the following actions:

  # aws_iam_policy.email_report_lambda_send_raw_email will be updated in-place
  ~ resource "aws_iam_policy" "email_report_lambda_send_raw_email" {
        id               = "arn:aws:iam::343515223843:policy/dev-email-report-send-raw-email"
        name             = "dev-email-report-send-raw-email"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Resource = "arn:aws:ses:eu-west-2:343515223843:identity/gp2gp.report@nhs.net" -> "arn:aws:ses:eu-west-2:343515223843:identity/gp2gp-reports@mail.dev.gp-registrations-data.nhs.uk"
                        # (3 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {}
        # (7 unchanged attributes hidden)
    }

  # aws_iam_policy.email_report_lambda_ssm_access will be updated in-place
  ~ resource "aws_iam_policy" "email_report_lambda_ssm_access" {
        id               = "arn:aws:iam::343515223843:policy/dev-email-report-lambda-ssm-access"
        name             = "dev-email-report-lambda-ssm-access"
      ~ policy           = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Resource = [
                          - "arn:aws:ssm:eu-west-2:343515223843:parameter/registrations/dev/user-input/email-report-sender-email-key",
                          - "arn:aws:ssm:eu-west-2:343515223843:parameter/registrations/dev/user-input/email-report-sender-email",
                            "arn:aws:ssm:eu-west-2:343515223843:parameter/registrations/dev/user-input/email-report-recipient-internal-email",
                            # (1 unchanged element hidden)
                        ]
                        # (3 unchanged attributes hidden)
                    },
                ]
                # (1 unchanged attribute hidden)
            }
        )
        tags             = {}
        # (7 unchanged attributes hidden)
    }

  # aws_lambda_function.email_report_lambda will be updated in-place
  ~ resource "aws_lambda_function" "email_report_lambda" {
        id                             = "dev-email-report-lambda"
      ~ last_modified                  = "2026-03-13T11:28:34.000+0000" -> (known after apply)
      ~ source_code_hash               = "6Z6qoCni1vl6/XqPxnOU4wx1WuRg0dv5r/APFynx5Z0=" -> "UgMhlQTapi3pMzblWvN7mythqzhJNX/iUE9T+u9D1NE="
        tags                           = {
            "ApplicationRole"     = "AwsLambdaFunction"
            "BackupLocal"         = "False"
            "BackupRemote"        = "False"
            "CostCentre"          = "P0688/04"
            "CreatedBy"           = "gp2gp-reporting-infrastructure"
            "Customer"            = "NHS D"
            "DataType"            = "None"
            "Environment"         = "dev"
            "Name"                = "dev-email-report-lambda"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "Candice Moore"
            "Programme"           = "GP IT Futures"
            "Project"             = "Patient Record Migration"
            "ProjectType"         = "Public beta"
            "PublicFacing"        = "N"
            "ServiceCategory"     = "Bronze"
            "TagVersion"          = "1"
            "Team"                = "Registrations"
            "data_classification" = "1"
            "envtype"             = "dev"
        }
        # (30 unchanged attributes hidden)

      ~ environment {
          ~ variables = {
              + "EMAIL_REPORT_SENDER"                              = "gp2gp-reports@mail.dev.gp-registrations-data.nhs.uk"
              - "EMAIL_REPORT_SENDER_EMAIL_KEY_PARAM_NAME"         = "/registrations/dev/user-input/email-report-sender-email-key" -> null
              - "EMAIL_REPORT_SENDER_EMAIL_PARAM_NAME"             = "/registrations/dev/user-input/email-report-sender-email" -> null
                # (2 unchanged elements hidden)
            }
        }

        # (3 unchanged blocks hidden)
    }

  # aws_lambda_function.gp2gp_dashboard_alert_lambda will be updated in-place
  ~ resource "aws_lambda_function" "gp2gp_dashboard_alert_lambda" {
        id                             = "dev-gp2gp-dashboard-alert-lambda"
      ~ last_modified                  = "2026-03-13T11:29:07.000+0000" -> (known after apply)
      ~ source_code_hash               = "NZNUUxTZQIBEcK5PCsqwOeMBJLEnSY1bZwo1zflikaQ=" -> "NymK82/LbRcZLgPRSfY31hWpGAXPMt6pDahHcWqGpOk="
        tags                           = {
            "ApplicationRole"     = "AwsLambdaFunction"
            "BackupLocal"         = "False"
            "BackupRemote"        = "False"
            "CostCentre"          = "P0688/04"
            "CreatedBy"           = "gp2gp-reporting-infrastructure"
            "Customer"            = "NHS D"
            "DataType"            = "None"
            "Environment"         = "dev"
            "Name"                = "dev-gp2gp-dashboard-alert-lambda"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "Candice Moore"
            "Programme"           = "GP IT Futures"
            "Project"             = "Patient Record Migration"
            "ProjectType"         = "Public beta"
            "PublicFacing"        = "N"
            "ServiceCategory"     = "Bronze"
            "TagVersion"          = "1"
            "Team"                = "Registrations"
            "data_classification" = "1"
            "envtype"             = "dev"
        }
        # (30 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # aws_lambda_function.log_alerts_pipeline_error_lambda will be updated in-place
  ~ resource "aws_lambda_function" "log_alerts_pipeline_error_lambda" {
        id                             = "dev-log-alerts-pipeline-error-lambda"
      ~ last_modified                  = "2026-03-13T11:28:45.000+0000" -> (known after apply)
      ~ source_code_hash               = "3kSsn3HidnPViXb3WbPJlohPkLwbnHG2XRmDVnszty8=" -> "fmV+knzxujqe/JqtazjudlMZcD9YwnoUUFKnBlwxiQM="
        tags                           = {
            "ApplicationRole"     = "AwsLambdaFunction"
            "BackupLocal"         = "False"
            "BackupRemote"        = "False"
            "CostCentre"          = "P0688/04"
            "CreatedBy"           = "gp2gp-reporting-infrastructure"
            "Customer"            = "NHS D"
            "DataType"            = "None"
            "Environment"         = "dev"
            "Name"                = "dev-log-alerts-pipeline-error-lambda"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "Candice Moore"
            "Programme"           = "GP IT Futures"
            "Project"             = "Patient Record Migration"
            "ProjectType"         = "Public beta"
            "PublicFacing"        = "N"
            "ServiceCategory"     = "Bronze"
            "TagVersion"          = "1"
            "Team"                = "Registrations"
            "data_classification" = "1"
            "envtype"             = "dev"
        }
        # (30 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # aws_lambda_function.log_alerts_technical_failures_above_threshold_lambda will be updated in-place
  ~ resource "aws_lambda_function" "log_alerts_technical_failures_above_threshold_lambda" {
        id                             = "dev-log-alerts-technical-failures-above-threshold-lambda"
      ~ last_modified                  = "2026-03-13T11:28:24.000+0000" -> (known after apply)
      ~ source_code_hash               = "ay7PCkmM0H/avx4jMgq8kUNnS18Sw4U6Hbnc+cNwZtI=" -> "xrDaBgg7QJ4lhM2RMeXk41VF/dk78lC7AZz4NXC9n/8="
        tags                           = {
            "ApplicationRole"     = "AwsLambdaFunction"
            "BackupLocal"         = "False"
            "BackupRemote"        = "False"
            "CostCentre"          = "P0688/04"
            "CreatedBy"           = "gp2gp-reporting-infrastructure"
            "Customer"            = "NHS D"
            "DataType"            = "None"
            "Environment"         = "dev"
            "Name"                = "dev-log-alerts-technical-failures-above-threshold-lambda"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "Candice Moore"
            "Programme"           = "GP IT Futures"
            "Project"             = "Patient Record Migration"
            "ProjectType"         = "Public beta"
            "PublicFacing"        = "N"
            "ServiceCategory"     = "Bronze"
            "TagVersion"          = "1"
            "Team"                = "Registrations"
            "data_classification" = "1"
            "envtype"             = "dev"
        }
        # (30 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # aws_lambda_function.store_asid_lookup will be updated in-place
  ~ resource "aws_lambda_function" "store_asid_lookup" {
        id                             = "dev_store_asid_lookup_lambda"
      ~ last_modified                  = "2026-03-13T11:28:56.000+0000" -> (known after apply)
      ~ source_code_hash               = "QRVIRXPUgxVT6r8ekFaScrLMmdNdR5wFSOLgY86Hqc0=" -> "ZzaUqOqeDVgj9hcsMzlsdrSNd7VnSrGIIbnYY1NGk/k="
        tags                           = {}
        # (30 unchanged attributes hidden)

        # (4 unchanged blocks hidden)
    }

  # aws_route53_record.gp2gp_inbox_dmarc will be updated in-place
  ~ resource "aws_route53_record" "gp2gp_inbox_dmarc" {
        id                               = "Z0811924E54GS533TZXR__dmarc.mail.dev.gp-registrations-data.nhs.uk_TXT"
        name                             = "_dmarc.mail.dev.gp-registrations-data.nhs.uk"
      ~ records                          = [
          - "v=DMARC1; p=none;",
          + "v=DMARC1; p=none; adkim=s; aspf=s",
        ]
        # (7 unchanged attributes hidden)
    }

  # aws_route53_record.ses_mail_from_mx will be created
  + resource "aws_route53_record" "ses_mail_from_mx" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "mail.dev.gp-registrations-data.nhs.uk"
      + records         = [
          + "10 feedback-smtp.eu-west-2.amazonses.com",
        ]
      + ttl             = 600
      + type            = "MX"
      + zone_id         = "Z0811924E54GS533TZXR"
    }

  # aws_route53_record.ses_mail_from_spf will be created
  + resource "aws_route53_record" "ses_mail_from_spf" {
      + allow_overwrite = (known after apply)
      + fqdn            = (known after apply)
      + id              = (known after apply)
      + name            = "mail.dev.gp-registrations-data.nhs.uk"
      + records         = [
          + "v=spf1 include:amazonses.com -all",
        ]
      + ttl             = 600
      + type            = "TXT"
      + zone_id         = "Z0811924E54GS533TZXR"
    }

  # aws_ses_domain_mail_from.sending will be created
  + resource "aws_ses_domain_mail_from" "sending" {
      + behavior_on_mx_failure = "UseDefaultValue"
      + domain                 = "mail.dev.gp-registrations-data.nhs.uk"
      + id                     = (known after apply)
      + mail_from_domain       = "mail.dev.gp-registrations-data.nhs.uk"
      + region                 = "eu-west-2"
    }

  # aws_ses_email_identity.gp2gp_inbox_sender_address will be destroyed
  # (because aws_ses_email_identity.gp2gp_inbox_sender_address is not in configuration)
  - resource "aws_ses_email_identity" "gp2gp_inbox_sender_address" {
      - arn    = "arn:aws:ses:eu-west-2:343515223843:identity/gp2gp.report@nhs.net" -> null
      - email  = (sensitive value) -> null
      - id     = "gp2gp.report@nhs.net" -> null
      - region = "eu-west-2" -> null
    }

  # aws_ses_email_identity.gp2gp_mailbox will be created
  + resource "aws_ses_email_identity" "gp2gp_mailbox" {
      + arn    = (known after apply)
      + email  = (sensitive value)
      + id     = (known after apply)
      + region = "eu-west-2"
    }

Plan: 4 to add, 8 to change, 1 to destroy.

@github-actions
Copy link

Report for gp2gp_dashboard on environment: dev

Terraform Format and Style 🖌success

Format Output


Terraform Initialization ⚙️success

Initialization Output

Initializing the backend...

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 6.0"...
- Installing hashicorp/aws v6.37.0...
- Installed hashicorp/aws v6.37.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Terraform Validation 🤖success

Validation Output

Success! The configuration is valid.


Terraform Plan 📖success

Show Plan (0 to add, 2 to change, 0 to destroy)


Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
 <= read (data resources)

Terraform will perform the following actions:

  # data.aws_iam_policy_document.dashboard_website will be read during apply
  # (depends on a resource or a module with changes pending)
 <= data "aws_iam_policy_document" "dashboard_website" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "s3:GetObject",
            ]
          + effect    = "Allow"
          + resources = [
              + "arn:aws:s3:::prm-service-dashboard-dev/*",
            ]
          + sid       = "AllowCloudFrontRead"

          + condition {
              + test     = "StringEquals"
              + values   = [
                  + "arn:aws:cloudfront::343515223843:distribution/ES60SAUQ8ZFXZ",
                ]
              + variable = "AWS:SourceArn"
            }

          + principals {
              + identifiers = [
                  + "cloudfront.amazonaws.com",
                ]
              + type        = "Service"
            }
        }
    }

  # aws_cloudfront_distribution.dashboard_s3_distribution will be updated in-place
  ~ resource "aws_cloudfront_distribution" "dashboard_s3_distribution" {
        id                              = "ES60SAUQ8ZFXZ"
        tags                            = {
            "ApplicationRole"     = "AwsCloudfrontDistribution"
            "BackupLocal"         = "False"
            "BackupRemote"        = "False"
            "CostCentre"          = "P0688/04"
            "CreatedBy"           = "gp2gp-reporting-infrastructure"
            "Customer"            = "NHS D"
            "DataType"            = "None"
            "Environment"         = "dev"
            "Name"                = "dev-GP2GP-service-dashboard"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "Candice Moore"
            "Programme"           = "GP IT Futures"
            "Project"             = "Patient Record Migration"
            "ProjectType"         = "Public beta"
            "PublicFacing"        = "Y"
            "ServiceCategory"     = "Bronze"
            "TagVersion"          = "1"
            "Team"                = "Registrations"
            "data_classification" = "1"
            "envtype"             = "dev"
        }
        # (24 unchanged attributes hidden)

      - origin {
          - connection_attempts         = 3 -> null
          - connection_timeout          = 10 -> null
          - domain_name                 = "prm-service-dashboard-dev.s3.eu-west-2.amazonaws.com" -> null
          - origin_access_control_id    = "E2OQ2VSHLUFC7V" -> null
          - origin_id                   = "prm-service-dashboard-dev" -> null
          - response_completion_timeout = 0 -> null
            # (1 unchanged attribute hidden)
        }
      + origin {
          + connection_attempts         = 3
          + connection_timeout          = 10
          + domain_name                 = "prm-service-dashboard-dev.s3.eu-west-2.amazonaws.com"
          + origin_access_control_id    = "E2OQ2VSHLUFC7V"
          + origin_id                   = "prm-service-dashboard-dev"
          + response_completion_timeout = 0
            # (1 unchanged attribute hidden)

          + s3_origin_config {
                # (1 unchanged attribute hidden)
            }
        }

        # (3 unchanged blocks hidden)
    }

  # aws_s3_bucket_policy.dashboard_website will be updated in-place
  ~ resource "aws_s3_bucket_policy" "dashboard_website" {
        id     = "prm-service-dashboard-dev"
      ~ policy = jsonencode(
            {
              - Statement = [
                  - {
                      - Action    = "s3:GetObject"
                      - Condition = {
                          - StringEquals = {
                              - "AWS:SourceArn" = "arn:aws:cloudfront::343515223843:distribution/ES60SAUQ8ZFXZ"
                            }
                        }
                      - Effect    = "Allow"
                      - Principal = {
                          - Service = "cloudfront.amazonaws.com"
                        }
                      - Resource  = "arn:aws:s3:::prm-service-dashboard-dev/*"
                      - Sid       = "AllowCloudFrontRead"
                    },
                ]
              - Version   = "2012-10-17"
            }
        ) -> (known after apply)
        # (2 unchanged attributes hidden)
    }

Plan: 0 to add, 2 to change, 0 to destroy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants