Skip to content

Commit 13f79b7

Browse files
authored
Merge branch 'main' into eli-786/status_text_integration_tests_and_config
2 parents e571ccc + 78902f1 commit 13f79b7

4 files changed

Lines changed: 251 additions & 20 deletions

File tree

.github/workflows/base-deploy.yml

Lines changed: 234 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,21 +153,246 @@ jobs:
153153
./dist/lambda.zip \
154154
--region eu-west-2
155155
156-
- name: "Upload lambda artifact for the current workflow"
156+
- name: "Upload lambda artifact for downstream jobs"
157157
uses: actions/upload-artifact@v6
158158
with:
159159
name: lambda-${{ needs.metadata.outputs.tag }}
160160
path: ./dist/lambda.zip
161161

162-
deploy:
163-
name: "Deploy to ${{ needs.metadata.outputs.environment }}"
162+
sign-lambda-artifact:
163+
name: "Sign lambda artifact for PreProd"
164+
if: ${{ needs.metadata.outputs.environment == 'preprod' }}
165+
runs-on: ubuntu-latest
166+
needs: [ metadata, download-lambda-artifact ]
167+
timeout-minutes: 45
168+
permissions:
169+
id-token: write
170+
contents: read
171+
environment: preprod
172+
steps:
173+
- name: "Checkout repository at ref"
174+
uses: actions/checkout@v6
175+
with:
176+
ref: ${{ needs.metadata.outputs.ref }}
177+
fetch-depth: 0
178+
179+
- name: "Setup Terraform"
180+
uses: hashicorp/setup-terraform@v3
181+
with:
182+
terraform_version: ${{ needs.metadata.outputs.terraform_version }}
183+
184+
- name: "Configure AWS Credentials"
185+
uses: aws-actions/configure-aws-credentials@v6
186+
with:
187+
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
188+
aws-region: eu-west-2
189+
190+
- name: "Download unsigned lambda artifact from current workflow"
191+
uses: actions/download-artifact@v7
192+
with:
193+
name: lambda-${{ needs.metadata.outputs.tag }}
194+
path: ./dist
195+
196+
- name: "Terraform Init (PREPROD api-layer)"
197+
env:
198+
ENVIRONMENT: preprod
199+
WORKSPACE: "default"
200+
run: |
201+
echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=api-layer tf-command=init"
202+
make terraform env=$ENVIRONMENT stack=api-layer tf-command=init workspace=$WORKSPACE
203+
working-directory: ./infrastructure
204+
205+
- name: "Extract PREPROD Terraform outputs"
206+
id: preprod_tf_output
207+
run: |
208+
BUCKET=$(terraform output -raw lambda_artifact_bucket)
209+
PROFILE=$(terraform output -raw signing_profile_name)
210+
echo "bucket_name=$BUCKET" >> $GITHUB_OUTPUT
211+
echo "signing_profile_name=$PROFILE" >> $GITHUB_OUTPUT
212+
working-directory: ./infrastructure/stacks/api-layer
213+
214+
- name: "Upload unsigned lambda artifact to PREPROD S3"
215+
run: |
216+
aws s3 cp ./dist/lambda.zip \
217+
s3://${{ steps.preprod_tf_output.outputs.bucket_name }}/artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip \
218+
--region eu-west-2
219+
220+
- name: "Get uploaded source object version"
221+
id: source_object
222+
run: |
223+
VERSION_ID=$(aws s3api head-object \
224+
--bucket "${{ steps.preprod_tf_output.outputs.bucket_name }}" \
225+
--key "artifacts/${{ needs.metadata.outputs.tag }}/lambda.zip" \
226+
--query 'VersionId' \
227+
--output text \
228+
--region eu-west-2)
229+
echo "version_id=$VERSION_ID" >> $GITHUB_OUTPUT
230+
231+
- name: "Start signing job"
232+
id: signing
233+
env:
234+
SIGNING_PROFILE_NAME: ${{ steps.preprod_tf_output.outputs.signing_profile_name }}
235+
run: |
236+
JOB_ID=$(aws signer start-signing-job \
237+
--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 }}}" \
238+
--destination "s3={bucketName=${{ steps.preprod_tf_output.outputs.bucket_name }},prefix=signed-artifacts/${{ needs.metadata.outputs.tag }}/}" \
239+
--profile-name "$SIGNING_PROFILE_NAME" \
240+
--query 'jobId' \
241+
--output text \
242+
--region eu-west-2)
243+
echo "job_id=$JOB_ID" >> $GITHUB_OUTPUT
244+
245+
- name: "Wait for signing job"
246+
run: |
247+
aws signer wait successful-signing-job \
248+
--job-id "${{ steps.signing.outputs.job_id }}" \
249+
--region eu-west-2
250+
251+
- name: "Resolve signed artifact location"
252+
id: signed_object
253+
run: |
254+
SIGNED_BUCKET=$(aws signer describe-signing-job \
255+
--job-id "${{ steps.signing.outputs.job_id }}" \
256+
--region eu-west-2 \
257+
--query 'signedObject.s3.bucketName' \
258+
--output text)
259+
260+
SIGNED_KEY=$(aws signer describe-signing-job \
261+
--job-id "${{ steps.signing.outputs.job_id }}" \
262+
--region eu-west-2 \
263+
--query 'signedObject.s3.key' \
264+
--output text)
265+
266+
echo "bucket_name=$SIGNED_BUCKET" >> $GITHUB_OUTPUT
267+
echo "object_key=$SIGNED_KEY" >> $GITHUB_OUTPUT
268+
269+
- name: "Download signed lambda artifact"
270+
run: |
271+
aws s3 cp \
272+
"s3://${{ steps.signed_object.outputs.bucket_name }}/${{ steps.signed_object.outputs.object_key }}" \
273+
./dist/lambda.zip \
274+
--region eu-west-2
275+
276+
- name: "Upload signed lambda artifact for current workflow"
277+
uses: actions/upload-artifact@v6
278+
with:
279+
name: lambda-signed-${{ needs.metadata.outputs.tag }}
280+
path: ./dist/lambda.zip
281+
282+
283+
deploy-preprod:
284+
name: "Deploy to preprod"
285+
if: ${{ needs.metadata.outputs.environment == 'preprod' }}
286+
runs-on: ubuntu-latest
287+
needs: [metadata, download-lambda-artifact, sign-lambda-artifact]
288+
timeout-minutes: 45
289+
permissions:
290+
id-token: write
291+
contents: write
292+
environment: preprod
293+
steps:
294+
- name: "Checkout repository at ref"
295+
uses: actions/checkout@v6
296+
with:
297+
ref: ${{ needs.metadata.outputs.ref }}
298+
fetch-depth: 0
299+
300+
- name: "Setup Terraform"
301+
uses: hashicorp/setup-terraform@v3
302+
with:
303+
terraform_version: ${{ needs.metadata.outputs.terraform_version }}
304+
305+
- name: "Download signed Lambda Artifact"
306+
uses: actions/download-artifact@v7
307+
with:
308+
name: lambda-signed-${{ needs.metadata.outputs.tag }}
309+
path: ./dist
310+
311+
- name: "Configure AWS Credentials (IAM Bootstrap Role)"
312+
uses: aws-actions/configure-aws-credentials@v6
313+
with:
314+
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-iam-bootstrap-role
315+
aws-region: eu-west-2
316+
317+
- name: "Deploy IAM roles (iams-developer-roles stack)"
318+
working-directory: ./infrastructure
319+
run: |
320+
make terraform env=preprod stack=iams-developer-roles tf-command=apply workspace=default
321+
322+
- name: "Configure AWS Credentials (Main Deployment Role)"
323+
uses: aws-actions/configure-aws-credentials@v6
324+
with:
325+
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/service-roles/github-actions-api-deployment-role
326+
aws-region: eu-west-2
327+
328+
- name: "Terraform Apply"
329+
env:
330+
ENVIRONMENT: preprod
331+
WORKSPACE: "default"
332+
TF_VAR_API_CA_CERT: ${{ secrets.API_CA_CERT }}
333+
TF_VAR_API_CLIENT_CERT: ${{ secrets.API_CLIENT_CERT }}
334+
TF_VAR_API_PRIVATE_KEY_CERT: ${{ secrets.API_PRIVATE_KEY_CERT }}
335+
TF_VAR_SPLUNK_HEC_TOKEN: ${{ secrets.SPLUNK_HEC_TOKEN }}
336+
TF_VAR_SPLUNK_HEC_ENDPOINT: ${{ secrets.SPLUNK_HEC_ENDPOINT }}
337+
TF_VAR_OPERATOR_EMAILS: ${{ vars.SECRET_ROTATION_OPERATOR_EMAILS }}
338+
TF_VAR_PROXYGEN_PRIVATE_KEY_PTL: ${{ secrets.PROXYGEN_PRIVATE_KEY_PTL }}
339+
TF_VAR_PROXYGEN_PRIVATE_KEY_PROD: ${{ secrets.PROXYGEN_PRIVATE_KEY_PROD }}
340+
working-directory: ./infrastructure
341+
shell: bash
342+
run: |
343+
set -euo pipefail
344+
mkdir -p ./build
345+
echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=networking tf-command=apply"
346+
make terraform env=$ENVIRONMENT stack=networking tf-command=apply workspace=$WORKSPACE
347+
echo "Running: make terraform env=$ENVIRONMENT workspace=$WORKSPACE stack=api-layer tf-command=apply"
348+
make terraform env=$ENVIRONMENT stack=api-layer tf-command=apply workspace=$WORKSPACE
349+
350+
- name: "Extract S3 bucket name from Terraform output"
351+
id: tf_output
352+
run: |
353+
BUCKET=$(terraform output -raw lambda_artifact_bucket)
354+
echo "bucket_name=$BUCKET" >> $GITHUB_OUTPUT
355+
working-directory: ./infrastructure/stacks/api-layer
356+
357+
- name: "Validate Feature Toggles"
358+
env:
359+
ENV: preprod
360+
run: |
361+
pip install boto3
362+
python scripts/feature_toggle/validate_toggles.py
363+
364+
- name: "Tag and Release"
365+
env:
366+
ENVIRONMENT: preprod
367+
REF: ${{ needs.metadata.outputs.ref }}
368+
INPUT_RELEASE_TYPE: ${{ inputs.release_type }}
369+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
370+
GITHUB_REPOSITORY: ${{ github.repository }}
371+
run: |
372+
pip install requests
373+
python scripts/workflow/tag_and_release.py
374+
375+
- name: "Capture release tag"
376+
id: release_tag
377+
run: |
378+
echo "release_tag=$(cat release_tag.txt)" >> $GITHUB_OUTPUT
379+
380+
- name: "Upload lambda artifact to S3"
381+
run: |
382+
aws s3 cp ./dist/lambda.zip \
383+
s3://${{ steps.tf_output.outputs.bucket_name }}/artifacts/${{ steps.release_tag.outputs.release_tag }}/lambda.zip \
384+
--region eu-west-2
385+
386+
deploy-prod:
387+
name: "Deploy to prod"
388+
if: ${{ needs.metadata.outputs.environment == 'prod' }}
164389
runs-on: ubuntu-latest
165390
needs: [metadata, download-lambda-artifact]
166391
timeout-minutes: 45
167392
permissions:
168393
id-token: write
169394
contents: write
170-
environment: ${{ needs.metadata.outputs.environment }}
395+
environment: prod
171396
steps:
172397
- name: "Checkout repository at ref"
173398
uses: actions/checkout@v6
@@ -195,7 +420,7 @@ jobs:
195420
- name: "Deploy IAM roles (iams-developer-roles stack)"
196421
working-directory: ./infrastructure
197422
run: |
198-
make terraform env=${{ needs.metadata.outputs.environment }} stack=iams-developer-roles tf-command=apply workspace=default
423+
make terraform env=prod stack=iams-developer-roles tf-command=apply workspace=default
199424
200425
- name: "Configure AWS Credentials (Main Deployment Role)"
201426
uses: aws-actions/configure-aws-credentials@v6
@@ -205,7 +430,7 @@ jobs:
205430

206431
- name: "Terraform Apply"
207432
env:
208-
ENVIRONMENT: ${{ needs.metadata.outputs.environment }}
433+
ENVIRONMENT: prod
209434
WORKSPACE: "default"
210435
TF_VAR_API_CA_CERT: ${{ secrets.API_CA_CERT }}
211436
TF_VAR_API_CLIENT_CERT: ${{ secrets.API_CLIENT_CERT }}
@@ -215,7 +440,6 @@ jobs:
215440
TF_VAR_OPERATOR_EMAILS: ${{ vars.SECRET_ROTATION_OPERATOR_EMAILS }}
216441
TF_VAR_PROXYGEN_PRIVATE_KEY_PTL: ${{ secrets.PROXYGEN_PRIVATE_KEY_PTL }}
217442
TF_VAR_PROXYGEN_PRIVATE_KEY_PROD: ${{ secrets.PROXYGEN_PRIVATE_KEY_PROD }}
218-
219443
working-directory: ./infrastructure
220444
shell: bash
221445
run: |
@@ -235,15 +459,14 @@ jobs:
235459

236460
- name: "Validate Feature Toggles"
237461
env:
238-
ENV: ${{ needs.metadata.outputs.environment }}
462+
ENV: prod
239463
run: |
240464
pip install boto3
241465
python scripts/feature_toggle/validate_toggles.py
242466
243467
- name: "Tag and Release"
244-
if: ${{ needs.metadata.outputs.environment == 'preprod' || needs.metadata.outputs.environment == 'prod' }}
245468
env:
246-
ENVIRONMENT: ${{ needs.metadata.outputs.environment }}
469+
ENVIRONMENT: prod
247470
REF: ${{ needs.metadata.outputs.ref }}
248471
INPUT_RELEASE_TYPE: ${{ inputs.release_type }}
249472
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -266,7 +489,7 @@ jobs:
266489
regression-tests:
267490
name: "Regression Tests"
268491
if: ${{ needs.metadata.outputs.environment == 'preprod' }}
269-
needs: deploy
492+
needs: deploy-preprod
270493
permissions:
271494
id-token: write
272495
contents: read

infrastructure/modules/lambda/lambda.tf

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
resource "aws_lambda_function" "eligibility_signposting_lambda" {
22
#checkov:skip=CKV_AWS_116: No deadletter queue is configured for this Lambda function, as the requests are synchronous
33
#checkov:skip=CKV_AWS_115: Concurrent execution limit will be set at APIM level, not at Lambda level
4-
#checkov:skip=CKV_AWS_272: Skipping code signing but flagged to create ticket to investigate on ELI-238
4+
#checkov:skip=CKV_AWS_272: Code signing not yet enforced in prod - tracked for removal when prod enforcement is enabled
55
# If the file is not in the current working directory you will need to include a
66
# path.module in the filename.
77
filename = var.file_name
@@ -11,6 +11,8 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" {
1111

1212
source_code_hash = filebase64sha256(var.file_name)
1313

14+
code_signing_config_arn = contains(var.environments_with_signing, var.environment) ? aws_lambda_code_signing_config.signing_config.arn : null
15+
1416
runtime = var.runtime
1517
timeout = 30
1618
memory_size = 2048
@@ -39,10 +41,10 @@ resource "aws_lambda_function" "eligibility_signposting_lambda" {
3941
}
4042

4143
layers = compact([
42-
var.environment == "prod" || var.environment == "preprod" ?
43-
"arn:aws:lambda:${var.region}:580247275435:layer:LambdaInsightsExtension:${var.lambda_insights_extension_version}"
44-
:
45-
null
44+
var.environment == "prod" || var.environment == "preprod" ?
45+
"arn:aws:lambda:${var.region}:580247275435:layer:LambdaInsightsExtension:${var.lambda_insights_extension_version}"
46+
:
47+
null
4648
])
4749

4850

@@ -66,4 +68,3 @@ resource "aws_lambda_provisioned_concurrency_config" "campaign_pc" {
6668
qualifier = aws_lambda_alias.campaign_alias[0].name
6769
provisioned_concurrent_executions = var.provisioned_concurrency_count
6870
}
69-

infrastructure/modules/lambda/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,9 @@ variable "hashing_secret_name" {
8888
description = "hashing secret name"
8989
type = string
9090
}
91+
92+
variable "environments_with_signing" {
93+
description = "List of environments where Lambda code signing is enabled; enforcement behaviour depends on the configured code signing policy"
94+
type = list(string)
95+
default = ["test"]
96+
}

infrastructure/stacks/api-layer/lambda.tf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module "eligibility_signposting_lambda_function" {
1818
environment = var.environment
1919
runtime = "python3.13"
2020
lambda_func_name = "${terraform.workspace == "default" ? "" : "${terraform.workspace}-"}eligibility_signposting_api"
21-
security_group_ids = [data.aws_security_group.main_sg.id]
21+
security_group_ids = [data.aws_security_group.main_sg.id]
2222
vpc_intra_subnets = [for v in data.aws_subnet.private_subnets : v.id]
2323
file_name = "../../../dist/lambda.zip"
2424
handler = "eligibility_signposting_api.app.lambda_handler"
@@ -33,6 +33,7 @@ module "eligibility_signposting_lambda_function" {
3333
stack_name = local.stack_name
3434
provisioned_concurrency_count = 5
3535
api_domain_name = local.api_domain_name
36+
environments_with_signing = ["test", "preprod"]
3637
}
3738

3839

@@ -69,7 +70,7 @@ resource "aws_lambda_function" "create_secret_lambda" {
6970
variables = { SECRET_NAME = module.secrets_manager.aws_hashing_secret_name }
7071
}
7172
vpc_config {
72-
subnet_ids = [for s in data.aws_subnet.private_subnets : s.id]
73+
subnet_ids = [for s in data.aws_subnet.private_subnets : s.id]
7374
security_group_ids = [data.aws_security_group.main_sg.id]
7475
}
7576
}
@@ -98,7 +99,7 @@ resource "aws_lambda_function" "promote_secret_lambda" {
9899
variables = { SECRET_NAME = module.secrets_manager.aws_hashing_secret_name }
99100
}
100101
vpc_config {
101-
subnet_ids = [for s in data.aws_subnet.private_subnets : s.id]
102+
subnet_ids = [for s in data.aws_subnet.private_subnets : s.id]
102103
security_group_ids = [data.aws_security_group.main_sg.id]
103104
}
104105
}

0 commit comments

Comments
 (0)