Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXLIII · OIDC and Short-Lived CredentialsAWS

OIDC in AWS — provider, audience, role, trust policy; aws-actions/configure-aws-credentials

Advanced⏱ ~28 mingit

What you'll learn

  • Register the GitHub Actions OIDC provider in AWS IAM
  • Configure an IAM role with a trust policy that gates repo, branch, and workflow path
  • Use aws-actions/configure-aws-credentials@v4 to exchange the OIDC token for a short-lived STS session
  • Configure the role session duration and the audience to match the trust policy

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

OIDC federation in AWS has four pieces that must agree: the OIDC provider (the GitHub Actions issuer URL and JWKS endpoint), the audience (sts.amazonaws.com), the IAM role (the permission grant), and the trust policy (the subject and audience match). When all four agree, the aws-actions/configure-aws-credentials@v4 action fetches the OIDC token from GitHub and calls sts:AssumeRoleWithWebIdentity; AWS validates the claims and issues a short-lived STS session.

The four pieces

flowchart LR
    P["1. OIDC provider\ntoken.actions.githubusercontent.com"] --> C["AWS IAM\ntrusts the provider"]
    A["2. Audience\nsts.amazonaws.com"] --> C
    R["3. IAM role\ngrants permissions"] --> T["4. Trust policy\ngates repo + branch + workflow"]
    T --> C
    C --> S["STS session\n(~1 hour)"]
  • OIDC provider. An IAM identity provider entry that registers GitHub Actions as a trusted issuer. The provider URL is https://token.actions.githubusercontent.com; the audience is sts.amazonaws.com. AWS fetches the JWKS endpoint and validates the token’s signature against the published keys.
  • Audience. The aud claim in the OIDC token. AWS expects sts.amazonaws.com; the trust policy matches the audience; a different audience is rejected.
  • IAM role. The role that the workflow assumes. The role’s permission policy grants the AWS permissions the workflow needs.
  • Trust policy. The role’s trust policy gates which forge, repository, branch, and workflow may assume the role. The trust policy matches the sub and aud claims in the OIDC token.

The four pieces are registered and configured once per AWS account. The workflow declares the role ARN; AWS validates the token against the trust policy; AWS issues the STS session.

Registering the OIDC provider

The OIDC provider is registered in IAM once per AWS account:

aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1

The --url is the GitHub Actions OIDC issuer. The --client-id-list is the audience the provider may issue tokens for (AWS uses sts.amazonaws.com). The --thumbprint-list is the SHA-1 thumbprint of the TLS certificate GitHub uses for the OIDC endpoint.

After registration, the provider ARN is available at arn:aws:iam::$AWS_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com. The trust policy references the provider ARN.

The trust policy

The IAM role’s trust policy declares which workflows may assume the role. A minimal trust policy for a single repository and branch:

{
  "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:acme/infra:ref:refs/heads/main"
        }
      }
    }
  ]
}

The Condition block matches the aud claim to sts.amazonaws.com and the sub claim to repo:acme/infra:ref:refs/heads/main. A workflow on a different repository or branch cannot assume the role; the trust policy denies.

For finer-grained gating, the trust policy can match the job_workflow_ref claim:

"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:acme/infra:ref:refs/heads/main",
    "token.actions.githubusercontent.com:job_workflow_ref": "acme/infra/.github/workflows/deploy.yml@refs/heads/main"
  }
}

The job_workflow_ref claim matches the workflow file path; only the specific deploy workflow can assume the role.

The workflow

The workflow uses aws-actions/configure-aws-credentials@v4 to fetch the OIDC token and exchange it for an STS session:

name: Deploy
on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::"$AWS_ACCOUNT_ID":role/github-actions-deploy
          aws-region: us-east-1

      - name: Deploy
        run: aws s3 sync ./build s3://"$BUCKET_NAME"

The action calls GitHub’s OIDC endpoint to fetch a JWT, calls sts:AssumeRoleWithWebIdentity to exchange the JWT for an STS session, and configures the AWS CLI to use the session credentials. The session is valid for the role’s MaxSessionDuration (default 1 hour, maximum 12 hours).

Configuring the session

The aws-actions/configure-aws-credentials@v4 action supports several options for the session:

  • role-to-assume — the ARN of the IAM role to assume (required)
  • aws-region — the AWS region for the session (required)
  • role-session-name — a name for the session (defaults to GitHubActions_${GITHUB_RUN_ID})
  • session-duration — the session duration in seconds (default 1 hour, maximum 12 hours — must not exceed the role’s MaxSessionDuration)
  • role-skip-session-tagging — skip tagging the session with GitHub-specific attributes

The session duration is bounded by the role’s MaxSessionDuration. A role with a 1-hour MaxSessionDuration rejects session requests for longer durations; the action fails with an AccessDenied error.

Multiple roles

A workflow can assume different roles for different jobs by declaring separate aws-actions/configure-aws-credentials@v4 steps. Each step fetches a new OIDC token and assumes the role for the duration of the job.

For cross-account access — a workflow in account A that needs to assume a role in account B — the trust policy in account B grants access to the role in account A; the workflow assumes the role in account B by setting role-to-assume to the account B role ARN.

- name: Configure AWS credentials in account B
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::"$ACCOUNT_B_ID":role/github-actions-deploy
    aws-region: us-east-1

Production discipline

  1. The OIDC provider is registered once per AWS account. The provider URL is https://token.actions.githubusercontent.com; the client ID list is sts.amazonaws.com.
  2. Trust policies use StringEquals with specific values. No wildcards in the sub claim; no StringLike for production roles.
  3. Session duration matches the job duration. A 30-minute job should not request a 12-hour session; the longer the session, the larger the replay window if the credentials leak.
  4. Trust policies are reviewed when workflow files change. A new workflow file may require a new subject pattern; the policy update is part of the pull request.

Cross-course references

  • Git, CI/CD & GitOps — Part XLIII-02 (OIDC federation basics) covers the trust relationship and the JWT claim anatomy.
  • Git, CI/CD & GitOps — Part XLIII-03 (GitHub Actions OIDC in practice) covers the id-token: write permission and the OIDC token API.
  • Git, CI/CD & GitOps — Part XLIII-06 (OIDC trust policy deep dive) covers the sub and job_workflow_ref claims in detail.
  • AWS for Production Sysadmins — Part XXXI (IAM) covers IAM roles, trust policies, and permission boundaries.

Quiz

Knowledge check · 4 questions

  1. Q1. Which AWS IAM API does `aws-actions/configure-aws-credentials@v4` call to exchange an OIDC token for a short-lived session?

  2. Q2. A trust policy using `StringLike` with a wildcard pattern in the `sub` claim is the OIDC equivalent of a static access key with no scope.

  3. Q3. Name the four pieces that must agree for OIDC federation in AWS, and state the value each one takes for GitHub Actions.

  4. Q4. Diagnose the OIDC authentication failure and prescribe the fix.

    Team T configures OIDC federation between GitHub Actions and AWS. The OIDC provider is registered. The IAM role has a permission policy granting AdministratorAccess on the production account. The trust policy's `Condition` block has `token.actions.githubusercontent.com:aud: sts.amazonaws.com` and `token.actions.githubusercontent.com:sub: repo:acme/infra:ref:refs/heads/main`. The workflow declares `id-token: write` and calls `aws-actions/configure-aws-credentials@v4` with `role-to-assume`. The action fails with: `Error: Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity`.

Passing score: 75%. Answers are checked in this browser.