Lesson 9 · Security, supply chain & operations
Keyless GCP auth (OIDC/WIF)
How CI proves who it is to Google Cloud — with no static keys to leak.
Your win: explain how a GitHub Actions job authenticates to GCP without a service-account key file — the OIDC / Workload Identity Federation token exchange — and why this is the single biggest CI security win.
The problem: long-lived keys leak
CI must authenticate to GCP to push images and deploy. The old way: store a service-account JSON key as a GitHub secret. But a static key is a standing liability — it doesn't expire, and if it leaks (a log, a fork, a compromised action) an attacker has your cloud until someone notices and rotates it. The modern fix is to have no key at all.1
The token exchange — OIDC / Workload Identity Federation
Instead of a stored key, a job asks GitHub to mint a short-lived OIDC token that describes it (which repo, which workflow, which branch). GCP is configured to trust GitHub's issuer and exchange that token for a short-lived Google credential.2
permissions: id-token: write to be allowed to request
an OIDC token. Miss that and the auth step fails with a confusing error. It's the single line
that says "this job may prove its identity to an external system." Every deploy/build job here
sets it.
permissions: id-token: "write"
(tiered.pre_merge.yml:152-156,
tbd.deploy.yml:362-364), then use
google-github-actions/auth@v2
(.github/actions/tbd.build-backend/action.yml:49-53) with a WIF
provider (projects/…/workloadIdentityPools/gh-action-pool/providers/build-bot-provider)
and a purpose-specific service account. And there's a nice least-privilege detail: different
bots for different jobs — prod-build-bot@student-coach-e1e95 for builds, a
deploy SA resolved per env/org (auth-oidc/action.yaml:84-87), an
integration-test-bot@… for E2E. So a compromised build job can't also deploy prod —
it simply isn't that identity. No static SA JSON keys anywhere.
GitHub OIDC + google-github-actions/auth
How the OIDC token is minted and exchanged, and the auth action's config.
→ docs.github.com — OIDC in Google Cloud
→ github.com — google-github-actions/auth
Check yourself (from memory)
Q1. Keyless auth to GCP works by…
Q2. A job must declare which permission to use OIDC?
id-token: write lets the job request an OIDC
token; without it the auth step fails.
Q3. Using different bot SAs per job (build/deploy/test) gives…
permissions: id-token: write)
asks GitHub for a short-lived OIDC token describing it (repo/workflow/ref); GCP TRUSTS GitHub's
issuer + EXCHANGES it (via STS) for a short-lived Google credential — NO static key. Repo:
google-github-actions/auth@v2 with a WIF provider
(.../gh-action-pool/providers/build-bot-provider) + PER-PURPOSE bots
(prod-build-bot for build, deploy SA per env/org, integration-test-bot
for E2E) = LEAST PRIVILEGE (a build job can't deploy prod). Same principle as Pod Workload
Identity (C2 L12 / C4 L9), applied to GitHub jobs.1. Google — Keyless auth from GitHub Actions.
2. GitHub — OIDC in Google Cloud; google-github-actions/auth.