GitHub Actions + AWS Role Chaining: A Security Upgrade Worth Making
Source: Dev.to
Introduction
As the year comes to an end, I’ve been reflecting on and intentionally improving my security knowledge.
Since joining Muzz, I’ve worked with systems that operate at scale across multiple AWS accounts, production‑critical pipelines, and infrastructure that cannot afford loose security practices. One of the most valuable lessons has been AWS role chaining in GitHub Actions. It may look complex at first, but once it clicks, you realize:
“Yeah… this is how CI/CD should work.”
Problems with Static AWS Credentials
Traditionally, CI/CD pipelines access AWS by storing credentials such as AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as GitHub Secrets. While this works, it introduces several issues:
- Long‑lived credentials sitting in GitHub
- Hard to rotate safely
- Over‑permissioned “just in case” policies
- No clear trust boundaries between environments
- Risk increases as the organisation scales
As teams grow and environments multiply (shared, dev, staging, prod), this approach does not scale securely.
Moving to OIDC and Role Chaining
Instead of static secrets, we switched to:
- GitHub Actions OpenID Connect (OIDC) – see my earlier blog post for details.
- IAM roles with trust policies
- Short‑lived AWS credentials
- Role chaining for environment isolation
This change brings several benefits:
- No AWS secrets stored in GitHub
- Credentials are issued only when a job runs
- Access is tightly scoped and time‑limited
What Is AWS Role Chaining?
Role chaining means that GitHub Actions first assumes a base role (usually in a shared AWS account) and then assumes a target role for the specific environment (dev, prod, etc.).
Think of it like airport security:
- GitHub gets through the main gate (shared role).
- It is then escorted to the correct terminal (dev/prod role).
There is no free roaming and no shortcuts—each step is explicitly trusted.
How It Works
- Configure the GitHub Actions OIDC provider in the target AWS account.
- Create a base role with a trust policy that allows the GitHub OIDC principal.
- Create environment‑specific roles that trust the base role.
- In the workflow, use the official AWS action with
role‑chaining: true(or fall back toaws sts assume-role).
Example Configuration
# .github/workflows/deploy.yml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::ACCOUNT_ID:role/target-role
role-chaining: true
aws-region: eu-west-2
If you prefer a manual approach:
aws sts assume-role \
--role-arn arn:aws:iam::ACCOUNT_ID:role/target-role \
--role-session-name github-actions-session
Why Adopt This Pattern?
Security isn’t something you “add later”; it’s built into your workflows from day one. Using GitHub Actions with AWS role chaining:
- Eliminates long‑lived keys in CI/CD
- Provides clear trust boundaries between environments
- Improves auditability and confidence in production deployments
If you’re still using long‑lived AWS keys in CI/CD, this is one of the cleanest upgrades you can make.
Hope this helps fellow builders ship with more confidence and less risk. If you have any issues, feel free to comment.