Lambda Code Signing: Enforce CI-Built Artifacts in Every Account

Lambda Code Signing: Enforce CI-Built Artifacts in Every Account
5 views
Console “Upload .zip” is an incident waiting for a tired engineer. Code signing makes unsigned artifacts a hard deny in every account: only CI-built, signer-profile-attested packages update production functions. That is the unfair advantage — provenance as IAM, not as a wiki page.
⚡ TL;DR: Create a signing profile (PLATFORM or AWSLambda), sign in CI after npm ci/esbuild, attach a code-signing config with Enforce to every prod function. SCP-deny lambda:UpdateFunctionCode without signing when possible; block console upload paths. Combine with Secret-Aware Context Filters and Agent Tool Allowlists so agents cannot push unsigned blobs.

Lambda Code Signing: production guidance

yaml
# .github/workflows/lambda-sign.yml
jobs:
 build-sign:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
 - run: npm ci && npm run build
 - name: Package
 run: (cd dist && zip -r ../function.zip .)
 - name: Start signing job
 run: |
 JOB=$(aws signer start-signing-job \
 --source "s3={bucketName=$BUCKET,key=function.zip,version=$VER}" \
 --destination "s3={bucketName=$BUCKET,prefix=signed/}" \
 --profile-name prod-lambda-signing)
 echo "job=$JOB" >> $GITHUB_OUTPUT
typescript
// BAD: laptop zip uploaded via console
aws lambda update-function-code --function-name checkout --zip-file fileb://local.zip

// GOOD: deploy only the signed S3 object ARN produced by Signer
aws lambda update-function-code \
 --function-name checkout \
 --s3-bucket "$BUCKET" --s3-key "signed/function.zip"
✅ Signer job in the same pipeline that ran tests.
❌ Signing a zip that engineers can replace in S3 without bucket policies / object lock.

Enforce on the function

json
{
 "CodeSigningConfigArn": "arn:aws:lambda:REGION:ACCT:code-signing-config:csc-xxx",
 "Description": "prod enforce",
 "AllowedPublishers": {
 "SigningProfileVersionArns": [
 "arn:aws:signer:REGION:ACCT:/signing-profiles/prod-lambda-signing/X"
 ]
 },
 "CodeSigningPolicies": {
 "UntrustedArtifactOnDeployment": "Enforce"
 }
}
Warn is for migration week. Enforce is production. Attach the CSC at function create time; drift-detect with Config rules if someone removes it.

Org-wide guardrails

json
{
 "Effect": "Deny",
 "Action": ["lambda:UpdateFunctionCode", "lambda:CreateFunction"],
 "Resource": "arn:aws:lambda:*:*:function:prod-*",
 "Condition": {
 "StringNotEquals": {
 "aws:RequestedRegion": "us-east-1"
 }
 }
}
Pair with permissions boundaries that deny lambda:PutFunctionCodeSigningConfig removal except for the platform role. Cross-account deploys: grant Signer profile use via Cross-Account Bedrock Access-style role assumption patterns (platform signs, app accounts consume).

Closing checklist

  • [ ] Signing profile owned by platform; versions pinned in CSC
  • [ ] CI signs only after tests; artifacts land in write-protected prefix
  • [ ] Prod functions use UntrustedArtifactOnDeployment=Enforce
  • [ ] Console/local zip updates denied by IAM/SCP for prod-*
  • [ ] Config rule alerts if CSC detached
  • [ ] Runbook for emergency break-glass with dual control

Related reading

Last updated on September 11, 2026 Related: AWS Lambda SnapStart: Sub-100ms Cold Starts for Java Without Changing Your Code; Lambda Extensions API: Build Custom Monitoring Without Touching Application Code; Lambda Ephemeral Storage: Safe /tmp Strategies for Large Artifacts.

Watch: 100 Days of AI on YouTube

Short videos from CheatCoders, one AI engineering topic per day.

Open the playlist on YouTube · CheatCoders on YouTube

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.