GitHub Actions to AWS Without Access Keys: OIDC Step by Step

1–2 minutes

Updated

Short answer: GitHub Actions can assume an IAM role using OpenID Connect (OIDC). No long-lived access keys are stored in GitHub: each job gets short-lived credentials, and the role trust policy decides which repository and branch can use it.

LabEstimated · not yet run
Time
30 min
Cost
Free
Level
Intermediate
Services
IAM · STS · GitHub Actions

Step 1: Add GitHub as an identity provider

In the IAM console, add an OpenID Connect provider with the URL https://token.actions.githubusercontent.com and the audience sts.amazonaws.com. You only need one per AWS account.

Step 2: Create the role and its trust policy

The sub condition is what limits the role to your repository and branch. Without it, any repository on GitHub could try to assume the role.

trust-policy.json

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com" },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
        "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main"
      }
    }
  }]
}

Attach only the permissions the pipeline needs, for example deploy to one ECS service or write to one S3 bucket.

Step 3: Use it in the workflow

.github/workflows/deploy.yml

permissions:
  id-token: write   # required to request the OIDC token
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-deploy
          aws-region: us-east-1
      - run: aws sts get-caller-identity

If it fails

ErrorUsual cause
Not authorized to perform sts:AssumeRoleWithWebIdentityThe sub in the trust policy does not match (branch, environment or pull request)
Credentials could not be loadedMissing id-token: write permission in the workflow
Works on main, fails on pull requestsPR tokens have a different sub; add a separate, more limited role for them

Do not use StringLike with repo:my-org/* on a role that can deploy to production. Any repository in the organization could assume it.

Clean up

Delete the old access keys from GitHub secrets and deactivate them in IAM once the OIDC role works.

Joniel Gallo · Cloud & AI Engineer

I build these labs in a real AWS account and publish the code. Need a second opinion on your architecture or your AWS bill? Work with me.

One tested AWS & AI lab a week

Real costs, working code and what changed in Bedrock this month. Subscribe and get the free AWS Permission Debugger (PDF).