From 310a7fb69f4e7ad54bd5ae85616bc981bf79e333 Mon Sep 17 00:00:00 2001 From: TOEL2 Date: Fri, 17 Apr 2026 15:04:24 +0100 Subject: [PATCH 1/5] [ELI-702] enforcing code signing for the test environment --- infrastructure/modules/lambda/lambda.tf | 2 ++ infrastructure/modules/lambda/variables.tf | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/infrastructure/modules/lambda/lambda.tf b/infrastructure/modules/lambda/lambda.tf index db67f93ae..bbf8f0f48 100644 --- a/infrastructure/modules/lambda/lambda.tf +++ b/infrastructure/modules/lambda/lambda.tf @@ -11,6 +11,8 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" { source_code_hash = filebase64sha256(var.file_name) + code_signing_config_arn = contains(var.environments_with_signing, var.environment) ? aws_lambda_code_signing_config.signing_config.arn : null + runtime = var.runtime timeout = 30 memory_size = 2048 diff --git a/infrastructure/modules/lambda/variables.tf b/infrastructure/modules/lambda/variables.tf index ffc764976..85ffe6825 100644 --- a/infrastructure/modules/lambda/variables.tf +++ b/infrastructure/modules/lambda/variables.tf @@ -88,3 +88,8 @@ variable "hashing_secret_name" { description = "hashing secret name" type = string } + +variable "environments_with_signing" { + type = list(string) + default = ["test"] +} From 792890d43415ccfc5165e00439ae5383afe7fe9d Mon Sep 17 00:00:00 2001 From: TOEL2 Date: Tue, 21 Apr 2026 10:59:41 +0100 Subject: [PATCH 2/5] [ELI-702] applying change to preprod workflow by splitting base deploy --- .github/workflows/base-deploy.yml | 122 +++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/.github/workflows/base-deploy.yml b/.github/workflows/base-deploy.yml index 6679d6694..cbe7f3b27 100644 --- a/.github/workflows/base-deploy.yml +++ b/.github/workflows/base-deploy.yml @@ -159,11 +159,131 @@ jobs: name: lambda-${{ needs.metadata.outputs.tag }} path: ./dist/lambda.zip + sign-lambda-artifact: + name: "Sign lambda artifact for PreProd" + if: ${{ needs.metadata.outputs.environment == 'preprod' }} + runs-on: ubuntu-latest + needs: [ metadata, download-lambda-artifact ] + timeout-minutes: 45 + permissions: + id-token: write + contents: read + environment: preprod + steps: + - name: "Checkout repository at ref" + uses: actions/checkout@v6 + with: + ref: ${{ needs.metadata.outputs.ref }} + fetch-depth: 0 + + - name: "Setup Terraform" + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ needs.metadata.outputs.terraform_version }} + + - name: "Configure AWS Credentials" + uses: aws-actions/configure-aws-credentials@v6 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role + aws-region: eu-west-2 + + - name: "Download unsigned lambda artifact from current workflow" + uses: actions/download-artifact@v7 + with: + name: lambda-${{ needs.metadata.outputs.tag }} + path: ./dist + + - name: "Terraform Init (PREPROD api-layer)" + env: + ENVIRONMENT: preprod + WORKSPACE: "default" + run: | + echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=api-layer tf-command=init" + make terraform env=$ENVIRONMENT stack=api-layer tf-command=init workspace=$WORKSPACE + working-directory: ./infrastructure + + - name: "Extract PREPROD Terraform outputs" + id: preprod_tf_output + run: | + BUCKET=$(terraform output -raw lambda_artifact_bucket) + PROFILE=$(terraform output -raw signing_profile_name) + echo "bucket_name=$BUCKET" >> $GITHUB_OUTPUT + echo "signing_profile_name=$PROFILE" >> $GITHUB_OUTPUT + working-directory: ./infrastructure/stacks/api-layer + + - name: "Upload unsigned lambda artifact to PREPROD S3" + run: | + aws s3 cp ./dist/lambda.zip \ + s3://${{ steps.preprod_tf_output.outputs.bucket_name }}/artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip \ + --region eu-west-2 + + - name: "Get uploaded source object version" + id: source_object + run: | + VERSION_ID=$(aws s3api head-object \ + --bucket "${{ steps.preprod_tf_output.outputs.bucket_name }}" \ + --key "artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip" \ + --query 'VersionId' \ + --output text \ + --region eu-west-2) + echo "version_id=$VERSION_ID" >> $GITHUB_OUTPUT + + - name: "Start signing job" + id: signing + env: + SIGNING_PROFILE_NAME: ${{ steps.preprod_tf_output.outputs.signing_profile_name }} + run: | + JOB_ID=$(aws signer start-signing-job \ + --source "s3={bucketName=${{ steps.preprod_tf_output.outputs.bucket_name }},key=artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip,version=${{ steps.source_object.outputs.version_id }}}" \ + --destination "s3={bucketName=${{ steps.preprod_tf_output.outputs.bucket_name }},prefix=signed-artifacts/${{ needs.metadata.outputs.tag }}/}" \ + --profile-name "$SIGNING_PROFILE_NAME" \ + --query 'jobId' \ + --output text \ + --region eu-west-2) + echo "job_id=$JOB_ID" >> $GITHUB_OUTPUT + + - name: "Wait for signing job" + run: | + aws signer wait successful-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 + + - name: "Resolve signed artifact location" + id: signed_object + run: | + SIGNED_BUCKET=$(aws signer describe-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 \ + --query 'signedObject.s3.bucketName' \ + --output text) + + SIGNED_KEY=$(aws signer describe-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 \ + --query 'signedObject.s3.key' \ + --output text) + + echo "bucket_name=$SIGNED_BUCKET" >> $GITHUB_OUTPUT + echo "object_key=$SIGNED_KEY" >> $GITHUB_OUTPUT + + - name: "Download signed lambda artifact" + run: | + aws s3 cp \ + "s3://${{ steps.signed_object.outputs.bucket_name }}/${{ steps.signed_object.outputs.object_key }}" \ + ./dist/lambda.zip \ + --region eu-west-2 + + - name: "Upload signed lambda artifact for current workflow" + uses: actions/upload-artifact@v6 + with: + name: lambda-${{ needs.metadata.outputs.tag }} + path: ./dist/lambda.zip + deploy: name: "Deploy to ${{ needs.metadata.outputs.environment }}" runs-on: ubuntu-latest - needs: [metadata, download-lambda-artifact] + needs: [metadata, download-lambda-artifact, sign-lambda-artifact] timeout-minutes: 45 permissions: id-token: write From d4ea35be0d9afe63e83b11d69671e21b1b1d43ce Mon Sep 17 00:00:00 2001 From: TOEL2 Date: Tue, 21 Apr 2026 11:11:36 +0100 Subject: [PATCH 3/5] [ELI-702] creating a separate deploy path --- .github/workflows/base-deploy.yml | 125 +++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 12 deletions(-) diff --git a/.github/workflows/base-deploy.yml b/.github/workflows/base-deploy.yml index cbe7f3b27..defc58fcc 100644 --- a/.github/workflows/base-deploy.yml +++ b/.github/workflows/base-deploy.yml @@ -276,19 +276,123 @@ jobs: - name: "Upload signed lambda artifact for current workflow" uses: actions/upload-artifact@v6 with: - name: lambda-${{ needs.metadata.outputs.tag }} + name: lambda-signed-${{ needs.metadata.outputs.tag }} path: ./dist/lambda.zip - deploy: - name: "Deploy to ${{ needs.metadata.outputs.environment }}" + deploy-preprod: + name: "Deploy to preprod" + if: ${{ needs.metadata.outputs.environment == 'preprod' }} runs-on: ubuntu-latest needs: [metadata, download-lambda-artifact, sign-lambda-artifact] timeout-minutes: 45 permissions: id-token: write contents: write - environment: ${{ needs.metadata.outputs.environment }} + environment: preprod + steps: + - name: "Checkout repository at ref" + uses: actions/checkout@v6 + with: + ref: ${{ needs.metadata.outputs.ref }} + fetch-depth: 0 + + - name: "Setup Terraform" + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ needs.metadata.outputs.terraform_version }} + + - name: "Download signed Lambda Artifact" + uses: actions/download-artifact@v7 + with: + name: lambda-signed-${{ needs.metadata.outputs.tag }} + path: ./dist + + - name: "Configure AWS Credentials (IAM Bootstrap Role)" + uses: aws-actions/configure-aws-credentials@v6 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-iam-bootstrap-role + aws-region: eu-west-2 + + - name: "Deploy IAM roles (iams-developer-roles stack)" + working-directory: ./infrastructure + run: | + make terraform env=preprod stack=iams-developer-roles tf-command=apply workspace=default + + - name: "Configure AWS Credentials (Main Deployment Role)" + uses: aws-actions/configure-aws-credentials@v6 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role + aws-region: eu-west-2 + + - name: "Terraform Apply" + env: + ENVIRONMENT: preprod + WORKSPACE: "default" + TF_VAR_API_CA_CERT: ${{ secrets.API_CA_CERT }} + TF_VAR_API_CLIENT_CERT: ${{ secrets.API_CLIENT_CERT }} + TF_VAR_API_PRIVATE_KEY_CERT: ${{ secrets.API_PRIVATE_KEY_CERT }} + TF_VAR_SPLUNK_HEC_TOKEN: ${{ secrets.SPLUNK_HEC_TOKEN }} + TF_VAR_SPLUNK_HEC_ENDPOINT: ${{ secrets.SPLUNK_HEC_ENDPOINT }} + TF_VAR_OPERATOR_EMAILS: ${{ vars.SECRET_ROTATION_OPERATOR_EMAILS }} + TF_VAR_PROXYGEN_PRIVATE_KEY_PTL: ${{ secrets.PROXYGEN_PRIVATE_KEY_PTL }} + TF_VAR_PROXYGEN_PRIVATE_KEY_PROD: ${{ secrets.PROXYGEN_PRIVATE_KEY_PROD }} + working-directory: ./infrastructure + shell: bash + run: | + set -euo pipefail + mkdir -p ./build + echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=networking tf-command=apply" + make terraform env=$ENVIRONMENT stack=networking tf-command=apply workspace=$WORKSPACE + echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=api-layer tf-command=apply" + make terraform env=$ENVIRONMENT stack=api-layer tf-command=apply workspace=$WORKSPACE + + - name: "Extract S3 bucket name from Terraform output" + id: tf_output + run: | + BUCKET=$(terraform output -raw lambda_artifact_bucket) + echo "bucket_name=$BUCKET" >> $GITHUB_OUTPUT + working-directory: ./infrastructure/stacks/api-layer + + - name: "Validate Feature Toggles" + env: + ENV: preprod + run: | + pip install boto3 + python scripts/feature_toggle/validate_toggles.py + + - name: "Tag and Release" + env: + ENVIRONMENT: preprod + REF: ${{ needs.metadata.outputs.ref }} + INPUT_RELEASE_TYPE: ${{ inputs.release_type }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository }} + run: | + pip install requests + python scripts/workflow/tag_and_release.py + + - name: "Capture release tag" + id: release_tag + run: | + echo "release_tag=$(cat release_tag.txt)" >> $GITHUB_OUTPUT + + - name: "Upload lambda artifact to S3" + run: | + aws s3 cp ./dist/lambda.zip \ + s3://${{ steps.tf_output.outputs.bucket_name }}/artifacts/${{ steps.release_tag.outputs.release_tag }}/lambda.zip \ + --region eu-west-2 + + deploy-prod: + name: "Deploy to prod" + if: ${{ needs.metadata.outputs.environment == 'prod' }} + runs-on: ubuntu-latest + needs: [metadata, download-lambda-artifact] + timeout-minutes: 45 + permissions: + id-token: write + contents: write + environment: prod steps: - name: "Checkout repository at ref" uses: actions/checkout@v6 @@ -316,7 +420,7 @@ jobs: - name: "Deploy IAM roles (iams-developer-roles stack)" working-directory: ./infrastructure run: | - make terraform env=${{ needs.metadata.outputs.environment }} stack=iams-developer-roles tf-command=apply workspace=default + make terraform env=prod stack=iams-developer-roles tf-command=apply workspace=default - name: "Configure AWS Credentials (Main Deployment Role)" uses: aws-actions/configure-aws-credentials@v6 @@ -326,7 +430,7 @@ jobs: - name: "Terraform Apply" env: - ENVIRONMENT: ${{ needs.metadata.outputs.environment }} + ENVIRONMENT: prod WORKSPACE: "default" TF_VAR_API_CA_CERT: ${{ secrets.API_CA_CERT }} TF_VAR_API_CLIENT_CERT: ${{ secrets.API_CLIENT_CERT }} @@ -336,7 +440,6 @@ jobs: TF_VAR_OPERATOR_EMAILS: ${{ vars.SECRET_ROTATION_OPERATOR_EMAILS }} TF_VAR_PROXYGEN_PRIVATE_KEY_PTL: ${{ secrets.PROXYGEN_PRIVATE_KEY_PTL }} TF_VAR_PROXYGEN_PRIVATE_KEY_PROD: ${{ secrets.PROXYGEN_PRIVATE_KEY_PROD }} - working-directory: ./infrastructure shell: bash run: | @@ -356,15 +459,14 @@ jobs: - name: "Validate Feature Toggles" env: - ENV: ${{ needs.metadata.outputs.environment }} + ENV: prod run: | pip install boto3 python scripts/feature_toggle/validate_toggles.py - name: "Tag and Release" - if: ${{ needs.metadata.outputs.environment == 'preprod' || needs.metadata.outputs.environment == 'prod' }} env: - ENVIRONMENT: ${{ needs.metadata.outputs.environment }} + ENVIRONMENT: prod REF: ${{ needs.metadata.outputs.ref }} INPUT_RELEASE_TYPE: ${{ inputs.release_type }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -384,11 +486,10 @@ jobs: s3://${{ steps.tf_output.outputs.bucket_name }}/artifacts/${{ steps.release_tag.outputs.release_tag }}/lambda.zip \ --region eu-west-2 - regression-tests: name: "Regression Tests" if: ${{ needs.metadata.outputs.environment == 'preprod' }} - needs: deploy + needs: deploy-preprod uses: ./.github/workflows/regression-tests.yml with: ENVIRONMENT: "preprod" From 4ac3721817ffef7aee8108576a511735e0fcdd2b Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:08:33 +0100 Subject: [PATCH 4/5] eli-731 enabling code signing enforcement in preprod --- infrastructure/modules/lambda/lambda.tf | 11 +++++------ infrastructure/stacks/api-layer/lambda.tf | 7 ++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/infrastructure/modules/lambda/lambda.tf b/infrastructure/modules/lambda/lambda.tf index bbf8f0f48..e44e948d8 100644 --- a/infrastructure/modules/lambda/lambda.tf +++ b/infrastructure/modules/lambda/lambda.tf @@ -1,7 +1,7 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" { #checkov:skip=CKV_AWS_116: No deadletter queue is configured for this Lambda function, as the requests are synchronous #checkov:skip=CKV_AWS_115: Concurrent execution limit will be set at APIM level, not at Lambda level - #checkov:skip=CKV_AWS_272: Skipping code signing but flagged to create ticket to investigate on ELI-238 + #checkov:skip=CKV_AWS_272: Code signing not yet enforced in prod - tracked for removal when prod enforcement is enabled # If the file is not in the current working directory you will need to include a # path.module in the filename. filename = var.file_name @@ -41,10 +41,10 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" { } layers = compact([ - var.environment == "prod" || var.environment == "preprod" ? - "arn:aws:lambda:${var.region}:580247275435:layer:LambdaInsightsExtension:${var.lambda_insights_extension_version}" - : - null + var.environment == "prod" || var.environment == "preprod" ? + "arn:aws:lambda:${var.region}:580247275435:layer:LambdaInsightsExtension:${var.lambda_insights_extension_version}" + : + null ]) @@ -68,4 +68,3 @@ resource "aws_lambda_provisioned_concurrency_config" "campaign_pc" { qualifier = aws_lambda_alias.campaign_alias[0].name provisioned_concurrent_executions = var.provisioned_concurrency_count } - diff --git a/infrastructure/stacks/api-layer/lambda.tf b/infrastructure/stacks/api-layer/lambda.tf index b3eba1568..cb38efb79 100644 --- a/infrastructure/stacks/api-layer/lambda.tf +++ b/infrastructure/stacks/api-layer/lambda.tf @@ -18,7 +18,7 @@ module "eligibility_signposting_lambda_function" { environment = var.environment runtime = "python3.13" lambda_func_name = "${terraform.workspace == "default" ? "" : "${terraform.workspace}-"}eligibility_signposting_api" - security_group_ids = [data.aws_security_group.main_sg.id] + security_group_ids = [data.aws_security_group.main_sg.id] vpc_intra_subnets = [for v in data.aws_subnet.private_subnets : v.id] file_name = "../../../dist/lambda.zip" handler = "eligibility_signposting_api.app.lambda_handler" @@ -33,6 +33,7 @@ module "eligibility_signposting_lambda_function" { stack_name = local.stack_name provisioned_concurrency_count = 5 api_domain_name = local.api_domain_name + environments_with_signing = ["test", "preprod"] } @@ -69,7 +70,7 @@ resource "aws_lambda_function" "create_secret_lambda" { variables = { SECRET_NAME = module.secrets_manager.aws_hashing_secret_name } } vpc_config { - subnet_ids = [for s in data.aws_subnet.private_subnets : s.id] + subnet_ids = [for s in data.aws_subnet.private_subnets : s.id] security_group_ids = [data.aws_security_group.main_sg.id] } } @@ -98,7 +99,7 @@ resource "aws_lambda_function" "promote_secret_lambda" { variables = { SECRET_NAME = module.secrets_manager.aws_hashing_secret_name } } vpc_config { - subnet_ids = [for s in data.aws_subnet.private_subnets : s.id] + subnet_ids = [for s in data.aws_subnet.private_subnets : s.id] security_group_ids = [data.aws_security_group.main_sg.id] } } From 390b97455d33e62d36d05c74eb8adf463ee1ebf5 Mon Sep 17 00:00:00 2001 From: Edd Almond <102675624+eddalmond1@users.noreply.github.com> Date: Mon, 27 Apr 2026 17:13:51 +0100 Subject: [PATCH 5/5] eli-702 enabling code signing in prod --- .github/workflows/base-deploy.yml | 129 +++++++++++++++++++++- infrastructure/modules/lambda/lambda.tf | 1 - infrastructure/stacks/api-layer/lambda.tf | 2 +- 3 files changed, 125 insertions(+), 7 deletions(-) diff --git a/.github/workflows/base-deploy.yml b/.github/workflows/base-deploy.yml index 2e01aaec7..31a50421e 100644 --- a/.github/workflows/base-deploy.yml +++ b/.github/workflows/base-deploy.yml @@ -163,7 +163,7 @@ jobs: name: "Sign lambda artifact for PreProd" if: ${{ needs.metadata.outputs.environment == 'preprod' }} runs-on: ubuntu-latest - needs: [ metadata, download-lambda-artifact ] + needs: [metadata, download-lambda-artifact] timeout-minutes: 45 permissions: id-token: write @@ -279,7 +279,6 @@ jobs: name: lambda-signed-${{ needs.metadata.outputs.tag }} path: ./dist/lambda.zip - deploy-preprod: name: "Deploy to preprod" if: ${{ needs.metadata.outputs.environment == 'preprod' }} @@ -383,11 +382,131 @@ jobs: s3://${{ steps.tf_output.outputs.bucket_name }}/artifacts/${{ steps.release_tag.outputs.release_tag }}/lambda.zip \ --region eu-west-2 + sign-lambda-artifact-prod: + name: "Sign lambda artifact for Prod" + if: ${{ needs.metadata.outputs.environment == 'prod' }} + runs-on: ubuntu-latest + needs: [metadata, download-lambda-artifact] + timeout-minutes: 45 + permissions: + id-token: write + contents: read + environment: prod + steps: + - name: "Checkout repository at ref" + uses: actions/checkout@v6 + with: + ref: ${{ needs.metadata.outputs.ref }} + fetch-depth: 0 + + - name: "Setup Terraform" + uses: hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ needs.metadata.outputs.terraform_version }} + + - name: "Configure AWS Credentials" + uses: aws-actions/configure-aws-credentials@v6 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role + aws-region: eu-west-2 + + - name: "Download unsigned lambda artifact from current workflow" + uses: actions/download-artifact@v7 + with: + name: lambda-${{ needs.metadata.outputs.tag }} + path: ./dist + + - name: "Terraform Init (PROD api-layer)" + env: + ENVIRONMENT: prod + WORKSPACE: "default" + run: | + echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=api-layer tf-command=init" + make terraform env=$ENVIRONMENT stack=api-layer tf-command=init workspace=$WORKSPACE + working-directory: ./infrastructure + + - name: "Extract PROD Terraform outputs" + id: prod_tf_output + run: | + BUCKET=$(terraform output -raw lambda_artifact_bucket) + PROFILE=$(terraform output -raw signing_profile_name) + echo "bucket_name=$BUCKET" >> $GITHUB_OUTPUT + echo "signing_profile_name=$PROFILE" >> $GITHUB_OUTPUT + working-directory: ./infrastructure/stacks/api-layer + + - name: "Upload unsigned lambda artifact to PROD S3" + run: | + aws s3 cp ./dist/lambda.zip \ + s3://${{ steps.prod_tf_output.outputs.bucket_name }}/artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip \ + --region eu-west-2 + + - name: "Get uploaded source object version" + id: source_object + run: | + VERSION_ID=$(aws s3api head-object \ + --bucket "${{ steps.prod_tf_output.outputs.bucket_name }}" \ + --key "artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip" \ + --query 'VersionId' \ + --output text \ + --region eu-west-2) + echo "version_id=$VERSION_ID" >> $GITHUB_OUTPUT + + - name: "Start signing job" + id: signing + env: + SIGNING_PROFILE_NAME: ${{ steps.prod_tf_output.outputs.signing_profile_name }} + run: | + JOB_ID=$(aws signer start-signing-job \ + --source "s3={bucketName=${{ steps.prod_tf_output.outputs.bucket_name }},key=artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip,version=${{ steps.source_object.outputs.version_id }}}" \ + --destination "s3={bucketName=${{ steps.prod_tf_output.outputs.bucket_name }},prefix=signed-artifacts/${{ needs.metadata.outputs.tag }}/}" \ + --profile-name "$SIGNING_PROFILE_NAME" \ + --query 'jobId' \ + --output text \ + --region eu-west-2) + echo "job_id=$JOB_ID" >> $GITHUB_OUTPUT + + - name: "Wait for signing job" + run: | + aws signer wait successful-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 + + - name: "Resolve signed artifact location" + id: signed_object + run: | + SIGNED_BUCKET=$(aws signer describe-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 \ + --query 'signedObject.s3.bucketName' \ + --output text) + + SIGNED_KEY=$(aws signer describe-signing-job \ + --job-id "${{ steps.signing.outputs.job_id }}" \ + --region eu-west-2 \ + --query 'signedObject.s3.key' \ + --output text) + + echo "bucket_name=$SIGNED_BUCKET" >> $GITHUB_OUTPUT + echo "object_key=$SIGNED_KEY" >> $GITHUB_OUTPUT + + - name: "Download signed lambda artifact" + run: | + aws s3 cp \ + "s3://${{ steps.signed_object.outputs.bucket_name }}/${{ steps.signed_object.outputs.object_key }}" \ + ./dist/lambda.zip \ + --region eu-west-2 + + - name: "Upload signed lambda artifact for current workflow" + uses: actions/upload-artifact@v6 + with: + name: lambda-signed-${{ needs.metadata.outputs.tag }} + path: ./dist/lambda.zip + deploy-prod: name: "Deploy to prod" if: ${{ needs.metadata.outputs.environment == 'prod' }} runs-on: ubuntu-latest - needs: [metadata, download-lambda-artifact] + needs: [metadata, download-lambda-artifact, sign-lambda-artifact-prod] timeout-minutes: 45 permissions: id-token: write @@ -405,10 +524,10 @@ jobs: with: terraform_version: ${{ needs.metadata.outputs.terraform_version }} - - name: "Download Lambda Artifact" + - name: "Download signed Lambda Artifact" uses: actions/download-artifact@v7 with: - name: lambda-${{ needs.metadata.outputs.tag }} + name: lambda-signed-${{ needs.metadata.outputs.tag }} path: ./dist - name: "Configure AWS Credentials (IAM Bootstrap Role)" diff --git a/infrastructure/modules/lambda/lambda.tf b/infrastructure/modules/lambda/lambda.tf index e44e948d8..fa992d355 100644 --- a/infrastructure/modules/lambda/lambda.tf +++ b/infrastructure/modules/lambda/lambda.tf @@ -1,7 +1,6 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" { #checkov:skip=CKV_AWS_116: No deadletter queue is configured for this Lambda function, as the requests are synchronous #checkov:skip=CKV_AWS_115: Concurrent execution limit will be set at APIM level, not at Lambda level - #checkov:skip=CKV_AWS_272: Code signing not yet enforced in prod - tracked for removal when prod enforcement is enabled # If the file is not in the current working directory you will need to include a # path.module in the filename. filename = var.file_name diff --git a/infrastructure/stacks/api-layer/lambda.tf b/infrastructure/stacks/api-layer/lambda.tf index cb38efb79..7a4c53f8e 100644 --- a/infrastructure/stacks/api-layer/lambda.tf +++ b/infrastructure/stacks/api-layer/lambda.tf @@ -33,7 +33,7 @@ module "eligibility_signposting_lambda_function" { stack_name = local.stack_name provisioned_concurrency_count = 5 api_domain_name = local.api_domain_name - environments_with_signing = ["test", "preprod"] + environments_with_signing = ["test", "preprod", "prod"] }