GitHub Actions + AWS Role Chaining: A Security Upgrade Worth Making

Published: (December 22, 2025 at 06:41 PM EST)
3 min read
Source: Dev.to

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:

  1. GitHub gets through the main gate (shared role).
  2. 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

  1. Configure the GitHub Actions OIDC provider in the target AWS account.
  2. Create a base role with a trust policy that allows the GitHub OIDC principal.
  3. Create environment‑specific roles that trust the base role.
  4. In the workflow, use the official AWS action with role‑chaining: true (or fall back to aws 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.

Back to Blog

Related posts

Read more »

Creating EC2 Instance

Log in to the AWS Management Console - Open the AWS Management Console. - Search for EC2 in the services search bar and open the EC2 Dashboard. Launch a New In...