Cloud · Google Cloud Data Platform

Workload Identity Federation for keyless CI/CD in GCP pipelines

gcpHardgcpiamworkload-identitysecurity

Interview question

How does Workload Identity Federation eliminate service account JSON keys in automated CI/CD deployment pipelines?

How to answer

The short answer

Deploying automated , BigQuery DDL schemas, and Cloud Functions via CI/CD platforms (such as GitHub Actions or GitLab CI) requires authenticating pipeline runners against Google Cloud.

Historically, teams created service accounts, generated long-lived service account private keys, and stored them as secrets in GitHub repositories.

The vulnerability of downloadable service account keys

Storing service account keys in external repositories creates severe security risks:

  • Keys have no default expiration dates; compromised keys can provide unauthorized access for months or years.
  • Keys can be accidentally leaked in pipeline build logs or committed to code repositories.
  • Rotating keys across dozens of repositories requires complex custom automation.

Google Cloud explicitly recommends disabling service account key creation across organizations.

Keyless authentication with Workload Identity Federation

Workload Identity Federation allows external CI/CD platforms to impersonate Google Cloud service accounts without private keys using OpenID Connect (OIDC).

Output
GitHub Actions Runner
         |
         v 1. Requests OIDC token signed by GitHub
GitHub OIDC Provider
         |
         v 2. Sends GitHub OIDC JWT token
Google Cloud Security Token Service (STS)
         |
         v 3. Validates issuer, repository, and branch attributes
Google Cloud IAM
         |
         v 4. Issues short-lived Google OAuth access token (1 hour)
Target GCP Service Account (Deploys BigQuery / Dataflow)

Enforcing repository-level least privilege

Administrators configure an Attribute Condition restricting which workflows can assume the service account:

Output
attribute.repository == "my-company/data-platform" &&
attribute.ref == "refs/heads/main"

Only pull requests merged into the production main branch can impersonate the deployment identity, completely eliminating secret key leaks.