Home

Published

- 8 min read

Stop Using Service Account Keys: A Guide to Workload Identity Federation

img of Stop Using Service Account Keys: A Guide to Workload Identity Federation

For years, there has been a dirty little secret in the world of cloud automation and CI/CD: the service account key. This humble JSON file, containing a long-lived, static private key, has been the de facto standard for authenticating workloads and pipelines to Google Cloud. We download them, store them as secrets in GitHub or GitLab, and use them to power our automated deployments. And in doing so, we have created a ticking time bomb at the heart of our security posture.

Leaked service account keys are one of the most common and devastating causes of cloud breaches. A single key, accidentally committed to a public Git repository, is all an attacker needs to gain direct, persistent access to your cloud environment.

It’s time for a better way. Google Cloud has provided a powerful, more secure, and keyless alternative: Workload Identity Federation (WIF). This isn’t just another IAM feature; it’s a fundamental paradigm shift in how we handle machine-to-machine authentication. This is the developer’s definitive, no-nonsense guide to understanding the risks of JSON keys and making the switch to a more secure, keyless future with WIF.

Workload Identity Federation Diagram

The Original Sin: Why Service Account Keys Are So Dangerous

Before we dive into the solution, we must be brutally honest about the problem. Service account keys are a security anti-pattern for several critical reasons:

  • They are Long-Lived: By default, a service account key never expires. A key created today will still be valid years from now unless it is manually rotated or deleted.
  • They are Static Credentials: The key is a static file. Once it’s created and distributed, you have no control over where it’s copied, stored, or backed up. It becomes a piece of “secret sprawl” that is nearly impossible to track.
  • They are a High-Value Target: Attackers are continuously scanning public repositories for accidentally committed keys. A leaked key is a direct, authenticated entry point into your cloud environment.
  • Rotation is a Nightmare: Manually rotating keys across dozens of CI/CD pipelines, applications, and developer machines is a complex, error-prone process that is often neglected, leaving old, potentially compromised keys active for far too long.

We have been treating these powerful credentials like simple configuration files, and it has created a massive, systemic risk across the industry.

The Keyless Revolution: How Workload Identity Federation Works

Workload Identity Federation allows external workloads—like a GitHub Actions runner, a GitLab pipeline, or an application running on AWS or Azure—to impersonate a GCP service account without needing a service account key.

Instead of exchanging a long-lived, static key, it uses a secure, short-lived token exchange based on trusted, verifiable identities.

Here’s a simplified breakdown of the flow, using a GitLab CI/CD pipeline as an example:

  1. The External Identity Provider (IdP): Your CI/CD platform (GitLab, in this case) acts as an external Identity Provider. When it runs a pipeline, it can generate a unique, short-lived, and auditable identity token (typically a JSON Web Token or JWT). This JWT contains verifiable claims, such as the Git repository, the branch, and the commit SHA the pipeline is running for.
  2. The Trust Configuration (The One-Time Setup): In GCP, you create a Workload Identity Pool and a Provider. This is where you establish a trust relationship. You are essentially telling GCP: “I trust tokens that are issued by gitlab.com. Specifically, I trust tokens that have an aud (audience) claim matching this project, and a sub (subject) claim matching this specific Git repository.”
  3. The Token Exchange: a. Your GitLab pipeline requests its unique JWT from GitLab’s OIDC provider. b. The pipeline then calls the GCP Security Token Service (STS), presenting this GitLab-issued JWT. c. The STS validates the token. It checks the issuer, the audience, and the subject claims against the trust configuration you created in your Workload Identity Pool.
  4. The Short-Lived GCP Token: If the trust is verified, the STS returns a short-lived GCP access token. This token is valid for a limited time (typically one hour) and can be used to call GCP APIs.
  5. Impersonation: The pipeline uses this short-lived GCP token to impersonate a designated GCP service account, inheriting its permissions for the duration of the job.

The result? The CI/CD pipeline has the access it needs to deploy resources, but there is no static JSON key stored in GitLab, no secret to be leaked, and no long-lived credential to be forgotten. The entire process is dynamic, auditable, and secure by default.

The Practical Blueprint: How to Set Up Workload Identity Federation with GitLab CI/CD

This isn’t just theory. Let’s walk through a concrete, technical implementation based on the excellent guide from Orange Business.

Step 1: Create the Workload Identity Pool and Provider in GCP

First, you need to set up the trust relationship in your GCP project.

   # 1. Create the Workload Identity Pool
gcloud iam workload-identity-pools create "gitlab-pool" \
  --project="your-gcp-project-id" \
  --location="global" \
  --display-name="GitLab Identity Pool"

# 2. Get the full ID of the new pool
gcloud iam workload-identity-pools describe "gitlab-pool" \
  --project="your-gcp-project-id" \
  --location="global" \
  --format="value(name)"

# 3. Create the OIDC Provider within the pool
gcloud iam workload-identity-pools providers create-oidc "gitlab-provider" \
  --project="your-gcp-project-id" \
  --location="global" \
  --workload-identity-pool="gitlab-pool" \
  --display-name="GitLab OIDC Provider" \
  --issuer-uri="https://gitlab.com" \
  --attribute-mapping="google.subject=assertion.sub,attribute.project_path=assertion.project_path"
  • --issuer-uri: This tells GCP to trust tokens issued by GitLab.
  • --attribute-mapping: This is a crucial step. It maps the claims from the GitLab JWT to attributes that you can use in your GCP IAM policies. Here, we are mapping the GitLab subject (e.g., project_path:mygroup/myproject:ref_type:branch:ref:main) to Google’s subject attribute.

Step 2: Create a Dedicated Service Account and Grant Permissions

Create a least-privilege service account that your pipeline will impersonate.

   # 1. Create a dedicated service account
gcloud iam service-accounts create "gitlab-deployer-sa" \
  --project="your-gcp-project-id" \
  --display-name="GitLab Deployer SA"

# 2. Grant the WIF user role to the Workload Identity Pool
gcloud iam service-accounts add-iam-policy-binding "[email protected]" \
  --project="your-gcp-project-id" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principalSet://iam.googleapis.com/[WORKLOAD_IDENTITY_POOL_ID]/attribute.project_path/your-group/your-repo"

This is the magic link. The --member flag grants the “Workload Identity User” role to a specific set of principals from your external IdP. In this case, we are saying: “Only identities from the GitLab repository your-group/your-repo are allowed to impersonate this service account.”

Step 3: Configure Your GitLab CI/CD Pipeline (.gitlab-ci.yml)

Now, configure your GitLab pipeline to perform the token exchange.

   deploy-to-gcp:
  stage: deploy
  image: google/cloud-sdk:latest
  id_tokens:
    GITLAB_OIDC_TOKEN:
      aud: 'https://iam.googleapis.com/[WORKLOAD_IDENTITY_POOL_ID]'
  script:
    - echo "${GITLAB_OIDC_TOKEN}" > .gitlab-oidc-token.jwt
    - gcloud auth login --cred-file <(printf '{"type": "external_account", "audience": "...", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "token_url": "https://sts.googleapis.com/v1/token", "credential_source": { "file": "%s" }}' ".gitlab-oidc-token.jwt")
    - gcloud projects list # This command now works, authenticated via WIF!
  • id_tokens: This special GitLab CI keyword instructs GitLab to fetch a JWT from its OIDC provider.
  • The Credential File: You create a configuration file on the fly that tells the gcloud CLI to use the external account flow, pointing it to the JWT file.
  • gcloud auth login: This command uses the JWT to call the GCP STS and get back a short-lived GCP access token. All subsequent gcloud commands in the script will now be authenticated.

Conclusion: It’s Time to Say Goodbye to Keys

The era of the static, long-lived service account key is over. The risks are too great, and the alternative is now too powerful and accessible. Workload Identity Federation provides a secure-by-default, dynamic, and auditable way to manage machine-to-machine authentication that is purpose-built for the modern CI/CD and multi-cloud landscape.

Migrating away from keys requires a deliberate effort, but it is one of the single most impactful security improvements you can make to your cloud environment. It eliminates a massive class of credential-based risks and sets a new, more secure foundation for your automated workflows. It’s time to stop managing secret files and start managing trust.

To further enhance your cloud security and implement Zero Trust, contact me on LinkedIn Profile or [email protected].

Workload Identity Federation (WIF) FAQ

  • What is Workload Identity Federation? It is a GCP feature that allows external workloads (like a GitHub Action or a VM on AWS) to securely authenticate to GCP and impersonate a service account without needing to use a long-lived service account JSON key.
  • How is WIF more secure than using a service account key? It eliminates static, long-lived credentials. Instead of a key that never expires and can be leaked, WIF uses a short-lived token exchange based on a trusted relationship with an external identity provider (like GitHub or GitLab). This is a “keyless” authentication method.
  • Does Workload Identity Federation only work with GitLab? No. It works with any identity provider that supports OpenID Connect (OIDC), including GitHub, AWS, Azure, and many others.
  • What is an OIDC token? An OIDC (OpenID Connect) token is a type of JSON Web Token (JWT) that is used to prove identity. In the context of WIF, your CI/CD platform (like GitLab) issues a short-lived OIDC token that contains verifiable information about the specific job, repository, and branch that is running.
  • Can I restrict which specific GitHub or GitLab repo can use a WIF configuration? Yes. This is a key security feature. When you grant the “Workload Identity User” role, you can create a condition based on the attributes from the external token, such as the project_path from a GitLab JWT. This allows you to enforce a policy like, “Only the main branch of our production repository can impersonate the production deployer service account.”

Relevant Resource List

  • Google Cloud Documentation: “Workload Identity Federation”
  • Medium Article (Google Cloud Community): “Goodbye Service Account Keys!”
  • Orange Business - Perspectives Blog: “How to secure your Google Cloud resources from a GitLab CI/CD”
  • OpenID Connect (OIDC) Foundation: (For understanding the underlying identity protocol)