Skip to content

Commit 2214ba7

Browse files
authored
feat(layers): add parameterised layer deployment and verification (#4033)
1 parent 848ff14 commit 2214ba7

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Parition Layer Verification
2+
# ---
3+
# This workflow queries the Parition layer info in production only
4+
5+
on:
6+
workflow_dispatch:
7+
inputs:
8+
environment:
9+
description: Deployment environment
10+
type: choice
11+
options:
12+
- Gamma
13+
- Prod
14+
required: true
15+
version:
16+
description: Layer version to verify
17+
type: string
18+
required: true
19+
partition_version:
20+
description: Layer version to verify, this is mostly used in Gamma where a version mismatch might exist
21+
type: string
22+
required: false
23+
partition:
24+
description: Partition to deploy to
25+
type: choice
26+
options:
27+
- China
28+
- GovCloud
29+
workflow_call:
30+
inputs:
31+
environment:
32+
description: Deployment environment
33+
type: string
34+
required: true
35+
version:
36+
description: Layer version to verify
37+
type: string
38+
required: true
39+
partition_version:
40+
description: Partition Layer version to verify, this is mostly used in Gamma where a version mismatch might exist
41+
type: string
42+
required: false
43+
44+
name: Layer Verification (Partition)
45+
run-name: Layer Verification (${{ inputs.partition }}) - ${{ inputs.environment }} / Version - ${{ inputs.version }}
46+
47+
permissions: {}
48+
49+
jobs:
50+
setup:
51+
runs-on: ubuntu-latest
52+
outputs:
53+
regions: ${{ format('{0}{1}', steps.regions_china.outputs.regions, steps.regions_govcloud.outputs.regions) }}
54+
parition: ${{ format('{0}{1}', steps.regions_china.outputs.partition, steps.regions_govcloud.outputs.parition) }}
55+
steps:
56+
- id: regions_china
57+
name: Parition (China)
58+
if: ${{ inputs.partition == 'China' }}
59+
run: |
60+
echo regions='["cn-north-1", "cn-northwest-1"]'>> "$GITHUB_OUTPUT"
61+
echo partition='aws-cn'>> "$GITHUB_OUTPUT"
62+
- id: regions_govcloud
63+
name: Partition (GovCloud)
64+
if: ${{ inputs.partition == 'GovCloud' }}
65+
run: |
66+
echo regions='["us-gov-east-1", "us-gov-west-1"]'>> "$GITHUB_OUTPUT"
67+
echo partition='aws-us-gov'>> "$GITHUB_OUTPUT"
68+
commercial:
69+
runs-on: ubuntu-latest
70+
permissions:
71+
id-token: write
72+
contents: read
73+
environment: Prod (Readonly)
74+
steps:
75+
- name: Configure AWS Credentials
76+
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
77+
with:
78+
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
79+
aws-region: us-east-1
80+
mask-aws-account-id: true
81+
- name: Output AWSLambdaPowertoolsTypeScriptV2
82+
# fetch the specific layer version information from the us-east-1 commercial region
83+
run: |
84+
aws --region us-east-1 lambda get-layer-version-by-arn --arn 'arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${{ inputs.version }}' > AWSLambdaPowertoolsTypeScriptV2.json
85+
- name: Store Metadata
86+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
87+
with:
88+
name: AWSLambdaPowertoolsTypeScriptV2.json
89+
path: AWSLambdaPowertoolsTypeScriptV2.json
90+
retention-days: 1
91+
if-no-files-found: error
92+
93+
verify:
94+
name: Verify
95+
needs:
96+
- setup
97+
- commercial
98+
runs-on: ubuntu-latest
99+
permissions:
100+
id-token: write
101+
contents: read
102+
# Environment should interperlate as "GovCloud Prod" or "China Beta"
103+
environment: ${{ inputs.partition }} ${{ inputs.environment }}
104+
strategy:
105+
matrix:
106+
region: ${{ fromJson(needs.setup.outputs.regions) }}
107+
steps:
108+
- name: Download Metadata
109+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
110+
with:
111+
name: AWSLambdaPowertoolsTypeScriptV2.json
112+
- id: transform
113+
run: |
114+
echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT"
115+
- name: Configure AWS Credentials
116+
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
117+
with:
118+
role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }}
119+
aws-region: ${{ matrix.region}}
120+
mask-aws-account-id: true
121+
- id: partition_version
122+
name: Partition Layer Version
123+
run: |
124+
echo 'partition_version=$([[ -n "${{ inputs.partition_version}}" ]] && echo ${{ inputs.partition_version}} || echo ${{ inputs.version }} )' >> "$GITHUB_OUTPUT"
125+
- name: Verify Layer
126+
run: |
127+
export layer_output='AWSLambdaPowertoolsTypeScriptV2-${{matrix.region}}.json'
128+
aws --region ${{ matrix.region}} lambda get-layer-version-by-arn --arn "arn:${{ needs.setup.outputs.parition }}:lambda:${{ matrix.region}}:${{ secrets[format('AWS_ACCOUNT_{0}', steps.transform.outputs.CONVERTED_REGION)] }}:layer:AWSLambdaPowertoolsTypeScriptV2:${{ steps.partition_version.outputs.partition_version }}" > $layer_output
129+
REMOTE_SHA=$(jq -r '.Content.CodeSha256' $layer_output)
130+
LOCAL_SHA=$(jq -r '.Content.CodeSha256' AWSLambdaPowertoolsTypeScriptV2.json)
131+
test "$REMOTE_SHA" == "$LOCAL_SHA" && echo "SHA OK: ${LOCAL_SHA}" || exit 1
132+
jq -s -r '["Layer Arn", "Runtimes", "Version", "Description", "SHA256"], ([.[0], .[1]] | .[] | [.LayerArn, (.CompatibleRuntimes | join("/")), .Version, .Description, .Content.CodeSha256]) |@tsv' AWSLambdaPowertoolsTypeScriptV2.json $layer_output | column -t -s $'\t'
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Partitioned Layer Publish
2+
# ---
3+
# This workflow publishes a specific layer version in an AWS account based on the environment input.
4+
#
5+
# We pull each the version of the layer and store them as artifacts, the we upload them to each of the Partitioned AWS accounts.
6+
#
7+
# A number of safety checks are performed to ensure safety.
8+
9+
on:
10+
workflow_dispatch:
11+
inputs:
12+
environment:
13+
description: Deployment environment
14+
type: choice
15+
options:
16+
- Gamma
17+
- Prod
18+
required: true
19+
version:
20+
description: Layer version to duplicate
21+
type: string
22+
required: true
23+
partition:
24+
description: Partition to deploy to
25+
type: choice
26+
options:
27+
- China
28+
- GovCloud
29+
workflow_call:
30+
inputs:
31+
environment:
32+
description: Deployment environment
33+
type: string
34+
required: true
35+
version:
36+
description: Layer version to duplicate
37+
type: string
38+
required: true
39+
40+
name: Layer Deployment (Partitions)
41+
run-name: Layer Deployment (${{ inputs.partition }}) - ${{ inputs.environment }} / Version - ${{ inputs.version }}
42+
43+
permissions:
44+
contents: read
45+
46+
jobs:
47+
setup:
48+
runs-on: ubuntu-latest
49+
outputs:
50+
regions: ${{ format('{0}{1}', steps.regions_china.outputs.regions, steps.regions_govcloud.outputs.regions) }}
51+
parition: ${{ format('{0}{1}', steps.regions_china.outputs.partition, steps.regions_govcloud.outputs.parition) }}
52+
steps:
53+
- id: regions_china
54+
name: Parition (China)
55+
if: ${{ inputs.partition == 'China' }}
56+
run: |
57+
echo regions='["cn-north-1", "cn-northwest-1"]'>> "$GITHUB_OUTPUT"
58+
echo partition='aws-cn'>> "$GITHUB_OUTPUT"
59+
- id: regions_govcloud
60+
name: Partition (GovCloud)
61+
if: ${{ inputs.partition == 'GovCloud' }}
62+
run: |
63+
echo regions='["us-gov-east-1", "us-gov-west-1"]'>> "$GITHUB_OUTPUT"
64+
echo partition='aws-us-gov'>> "$GITHUB_OUTPUT"
65+
download:
66+
runs-on: ubuntu-latest
67+
permissions:
68+
id-token: write
69+
contents: read
70+
environment: Prod (Readonly)
71+
steps:
72+
- name: Configure AWS Credentials
73+
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
74+
with:
75+
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
76+
aws-region: us-east-1
77+
mask-aws-account-id: true
78+
- name: Grab Zip
79+
run: |
80+
aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${{ inputs.version }} --query 'Content.Location' | xargs curl -L -o AWSLambdaPowertoolsTypeScriptV2.zip
81+
aws --region us-east-1 lambda get-layer-version-by-arn --arn arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:${{ inputs.version }} > AWSLambdaPowertoolsTypeScriptV2.json
82+
- name: Store Zip
83+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
84+
with:
85+
name: AWSLambdaPowertoolsTypeScriptV2.zip
86+
path: AWSLambdaPowertoolsTypeScriptV2.zip
87+
retention-days: 1
88+
if-no-files-found: error
89+
- name: Store Metadata
90+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
91+
with:
92+
name: AWSLambdaPowertoolsTypeScriptV2.json
93+
path: AWSLambdaPowertoolsTypeScriptV2.json
94+
retention-days: 1
95+
if-no-files-found: error
96+
97+
copy:
98+
name: Copy
99+
needs:
100+
- setup
101+
- download
102+
runs-on: ubuntu-latest
103+
permissions:
104+
id-token: write
105+
contents: read
106+
# Environment should interperlate as "GovCloud Prod" or "China Beta"
107+
environment: ${{ inputs.partition }} ${{ inputs.environment }}
108+
strategy:
109+
matrix:
110+
region: ${{ fromJson(needs.setup.outputs.regions) }}
111+
steps:
112+
- name: Download Zip
113+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
114+
with:
115+
name: AWSLambdaPowertoolsTypeScriptV2.zip
116+
- name: Download Metadata
117+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
118+
with:
119+
name: AWSLambdaPowertoolsTypeScriptV2.json
120+
- name: Verify Layer Signature
121+
run: |
122+
SHA=$(jq -r '.Content.CodeSha256' 'AWSLambdaPowertoolsTypeScriptV2.json')
123+
test "$(openssl dgst -sha256 -binary AWSLambdaPowertoolsTypeScriptV2.zip | openssl enc -base64)" == "$SHA" && echo "SHA OK: ${SHA}" || exit 1
124+
- id: transform
125+
run: |
126+
echo 'CONVERTED_REGION=${{ matrix.region }}' | tr 'a-z\-' 'A-Z_' >> "$GITHUB_OUTPUT"
127+
- name: Configure AWS Credentials
128+
uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1
129+
with:
130+
role-to-assume: ${{ secrets[format('IAM_ROLE_{0}', steps.transform.outputs.CONVERTED_REGION)] }}
131+
aws-region: ${{ matrix.region}}
132+
mask-aws-account-id: true
133+
- name: Create Layer
134+
id: create-layer
135+
run: |
136+
cat AWSLambdaPowertoolsTypeScriptV2.json | jq '{"LayerName": "AWSLambdaPowertoolsTypeScriptV2", "Description": .Description, "CompatibleRuntimes": .CompatibleRuntimes, "LicenseInfo": .LicenseInfo}' > input.json
137+
138+
LAYER_VERSION=$(aws --region ${{ matrix.region}} lambda publish-layer-version \
139+
--zip-file fileb://./AWSLambdaPowertoolsTypeScriptV2.zip \
140+
--cli-input-json file://./input.json \
141+
--query 'Version' \
142+
--output text)
143+
144+
echo "LAYER_VERSION=$LAYER_VERSION" >> "$GITHUB_OUTPUT"
145+
146+
aws --region ${{ matrix.region}} lambda add-layer-version-permission \
147+
--layer-name 'AWSLambdaPowertoolsTypeScriptV2' \
148+
--statement-id 'PublicLayer' \
149+
--action lambda:GetLayerVersion \
150+
--principal '*' \
151+
--version-number "$LAYER_VERSION"
152+
- name: Verify Layer
153+
env:
154+
LAYER_VERSION: ${{ steps.create-layer.outputs.LAYER_VERSION }}
155+
run: |
156+
export layer_output='AWSLambdaPowertoolsTypeScriptV2-${{matrix.region}}.json'
157+
aws --region ${{ matrix.region}} lambda get-layer-version-by-arn --arn 'arn:${{ needs.setup.outputs.parition }}:lambda:${{ matrix.region}}:${{ secrets[format('AWS_ACCOUNT_{0}', steps.transform.outputs.CONVERTED_REGION)] }}:layer:AWSLambdaPowertoolsTypeScriptV2:${{ env.LAYER_VERSION }}' > $layer_output
158+
REMOTE_SHA=$(jq -r '.Content.CodeSha256' $layer_output)
159+
LOCAL_SHA=$(jq -r '.Content.CodeSha256' AWSLambdaPowertoolsTypeScriptV2.json)
160+
test "$REMOTE_SHA" == "$LOCAL_SHA" && echo "SHA OK: ${LOCAL_SHA}" || exit 1
161+
jq -s -r '["Layer Arn", "Runtimes", "Version", "Description", "SHA256"], ([.[0], .[1]] | .[] | [.LayerArn, (.CompatibleRuntimes | join("/")), .Version, .Description, .Content.CodeSha256]) |@tsv' AWSLambdaPowertoolsTypeScriptV2.json $layer_output | column -t -s $'\t'
162+
163+
- name: Store Metadata - ${{ matrix.region }}
164+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
165+
with:
166+
name: AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
167+
path: AWSLambdaPowertoolsTypeScriptV2-${{ matrix.region }}.json
168+
retention-days: 1
169+
if-no-files-found: error

0 commit comments

Comments
 (0)