Google Cloud Platform's Workload Identity Federation eliminates long-lived service account keys by replacing secrets with trust relationships, and one organization rolled it out to over 120 projects in six months.

Every time a team onboards a CI/CD tool or grants a third-party service access to Google Cloud Platform, the same ritual plays out: navigate to Identity and Access Management, create a service account, download a JSON key, paste it into a secret store. That pattern repeats across every project, every integration, every time. And it creates a security problem that compounds silently.
Workload Identity Federation (WIF) offers a different model. Instead of handing a credential to an external system, you declare which external identity providers GCP should trust and under what conditions. When an external workload needs access, it presents its own native token to GCP's Security Token Service. GCP validates that token against your configuration and, if it passes, issues a short-lived GCP access token. The job runs, the token expires, nothing is stored and nothing needs to be rotated.
The Anatomy of a Federated Trust
WIF follows a three-part structure across all implementations: a pool, a provider, and a service account binding.
The Workload Identity Pool is a named container that groups external identity configurations. On its own, it does nothing. Think of it as a folder for trust configurations.
The Provider lives inside the pool and defines the actual trust relationship. One provider per external identity system tells GCP where tokens come from, how to validate them, how to map their claims to GCP-understandable attributes, and which specific identities are allowed through.
The Service Account Binding connects validated external identities to actual GCP permissions. You bind specific pool identities to a service account, and the workload temporarily inherits that service account's IAM permissions.
Attribute conditions serve as the critical security gate. Without them, any identity from a trusted provider can authenticate, which is too broad for production environments. With them, you can restrict access to a specific organization, repository, account, or any claim the token contains.
Scaling to 120 Projects in Six Months
One organization made WIF mandatory for every new GCP project as part of a cloud modernization initiative. No new project received a service account key. Deployments ran through Harness pipelines using federated identity. Within six months, more than 120 projects authenticated this way.
The key decision: they drew a line at the point of creation rather than attempting to migrate existing keys. Their environment had hundreds of service account keys with no expiry set, some years old. Retrofitting those keys required coordinating across every team and system holding a copy, with outage risk at each step and no clean way to prove a given key was actually dead rather than merely unused.
Legacy keys did not disappear, but they stopped multiplying. The problem shifted from an ever-growing attack surface into a fixed, shrinking one. Because every project inherited the same pattern, scoping conventions were settled once rather than diverging across teams. After the first few providers, each new integration was a copy of a trusted configuration rather than a fresh design decision.
OIDC Connectors: Teaching GCP to Read External Tokens
Most modern CI/CD platforms support OpenID Connect. When a workflow runs, the platform generates a short-lived JSON Web Token (JWT) for that run, cryptographically signed by the platform's own OIDC issuer. The token contains claims describing which repository, organization, or pipeline account originated the run.
The OIDC connector teaches GCP to understand these tokens. When you configure a provider of type OIDC inside your pool, you define three things:
- The Issuer URL — The OIDC endpoint of the external platform. GCP fetches the platform's public keys from this URL and uses them to verify incoming tokens.
- Attribute Mappings — A translation layer. GCP does not natively understand Harness claim names or GitHub claim names. The mappings tell GCP to call
assertion.account_idby the nameattribute.account_id. The reserved mappinggoogle.subject = assertion.subis always required and becomes the principal identity. - Attribute Conditions — A Common Expression Language (CEL) expression that filters which identities are allowed through.
For GitHub Actions, the setup requires creating the pool and OIDC connector, binding the pool to a service account, and adding the id-token: write permission to the workflow. No secret is stored in GitHub. The token lasts for the duration of the workflow run and expires automatically.
For Harness, the issuer URL is tied to your account: https://app.harness.io/ng/api/oidc/account/YOUR_HARNESS_ACCOUNT_ID. The attribute mappings extract Harness-specific fields from the JWT. A common mistake is omitting the organization_id check and only filtering on account_id — acceptable for single-org Harness accounts, but too permissive for multi-org setups.
AWS Workloads: A Different Token Model
AWS does not use OIDC for its workload tokens. It uses its own format based on AWS STS AssumeRole. WIF handles this with a dedicated provider type rather than OIDC.
When code runs on an AWS workload — an EC2 instance, a Lambda function, or an ECS task — AWS automatically gives it temporary credentials tied to an IAM role. These credentials consist of an access key ID, a secret access key, and a session token. When that workload wants to prove its identity to an outside system, it uses these credentials to call AWS STS GetCallerIdentity. This API call returns a signed response saying the request genuinely came from a specific IAM role in a specific AWS account. The signature on that response can only be produced by AWS itself.
GCP does not take the AWS account ID at face value. It receives the AWS credential package, calls AWS STS GetCallerIdentity on your behalf using the signed request, receives the IAM role ARN and account ID, and checks the response against your configuration. If the account ID matches the one in your AWS provider, the token passes.
The service account binding for AWS scopes down to a specific IAM role, not just the account. The workload uses a GCP credential configuration file generated via gcloud iam workload-identity-pools create-cred-config and sets it as the GOOGLE_APPLICATION_CREDENTIALS environment variable. GCP client libraries detect this file format automatically.
Security Considerations
WIF solves the key leakage problem but introduces its own attack surface if configured carelessly.
Attribute conditions are not optional in production. The default behavior allows any authenticated identity from the provider to exchange tokens. For GitHub, that allows any public repository on the platform to potentially authenticate to your pool if the issuer URL matches.
Use principalSet scoping carefully. The difference between principal:// (a single specific subject) and principalSet:// (all identities matching an attribute) has significant blast radius implications. Start narrow — a specific repository or pipeline — and widen only when operationally necessary.
Short-lived does not equal zero risk. WIF tokens typically last one hour. If a token is intercepted within that window, it can be used. Mitigate by scoping service accounts to minimum permissions and enabling Virtual Private Cloud Service Controls where applicable.
Audit token exchanges. Enable Cloud Audit Logs on the IAM API to capture token exchange events with full metadata: which subject, which provider, which service account was impersonated.
Direct Access vs. Impersonation
WIF lets you grant IAM roles straight to the federated principal on the resource (direct access) or route through a service account (impersonation). Google recommends direct access as the default for its simplicity and visibility.
But impersonation has practical advantages for teams managing many projects. An external identity federates once but often needs access across many projects and pipelines over time. Routing through service accounts means revoking access requires one action instead of an audit across every project the identity touched. Direct access also clears per-API limitations for every service a pipeline calls rather than once at setup.
One operation where direct access cannot work at all: Cloud Storage signed URLs. A signed URL is not an authenticated API call — it is a URL handed to someone with no GCP identity. What makes it trustworthy is a cryptographic signature tied to a specific service account. Producing that signature needs either the service account's private key or the iam.serviceAccounts.signBlob permission, neither of which exists for a bare federated principal. Under impersonation, signing works because the federated token calls signBlob on the impersonated service account.
When WIF Does Not Apply
WIF covers workload-to-GCP authentication, but not every scenario. Human users authenticating to GCP should use Cloud Identity or Workforce Identity Federation, designed for people rather than machines. Some GCP services and client libraries have limitations with federated credentials — check the supported services list before building against something less common than GitHub Actions or Google Kubernetes Engine.
If you are running workloads inside GCP, on Compute Engine, GKE, or Cloud Run, you do not need WIF. Those workloads already have a first-class GCP identity via the metadata server. WIF is for workloads that live outside GCP.
The Fundamental Shift
The move from service account keys to WIF changes how teams think about machine identity. Keys are secrets you manage. Federated identities are trust relationships you configure. One requires operational discipline to stay secure. The other is secure by design.
The practical consequence is repeatability. Create a pool, add a provider with a tight attribute condition, and bind a least-privilege service account. That sequence held across every integration, which is the only reason mandating it across new projects was realistic. A pattern that needs rethinking each time does not scale to a hundred teams.
For teams running CI/CD pipelines or connecting third-party services to GCP, WIF should be the default choice. There is nothing to rotate, nothing to accidentally commit, and nothing that gives an attacker permanent access if intercepted.

Comments
Please log in or register to join the discussion