Workload Identity Federation Playbook (Secretsless CI/CD for GitHub Actions)

2026-03-01 · software

Workload Identity Federation Playbook (Secretsless CI/CD for GitHub Actions)

Date: 2026-03-01
Category: knowledge (software / security / platform)

Why this matters

Long-lived cloud keys in CI are a latent incident:

Workload Identity Federation (WIF) replaces static keys with short-lived, claim-bound tokens. If you bind trust to repository/workflow/branch/environment claims, your deploy identity becomes:


Core model (mental picture)

  1. GitHub Actions job requests OIDC token (id-token: write).
  2. Cloud IAM validates JWT issuer/audience/subject (+ optional extra claims).
  3. Cloud exchanges JWT for short-lived credentials.
  4. Job uses temporary credentials; no static cloud secret stored in GitHub.

This is not “no auth”—it is better auth with tighter lifetime + stronger context binding.


Minimum trust contract (must-have)

For production, enforce all 5:

  1. Issuer pinned: https://token.actions.githubusercontent.com
  2. Audience pinned to provider expectation
  3. Subject constrained (repo + branch or environment, not wildcard *)
  4. Least privilege role for each workload identity
  5. Short session duration + full audit logging enabled

If any of these is weak, WIF degrades to “dynamic secret sprawl.”


GitHub OIDC claims that matter most

From GitHub OIDC docs, common high-signal claims are:

Common sub patterns:

Practical rule: prefer environment-scoped subjects for production deploys, then protect environment with branch/tag approvals.


Cloud-specific notes (AWS / GCP / Azure)

AWS

Example trust condition:

"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:environment:prod"
  }
}

Operational note: avoid broad wildcard subjects in production roles.

GCP

Typical guardrails:

Azure


GitHub workflow baseline

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: prod
    steps:
      - uses: actions/checkout@v5
      # cloud auth action here (aws/gcp/azure), pinned by commit SHA

Hardening checklist:


Reference architecture (recommended)

Use a two-lane identity design:

  1. Build lane identity
    • read artifact registry, push build outputs, no production mutation permissions.
  2. Deploy lane identity
    • minimal deploy-only permissions, environment-scoped subject, stricter approvals.

Benefits:


Rollout plan (safe migration from static secrets)

Phase 0 — Inventory

Phase 1 — Parallel auth (non-prod)

Phase 2 — Production cutover

Phase 3 — Post-cutover hardening


Observability and governance

Track these signals weekly:

Policy goal:


Common failure patterns

  1. id-token: write missing

    • job cannot request OIDC token.
  2. Over-broad subject wildcard

    • accidental privilege expansion across branches/environments.
  3. Single role for all repos

    • hard-to-audit cross-service blast radius.
  4. No environment protection rules

    • secure identity, insecure release process.
  5. Forgot to delete legacy static keys

    • new secure path + old insecure backdoor.

One-line operator rule

Treat federated deploy identity like production code: small scope, explicit conditions, short lifetime, continuous audit.


References