Google Cloud Workload Identity Federation: Enterprise Implementation Guide
Prerequisites
- Google Cloud project with IAM admin permissions
- Basic familiarity with OIDC, service accounts, and gcloud CLI
Steps
Google Cloud Workload Identity Federation lets external workloads authenticate to Google Cloud without long-lived service account keys. For enterprises, it reduces secret sprawl, improves auditability, and enables secure access from AWS, Azure, GitHub Actions, and on-premises identity providers.
Overview
Google Cloud Workload Identity Federation (WIF) allows workloads running outside Google Cloud to exchange trusted external identities for short-lived Google access tokens. Instead of distributing service account keys to CI/CD pipelines, multi-cloud workloads, or on-prem applications, enterprises define a trust relationship between Google Cloud IAM and an external identity provider such as AWS IAM, Azure AD, OIDC, or SAML.
Its core purpose is to eliminate static credentials while preserving fine-grained authorization through Google service accounts and IAM policies. Enterprises adopt WIF to reduce key management overhead, meet compliance requirements for credential rotation, and standardize machine authentication across hybrid and multi-cloud environments.
Architecture
Core components
- Workload Identity Pool: Logical container for external identities.
- Provider: Trust definition for AWS, Azure, OIDC, or SAML.
- Attribute mapping: Maps external claims to Google attributes such as
google.subjectandattribute.repository. - Service account impersonation: Grants external principals permission to mint short-lived credentials for a Google service account.
- Security Token Service (STS): Exchanges external subject tokens for Google federated tokens.
Deployment models
- CI/CD federation: GitHub Actions, GitLab, or Azure DevOps pipelines access Artifact Registry, GKE, or Cloud Run.
- Multi-cloud runtime federation: AWS EC2 or Azure workloads call Google APIs.
- On-prem federation: Applications authenticate using enterprise IdPs through OIDC or SAML.
Data flow
View as text
[External Workload] ---- 1. obtain OIDC/JWT ----> [External IdP] [External Workload] ---- 2. present subject token ----> [Google STS] [Google STS] ---- 3. federated token ----> [IAM Credentials API] [IAM Credentials API] ---- 4. impersonate SA ----> [Google Service Account] [External Workload] ---- 5. access API with short-lived token ----> [Google Cloud APIs]
Implementation Guide
- Create a workload identity pool:
gcloud iam workload-identity-pools create ci-pool --project=enterprise-sec-prj --location=global --display-name="CI Pool"
- Create an OIDC provider for GitHub Actions:
gcloud iam workload-identity-pools providers create-oidc github-provider --project=enterprise-sec-prj --location=global --workload-identity-pool=ci-pool --display-name="GitHub OIDC" --issuer-uri="https://token.actions.githubusercontent.com" --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.ref=assertion.ref" --attribute-condition="assertion.repository=='acme/platform-app'"
- Create a target service account:
gcloud iam service-accounts create github-deployer --project=enterprise-sec-prj --display-name="GitHub Deployer"
- Grant required permissions to the service account:
gcloud projects add-iam-policy-binding enterprise-sec-prj --member="serviceAccount:github-deployer@enterprise-sec-prj.iam.gserviceaccount.com" --role="roles/artifactregistry.writer"
- Allow federated principals to impersonate the service account:
gcloud iam service-accounts add-iam-policy-binding github-deployer@enterprise-sec-prj.iam.gserviceaccount.com --project=enterprise-sec-prj --role="roles/iam.workloadIdentityUser" --member="principalSet://iam.googleapis.com/projects/123456789012/locations/global/workloadIdentityPools/ci-pool/attribute.repository/acme/platform-app"
- Generate the credential configuration used by workloads:
gcloud iam workload-identity-pools create-cred-config projects/123456789012/locations/global/workloadIdentityPools/ci-pool/providers/github-provider --service-account=github-deployer@enterprise-sec-prj.iam.gserviceaccount.com --output-file=gha-wif-config.json --credential-source-file=/var/run/secrets/oidc/token
- Authenticate and test access:
gcloud auth login --cred-file=gha-wif-config.json
gcloud auth print-access-token
gcloud artifacts repositories list --location=us-central1
Code Examples
1. Bash validation flow
export GOOGLE_APPLICATION_CREDENTIALS=gha-wif-config.json
gcloud auth application-default print-access-token
curl -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" "https://artifactregistry.googleapis.com/v1/projects/enterprise-sec-prj/locations/us-central1/repositories"
2. GitHub Actions workflow
name: deploy
on:
push:
branches: [ main ]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: google-github-actions/auth@v2
with:
workload_identity_provider: projects/123456789012/locations/global/workloadIdentityPools/ci-pool/providers/github-provider
service_account: github-deployer@enterprise-sec-prj.iam.gserviceaccount.com
- run: gcloud run services list --region us-central1 --project enterprise-sec-prj
3. Python ADC usage
from google.cloud import storage
client = storage.Client(project="enterprise-sec-prj")
for bucket in client.list_buckets():
print(bucket.name)
Security Hardening
- Use attribute conditions to restrict trusted repositories, branches, environments, or AWS roles.
- Grant only
roles/iam.workloadIdentityUseron the specific service account, not broad project-wide impersonation. - Prefer dedicated service accounts per workload to isolate blast radius.
- Enable Cloud Audit Logs for
sts.googleapis.comandiamcredentials.googleapis.com. - Store subject tokens only in ephemeral runtime memory or mounted short-lived files.
- Combine WIF with organization policies, VPC Service Controls, and conditional IAM where applicable.
- Use customer-managed encryption for downstream services, although WIF tokens themselves are short-lived and managed by Google.
Comparison
| Feature | Google Cloud Workload Identity Federation | AWS IAM Roles Anywhere | HashiCorp Vault JWT/OIDC Auth |
|---|---|---|---|
| Pricing | No separate premium SKU; standard IAM and API usage | Charged with AWS Private CA and related services | Vault licensing and operational cost |
| Deployment | Native to Google Cloud IAM and STS | Native to AWS, certificate-based | Self-managed or HCP deployment |
| Scalability | Global managed control plane, strong for CI/CD and multi-cloud | Strong for X.509-based workloads | Highly flexible but operationally heavier |
| Security | Short-lived tokens, attribute mapping, SA impersonation, audit logs | Short-lived AWS creds, certificate trust model | Rich policy engine, secret brokering, more moving parts |
Troubleshooting
Error 1: Invalid audience
Log sample:
ERROR: (gcloud.auth.login) invalid_grant: Error connecting to the given credential's issuer.
{"error":"invalid_target","error_description":"The audience in ID Token [https://github.com/acme/platform-app] does not match the expected audience"}
Fix: Ensure the provider resource name is used as the audience and that the external IdP issues the token for that audience.
Error 2: Missing impersonation permission
Log sample:
PERMISSION_DENIED: Permission 'iam.serviceAccounts.getAccessToken' denied on resource 'projects/-/serviceAccounts/github-deployer@enterprise-sec-prj.iam.gserviceaccount.com'
Fix: Add roles/iam.workloadIdentityUser on the target service account for the correct principalSet:// member.
Error 3: Attribute condition mismatch
Log sample:
AUDIT: principalSubject=principal://iam.googleapis.com/projects/123456789012/locations/global/workloadIdentityPools/ci-pool/subject/repo:acme/other-app:ref:refs/heads/main
STATUS: 403
MESSAGE: The given credential is rejected by the attribute condition.
Fix: Review assertion.repository, assertion.ref, and provider condition syntax; align branch and repository claims with actual token values.
Best Practices
Do
- Bind by attributes, for example
attribute.repository/acme/platform-app, instead of trusting an entire pool. - Use one provider per trust boundary, such as separate providers for production and non-production GitHub organizations.
- Rotate trust deliberately by updating issuer conditions and repository restrictions during platform changes.
- Test with audit logs before production rollout.
Don't
- Don't export service account keys as a fallback for pipelines.
- Don't map unnecessary claims into attributes; keep trust decisions minimal.
- Don't reuse a highly privileged service account across unrelated applications.
- Don't skip branch or environment restrictions for deployment workflows.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI