Tired of managing cumbersome API keys for your Terraform Cloud deployments to GCP? There’s a better, more secure way.

In my previous lab post, I showed how to provision a Google Cloud Storage (GCS) bucket using Terraform Cloud (TFC) — but with long-lived service account keys for authentication.

That method works… but it comes with real security baggage:

  • Static credentials that must be rotated manually

  • Higher risk if keys are leaked

  • Clumsy management overhead in CI/CD pipelines

This post is all about solving that problem — by ditching API keys and upgrading to Workload Identity Federation (WIF).

Why Workload Identity Federation? 🔐

Workload Identity Federation allows external identities (like Terraform Cloud, GitHub Actions, etc.) to authenticate to GCP without needing service account keys. Instead of uploading secrets, your CI/CD platform presents an OIDC identity that GCP trusts — and issues short-lived tokens in return.

Key Benefits of WIF Over API Keys:

  • Better security: No long-lived secrets, short-lived tokens, automatic rotation

  • Reduced credential sprawl: No need to manage and distribute service account keys

  • Granular access control: Attribute-based identity mapping lets you apply least privilege per workspace

  • Improved auditability: Authentication is tied to identity pools and issuers

Step-by-Step: Provision GCS Bucket with WIF

Let’s walk through exactly how to create a GCS bucket from Terraform Cloud using Workload Identity Federation.

🔧 Step 1: Enable Required GCP APIs

gcloud services enable \
  iam.googleapis.com \
  iamcredentials.googleapis.com \
  cloudresourcemanager.googleapis.com

☁️ Step 2: Create a Workload Identity Pool

gcloud iam workload-identity-pools create tfc-pool \
  --location="global" \
  --display-name="Terraform Cloud Pool"

This creates a container for trusted external identities — like Terraform Cloud workspaces.

🪪 Step 3: Add an OIDC Provider for Terraform Cloud

gcloud iam workload-identity-pools providers create-oidc tfc-provider \
  --location="global" \
  --workload-identity-pool="tfc-pool" \
  --display-name="Terraform Cloud Provider" \
  --issuer-uri="https://app.terraform.io" \
  --attribute-mapping="google.subject=assertion.sub" \
  --attribute-condition="assertion.sub.startsWith("organization:<ORG-NAME>:project:<PROJECT_NAME>:workspace:<WORKSPACE_NAME>")"

👤 Step 4: Create a Service Account

gcloud iam service-accounts create tfc-deployer \
  --display-name="Terraform Cloud Deployer"

This account will be impersonated by Terraform Cloud via WIF.

👥 Step 5: Allow Pool to Impersonate Service Account


gcloud iam service-accounts add-iam-policy-binding tfc-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/iam.workloadIdentityUser \
  --member="principal://iam.googleapis.com/projects/$PROJECT_NUM/locations/global/workloadIdentityPools/$POOL_ID/subject/organization:$ORG:project:$TFC_PROJECT:workspace:$WORKSPACE:run_phase:plan"
gcloud iam service-accounts add-iam-policy-binding tfc-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com \
  --role=roles/iam.serviceAccountTokenCreator \
  --member="principal://iam.googleapis.com/projects/$PROJECT_NUM/locations/global/workloadIdentityPools/$POOL_ID/subject/organization:$ORG:project:$TFC_PROJECT:workspace:$WORKSPACE:run_phase:apply"

Replace the following and allow some time for permissions to sync.

  • YOUR_PROJECT_ID

  • PROJECT_NUM

  • POOL_ID

  • ORG

  • TFC_PROJECT

  • WORKSPACE

🗂️ Step 6: Grant Storage Admin role to Service Account

gcloud projects add-iam-iam-policy-binding PROJECT_ID --member="serviceAccount:tfc-deployer@PROJECT_ID.iam.gserviceaccount.com" --role="roles/storage.admin"

This lets Terraform Cloud create buckets. For production use, consider more granular roles like storage.objectCreator.

⚙️ Step 7: Configure Terraform Cloud Workspace Variables

In your Terraform Cloud workspace, add the following environment variables:

Name

Value

Sensitive

project_id

Your GCP project ID

No

TFC_GCP_PROVIDER_AUTH

true

No

TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL

No

region

us-central1

No

TFC_GCP_WORKLOAD_PROVIDER_ID

projects/YOUR_PROJECT_NUMBER/locations/global/workloadIdentityPools/tfc-pool/providers/tfc-provider

No

Marking sensitive variables is optional here as none of these contain secrets — but it’s good hygiene.

📦 Step 8: Terraform HCL for GCS Bucket

Here’s a minimal main.tf to test the setup:

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "6.50.0"
    }
  }
}

provider "google" {
  project = var.project_id
  region  = var.region
}

resource "google_storage_bucket" "example" {
  name     = "my-wif-secured-bucket-${random_id.bucket_suffix.hex}"
  location = var.region
  uniform_bucket_level_access = true
  labels = {
    environment = "test"
  }
}

resource "random_id" "bucket_suffix" {
  byte_length = 4
}

variable "project_id" {
  description = "The GCP project ID where resources will be created"
  type        = string
}

variable "region" {
  description = "The GCP region to deploy resources into"
  type        = string
}

Testing & Verification

  1. Push your Terraform code to GitHub (or your VCS).

  2. Trigger a plan or apply in Terraform Cloud.

  3. Confirm:

    • No API key or static credentials required

    • Authentication succeeds in run logs

    • GCS bucket appears in your GCP console

🧯 Troubleshooting & Best Practices

  • Double-check IAM roles and identity pool bindings

  • Ensure your terraform_workspace_id in attribute mapping matches your TFC workspace

  • Always prefer least privilege — avoid giving storage.admin if your use case only needs object creation

  • Use separate pools/providers for different environments (dev, staging, prod)

🔚 Conclusion: Make WIF Your Default

Workload Identity Federation represents the next step in secure, scalable Terraform-GCP workflows.

  • No more API key sprawl

  • Fine-grained access controls

  • Seamless integration with Terraform Cloud

If you're still using service account keys, now's the time to switch. WIF is what modern CI/CD pipelines need — especially when managing cloud infrastructure at scale.

📬 Want More Like This?

#DevOps #TerraformCloud #GoogleCloud #WorkloadIdentityFederation #IaC #CloudSecurity #Terraform #GCP #CI/CD #SecurityBestPractices

Keep reading