Keyless cloud deploys with OIDC

GitHub Actions · Advanced · 12 min

Long-lived cloud keys in secrets are the most common credential leak; OIDC removes them entirely.

With OpenID Connect, a job asks GitHub for a signed JSON Web Token describing itself: repository, ref, environment, workflow and more. Your cloud provider is configured to trust GitHub's token issuer (https://token.actions.githubusercontent.com) and exchanges a valid token for short-lived cloud credentials. No access keys are stored in GitHub at all.

To use it:

  • Grant the job permissions: id-token: write (plus contents: read for checkout).
  • In the cloud, create a trust relationship: an AWS IAM OIDC provider and role, an Azure federated credential, or a GCP workload identity pool.
  • Use the provider's login action, such as aws-actions/configure-aws-credentials with role-to-assume.

The security lives in the trust policy conditions on the token's claims. The key claim is sub, for example repo:my-org/shop:environment:production or repo:my-org/shop:ref:refs/heads/main. Always restrict sub to your repository and a specific branch or environment; a policy that only checks the audience would let any GitHub repository assume your role.

Credentials typically last an hour and die with the job, so a leaked log or compromised dependency gets far less than a permanent key would give.

Example

permissions:
  id-token: write     # allow requesting the OIDC token
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v7
      - uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
          aws-region: eu-central-1
      - run: aws sts get-caller-identity   # assumed-role/gha-deploy/...
# AWS trust policy condition (excerpt):
# "token.actions.githubusercontent.com:sub": "repo:my-org/shop:environment:production" 

Remember

  • OIDC exchanges a signed per-job token for short-lived cloud credentials
  • Requires permissions: id-token: write
  • Lock the trust policy to repo and branch or environment via the sub claim

Watch out for

  • A trust policy that checks only aud, not sub, trusts every repository on GitHub.

Check yourself

  1. What prevents another GitHub repository from assuming your OIDC-trusted AWS role?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect