Cloud & Infrastructure

GCP Workload Identity Federation: Eliminating IAM Keys

By DexNox Dev Team Published May 20, 2026

Securing deployments in public cloud environments requires robust identity management. Traditionally, to grant external CI/CD pipelines (such as GitHub Actions) or multi-cloud workloads (running on AWS or local servers) access to Google Cloud Platform (GCP) resources, developers created service accounts and downloaded static JSON private key files.

However, static keys introduce security risks. They do not expire automatically, are difficult to rotate, and are vulnerable to accidental exposure in public repositories, build logs, and storage backups. If a key is compromised, an attacker obtains persistent access to your GCP resources.

Google Cloud’s Workload Identity Federation (WIF) addresses this risk by eliminating static service account keys. By establishing trust between GCP and external identity providers (IdPs), WIF allows workloads to authenticate using short-lived OpenID Connect (OIDC) or SAML 2.0 security tokens.

This guide analyzes Workload Identity Federation concepts, details a Terraform HCL configuration for GitHub Actions integration, provides a companion GitHub Actions workflow, and lists common production failures with tested mitigations.


Workload Identity Federation Architecture

Workload Identity Federation uses a token exchange protocol based on OIDC or SAML standards.

OIDC Token Exchange Workflow:

1. Request: GitHub Actions runner requests an OIDC token from GitHub's token authority.
2. Token Issue: GitHub issues a signed JWT token containing claims:
   { "repository": "my-org/my-repo", "actor": "developer", ... }
3. STS Exchange: Runner sends the JWT to GCP Security Token Service (STS).
4. Validation: GCP STS verifies the signature against GitHub's public keys.
5. Assertion Check: STS validates that the claims match the allowed repository mappings.
6. Federated Token: STS returns a short-lived GCP federated access token.
7. Service Account Impersonation:
   Runner exchanges the federated token for a short-lived Google Service Account token
   (Valid for max 1 hour, used to execute GCP APIs).

By using this multi-step exchange, the application never stores long-lived credentials. All credentials generated are temporary and expire automatically within an hour, reducing the blast radius of a credential compromise.


Production Integration Code

Below is a complete, production-grade infrastructure deployment using Terraform HCL. It sets up a Workload Identity Pool, configures an OIDC provider for GitHub Actions with strict attribute conditions, creates a GCP Service Account, and grants the provider permission to impersonate the service account.

1. Terraform Workload Identity Stack (main.tf)

# main.tf

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = "dexnox-production-120"
  region  = "us-central1"
}

# 1. Create a Workload Identity Pool
resource "google_iam_workload_identity_pool" "github_pool" {
  workload_identity_pool_id = "github-actions-pool-prod"
  display_name              = "GitHub Actions Pool"
  description               = "Identity pool for federated authentication from GitHub Actions workflows"
  disabled                  = false
}

# 2. Configure the OIDC Workload Identity Provider for GitHub
resource "google_iam_workload_identity_pool_provider" "github_provider" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "github-provider-prod"
  display_name                       = "GitHub OIDC Provider"
  
  # Configure GitHub's OIDC issuer URL
  oidc {
    issuer_uri = "https://token.actions.githubusercontent.com"
  }

  # Map GitHub OIDC claims to GCP security attributes
  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.repository" = "assertion.repository"
    "attribute.actor"      = "assertion.actor"
  }

  # Enforce strict security conditions: Only allow builds from a specific repository
  attribute_condition = "attribute.repository == 'dexnox-org/core-platform'"
}

# 3. Create the Target Service Account
resource "google_service_account" "ci_deployer_sa" {
  account_id   = "github-actions-deployer"
  display_name = "GitHub Actions Deployment Service Account"
}

# 4. Grant the target Service Account role permissions (e.g., S3-like Cloud Storage Admin)
resource "google_project_iam_member" "sa_storage_admin" {
  project = "dexnox-production-120"
  role    = "roles/storage.admin"
  member  = "serviceAccount:${google_service_account.ci_deployer_sa.email}"
}

# 5. Authorize the Workload Identity Pool to impersonate the Service Account
resource "google_service_account_iam_member" "wif_impersonation" {
  service_account_id = google_service_account.ci_deployer_sa.name
  role               = "roles/iam.serviceAccountTokenCreator"

  # Restrict access to federated identities originating from the allowed repository mapping
  member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_pool.name}/attribute.repository/dexnox-org/core-platform"
}

2. GitHub Actions Authentication Workflow (.github/workflows/deploy.yml)

This YAML workflow demonstrates how to authenticate with GCP and upload files to Cloud Storage using the configured Workload Identity Provider.

# .github/workflows/deploy.yml
name: Deploy Assets to Google Cloud Storage

on:
  push:
    branches:
      - main

permissions:
  contents: read
  id-token: write # Required for requesting the JWT OIDC token from GitHub

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      # 1. Authenticate with Google Cloud using OIDC
      - name: Authenticate to Google Cloud
        id: auth
        uses: google-github-actions/auth@v2
        with:
          token_format: "access_token"
          # Provide the full resource path of the Workload Identity Provider
          workload_identity_provider: "projects/123456789012/locations/global/workloadIdentityPools/github-actions-pool-prod/providers/github-provider-prod"
          service_account: "github-actions-deployer@dexnox-production-120.iam.gserviceaccount.com"
          create_credentials_file: true

      # 2. Deploy static assets using the authenticated service account
      - name: Upload Static Assets to GCS
        uses: google-github-actions/upload-cloud-storage@v2
        with:
          path: "./public"
          destination: "dexnox-assets-bucket-prod"

Authentication Strategy Comparison

The table below compares different GCP authentication strategies across security, operational, and auditing dimensions:

Security MetricStatic JSON KeysScripted Key RotationWorkload Identity (GKE)Workload Identity Federation (WIF)
Credential LifespanInfinite (Until revoked)1 to 30 days (Manual)1 hour (Auto-renewed)1 hour (Short-lived token)
Key Leakage RiskHigh (Committed files)MediumZeroZero
Rotation OverheadHigh (Manual task)Medium (Script errors)Zero (Automated)Zero (Automated)
External Cloud SupportCompleteCompleteGKE Clusters OnlyComplete (OIDC/SAML providers)
Audit Trails (CloudAudit)Vague (Shared key ID)VagueClear (Bound to pod)Clear (Repository + Actor mapped)
Compliance RatingFail (PCI-DSS / SOC2)FailPassPass (Gold Standard)
Configuration ComplexityNoneHighMediumMedium

What Breaks in Production: Failure Modes and Mitigations

Deploying Workload Identity Federation across production pipelines exposes authentication routes to specific configuration bugs. Below are four common production failure modes and their mitigations.

1. Claim Mapping Mismatches and Rejected Token Requests

When setting up WIF providers, developers must map claims from the external provider’s token to GCP attributes. If these mappings contain syntax errors or look for missing claims, the Security Token Service (STS) will reject the exchange request with a 400 Bad Request or Invalid Subject error.

  • Root Cause: The OIDC token payload from the provider does not contain the mapped claims, or the attribute condition evaluated to false.
  • Mitigation: Verify the exact claims sent by your provider’s OIDC token. For GitHub Actions, inspect the public OIDC configuration (https://token.actions.githubusercontent.com/.well-known/openid-configuration) and ensure that your attribute mappings match the token properties:
    # Ensure assertion mappings match GitHub token definitions
    attribute_mapping = {
      "google.subject"       = "assertion.sub"
      "attribute.repository" = "assertion.repository"
    }
    

2. Missing Service Account Token Creator Role

Even if the OIDC token validates successfully and GCP STS issues a federated token, the authentication flow can fail at the final stage when attempting to assume the target Service Account, returning an IAM_SE_ACCOUNT_IMPERSONATION_FAILED or 403 Forbidden error.

  • Root Cause: The Workload Identity Pool principal has not been granted the roles/iam.serviceAccountTokenCreator role on the target service account.
  • Mitigation: Grant the impersonation role to the federated pool principal using Terraform:
    resource "google_service_account_iam_member" "wif_impersonation" {
      service_account_id = google_service_account.my_sa.name
      role               = "roles/iam.serviceAccountTokenCreator"
      member             = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.my_pool.name}/attribute.repository/my-org/my-repo"
    }
    

3. Missing Github Permissions (id-token: write)

When running a GitHub Actions workflow that implements WIF, the authentication step can fail immediately with a Credentials file not found or Failed to fetch OIDC token error.

  • Root Cause: GitHub Actions workflows do not have permission to request an OIDC ID token by default. The runner cannot retrieve the JWT token needed for the GCP STS exchange.
  • Mitigation: Declare the id-token: write permission explicitly in your GitHub Actions YAML workflow:
    permissions:
      contents: read # Allow checking out code
      id-token: write # Grant permission to request OIDC token
    

4. Project ID vs. Project Number Mismatches in Provider Paths

When configuring the workload_identity_provider string in your CI/CD configuration files, developers often construct paths using the GCP Project ID: projects/my-project-id/locations/global/....

  • Root Cause: The OTel/Google Authentication libraries resolve provider configurations faster and more reliably when using the numeric Project Number instead of the Project ID. Using the alphanumeric Project ID can cause resolution failures.
  • Mitigation: Always use the numeric GCP Project Number (e.g. projects/123456789012/locations/global/...) when defining the provider path in your deployment configurations:
    # Use Project Number instead of Project ID
    workload_identity_provider: "projects/123456789012/locations/global/workloadIdentityPools/github-actions-pool-prod/providers/github-provider-prod"
    

Frequently Asked Questions

What is Workload Identity Federation?

Workload Identity Federation is an authentication mechanism that allows external workloads to access GCP resources using short-lived tokens, eliminating the need for static, long-lived JSON service account keys.

How does OIDC token exchange work in GCP?

The workload fetches an OIDC token from its identity provider and exchanges it with GCP’s Security Token Service (STS). STS validates the signature, maps claims, and returns a short-lived GCP access token.

Why are static service account keys considered a security risk?

Static JSON keys do not expire automatically. If they are committed to source control or leaked in build logs, they grant persistent access to your GCP resources until manually revoked.

What IAM role is required to exchange federated tokens for service account tokens?

The federated identity principal must be granted the Service Account Token Creator role (roles/iam.serviceAccountTokenCreator) on the target Service Account.


Wrapping Up

Implementing GCP Workload Identity Federation is a key security measure for cloud-native applications. By replacing static JSON service account keys with short-lived OIDC tokens, developers can secure deployment pipelines and multi-cloud workloads. Configuring OIDC claim mappings, granting impersonation permissions, enabling OIDC tokens in workflows, and using Project Numbers instead of Project IDs ensures that your authentication infrastructure remains secure, performant, and reliable under heavy workloads.

Frequently Asked Questions

What is Workload Identity Federation?

Workload Identity Federation is an authentication mechanism that allows external workloads (such as GitHub Actions or AWS tasks) to access GCP resources using short-lived tokens, eliminating the need for static, long-lived JSON service account keys.

How does OIDC token exchange work in GCP?

The external workload fetches an OIDC token from its identity provider and exchanges it with GCP's Security Token Service (STS) for a short-lived Google access token, validating claims like repository paths.

Why are static service account keys considered a security risk?

Static JSON keys do not expire automatically. If they are accidentally committed to source control or leaked in build logs, they grant persistent access to your GCP resources until manually revoked.

What IAM role is required to exchange federated tokens for service account tokens?

The federated identity principal must be granted the Service Account Token Creator role (roles/iam.serviceAccountTokenCreator) on the target GCP Service Account.