I was setting up GitHub Actions to deploy to GCP and needed to use workload identity instead of service account keys. Here’s how to manage the providers.
TLDR Link to heading
Workload identity lets GitHub Actions authenticate to GCP without storing service account keys. It’s more secure because:
- No static credentials to rotate or leak
- Fine-grained control over which repos can access what
- Built-in audit trail of who authenticated when
The main gotcha: you need id-token: write permission in your workflow or auth fails silently.
List providers in a pool:
gcloud iam workload-identity-pools providers list \
--workload-identity-pool=github-actions \
--location=global \
--project=my-project
Describe one:
gcloud iam workload-identity-pools providers describe github \
--workload-identity-pool=github-actions \
--location=global \
--project=my-project
Delete an old one:
gcloud iam workload-identity-pools providers delete old-provider \
--workload-identity-pool=github-actions \
--location=global \
--project=my-project
In the GitHub workflow, make sure you have:
permissions:
contents: read
id-token: write # This is the important one
Without id-token: write, the authentication fails silently.
Why workload identity? Link to heading
Service account keys are a security risk. If they leak (in logs, git history, etc.), someone can impersonate your service account until you notice and rotate the key. I’ve seen keys accidentally committed to repos multiple times.
Workload identity uses OIDC tokens that are short-lived (minutes, not years) and scoped to the specific workflow run. Even if someone intercepts the token, it’s useless by the time they try to use it.
Plus, you can configure exactly which repos and branches can authenticate. No more blanket access for any workflow that has the key.
Debugging authentication failures Link to heading
If auth isn’t working, check these in order:
Missing id-token permission - This is the most common issue. The workflow needs
id-token: writeat the job or workflow level.Wrong attribute mapping - The workload identity provider needs to trust tokens from your repo. Check the attribute conditions:
gcloud iam workload-identity-pools providers describe github \ --workload-identity-pool=github-actions \ --location=global \ --project=my-project \ --format='value(attributeCondition)'Service account permissions - The service account needs
roles/iam.workloadIdentityUserbinding for the right principal:gcloud iam service-accounts add-iam-policy-binding my-sa@my-project.iam.gserviceaccount.com \ --role=roles/iam.workloadIdentityUser \ --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-actions/attribute.repository/my-org/my-repo"Check the GitHub token - Use
google-github-actions/auth@v2withtoken_format: access_tokenand add a debug step to print claims (careful not to print the token itself).
The error messages are often vague (“authentication failed”), so methodically checking each layer is the only way.