Zero-Downtime Deployments with GitHub Actions OIDC and AWS ECS
A deep dive into building secure, zero-downtime CI/CD pipelines for containerised Spring Boot apps on AWS ECS — OIDC trust setup, 9-stack CloudFormation IaC, and blue/green deployments with automatic rollback.
Zero-Downtime Deployments with GitHub Actions OIDC and AWS ECS
When I built the CI/CD pipeline for my Spring Boot application on AWS ECS, I had two hard
requirements: no long-lived AWS credentials anywhere in the pipeline, and zero-downtime
deployments. Both are achievable — here is exactly how.
Why OIDC Instead of Access Keys
The traditional approach stores an AWS Access Key ID and Secret Access Key in GitHub Secrets.
Those credentials are long-lived — they stay valid until you manually rotate them. If the
repository is compromised, the attacker has persistent AWS access.
OIDC (OpenID Connect) eliminates this. GitHub acts as an identity provider. When a workflow runs,
GitHub issues a short-lived OIDC token for that specific run. AWS exchanges this token for
temporary credentials that last at most one hour. No static credentials exist anywhere.
Setting Up the OIDC Trust
Step 1 — Create the OIDC Identity Provider in AWS:
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1Step 2 — Create an IAM Role with a trust policy scoped to your repository:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:nlenjibi/ecs-cicd-app:ref:refs/heads/main"
}
}
}]
}The StringLike condition scopes the role to a specific repo and branch. Even if another
GitHub Actions workflow tries to assume this role, it will be denied.
Step 3 — Use the role in your workflow:
permissions:
id-token: write # required to request the OIDC token
contents: readjobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::ACCOUNT_ID:role/GitHubActionsECSRole aws-region: eu-west-1