CloudFormation in CI/CD

Automate deploys; protect the pipeline.

Advanced12 min · lesson 12 of 12

The safe delivery pattern is the familiar one, run with CloudFormation’s primitives: on a pull request, validate and scan the template and create a change set so the diff is reviewable; on merge, execute the change set to apply the reviewed change — never an ad-hoc deploy from a laptop against production. The change set is the plan; reviewing it before execute is the gate.

.github/workflows/infra.yml
jobs:
plan:
if: github.event_name == 'pull_request'
steps:
- run: cfn-lint template.yaml && cfn-guard validate -r security.guard -d template.yaml
- run: |
aws cloudformation create-change-set --stack-name prod-net \
--change-set-name pr-${{ github.event.number }} --template-body file://template.yaml
aws cloudformation describe-change-set --stack-name prod-net \
--change-set-name pr-${{ github.event.number }} # post the diff
deploy:
if: github.ref == 'refs/heads/main'
environment: production # human approval
steps:
- run: aws cloudformation execute-change-set --stack-name prod-net --change-set-name main

Securing the pipeline

Because the pipeline can reshape your AWS account, harden it like the CI/CD course teaches: authenticate CI to AWS with OIDC and a scoped role (short-lived credentials, no long-lived access keys in secrets), give CloudFormation a least-privilege service role, protect the prod deploy behind an approval gate, and keep template scanning as a required check. The deploy identity and the pipeline are as sensitive as the infrastructure they build.

The secure CloudFormation pipeline
1PR: validate
lint + guard + change set
2review
read the diff
3merge: execute
apply reviewed change set
4guardrails
OIDC, scoped role, approval
Change set is visible and scanned; execute is approved; CI uses short-lived, least-privilege credentials.
OIDC over static keys
Long-lived AWS access keys stored in CI secrets are a top breach vector — a leaked runner or a malicious dependency exfiltrates them and owns your account. Use the CI provider’s OIDC integration to assume a scoped AWS role for each run instead, so credentials are short-lived, auditable, and never sit in a secret store. This single change removes the most common CloudFormation-pipeline compromise.