GCP Customer Workload Identity

This guide is the canonical customer walkthrough for connecting a customer GCP project to Dart Cloud Functions (DCF) through Workload Identity Federation (WIF).

The current DCF GCP onboarding flow is:

  1. The customer owns the GCP project.

  2. The customer owns the GCP service account that DCF will impersonate.

  3. The customer owns the workload identity pool and provider that trust DCF’s Kubernetes identity.

  4. The customer grants roles/iam.workloadIdentityUser on that service account to the federated DCF principal.

This setup is one-time per customer project/environment. It is not repeated for every function deployment or release unless the customer changes project, service account, or workload identity pool/provider.

This is the current customer-owned WIF model. Do not use the older direct service-account pattern of granting roles/iam.serviceAccountTokenCreator or roles/iam.serviceAccountUser to serviceAccount:flux-gsa-dcf-dev@aortem-prod.iam.gserviceaccount.com for this onboarding flow.

What The Customer Must Provide To DCF

After the customer-side setup is complete, enter these values in the DCF GCP integration form:

  • gcpProjectId

  • serviceAccountEmail

  • workloadIdentityProjectNumber

  • workloadIdentityPool

  • workloadIdentityProvider

Example:

Standard Customer Contract

To keep onboarding consistent across customers, standardize on these IDs unless the customer is explicitly reusing existing approved workload identity resources:

  • workloadIdentityPool=dcf-gke-pool

  • workloadIdentityProvider=dcf-gke-provider

For most customers, only these values should vary:

  • gcpProjectId

  • serviceAccountEmail

  • workloadIdentityProjectNumber

To reduce support drift, recommend these customer-side names in the docs:

  • Customer service account ID: dcf-<environment>-1

  • Workload identity pool ID: dcf-gke-pool

  • Workload identity provider ID: dcf-gke-provider

Examples:

  • Development service account: dcf-dev-1@<customer-project-id>.iam.gserviceaccount.com

  • Production service account: dcf-prod-1@<customer-project-id>.iam.gserviceaccount.com

The customer can use different names, but then the exact service account, project number, pool, and provider values entered in DCF must match what exists in GCP exactly.

Current DCF Identity Values

Use the DCF environment that matches the customer environment you are connecting.

Development

Production

Customer Setup Steps

1. Choose The Customer Service Account

Create or select a customer-owned service account in the customer project. DCF will impersonate this service account after the workload identity exchange succeeds.

Example:

  • dcf-dev-1@venturseed-website-dev.iam.gserviceaccount.com

The IAM binding that matters for onboarding is attached to the service account itself, not just the project IAM page.

2. Create A Workload Identity Pool

In the customer project, create a workload identity pool that will host the provider trusted by DCF.

PROJECT_ID="venturseed-website-dev"

gcloud services enable \
  iam.googleapis.com \
  iamcredentials.googleapis.com \
  sts.googleapis.com \
  --project="$PROJECT_ID"

If those APIs are already enabled, this command is safe to rerun.

PROJECT_ID="venturseed-website-dev"

gcloud iam workload-identity-pools create "dcf-gke-pool" \
  --project="$PROJECT_ID" \
  --location="global" \
  --display-name="DCF GKE Pool"

3. Create An OIDC Provider Trusted By DCF

Create an OIDC provider in that pool:

  • issuer-uri must match the DCF OIDC issuer for the environment.

  • attribute-mapping must include google.subject=assertion.sub.

  • allowed-audiences should match the current DCF bound token audience, which follows the same cluster URL used as the DCF issuer in the current runtime.

PROJECT_ID="venturseed-website-dev"
POOL_ID="dcf-gke-pool"
PROVIDER_ID="dcf-gke-provider"
DCF_ISSUER="https://container.googleapis.com/v1/projects/aortem-prod/locations/us-central1/clusters/aortem-infrastructure-core-new"

gcloud iam workload-identity-pools providers create-oidc "$PROVIDER_ID" \
  --project="$PROJECT_ID" \
  --location="global" \
  --workload-identity-pool="$POOL_ID" \
  --display-name="DCF Dev Provider" \
  --issuer-uri="$DCF_ISSUER" \
  --allowed-audiences="$DCF_ISSUER" \
  --attribute-mapping="google.subject=assertion.sub"

If the customer already has a compatible pool and provider, reuse them instead of creating new ones.

4. Grant DCF Workload Identity User On The Customer Service Account

Grant roles/iam.workloadIdentityUser on the customer service account to the federated DCF principal:

PROJECT_ID="venturseed-website-dev"
PROJECT_NUMBER="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')"

CUSTOMER_SA="dcf-dev-1@venturseed-website-dev.iam.gserviceaccount.com"
POOL_ID="dcf-gke-pool"
DCF_SUBJECT="system:serviceaccount:dartcloudfunctions-dev:flux-system-dartcloudfunctions-dev"

gcloud iam service-accounts add-iam-policy-binding \
  "$CUSTOMER_SA" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/subject/$DCF_SUBJECT"
If the workload identity pool lives in a different identity-host project, use that pool-host project’s numeric project number in the principal://…​ member and enter that value into workloadIdentityProjectNumber.

5. Validate The Customer Setup

Before entering values in DCF, confirm the customer setup is active and matches the DCF runtime identity.

gcloud iam workload-identity-pools describe dcf-gke-pool \
  --project=venturseed-website-dev \
  --location=global

gcloud iam workload-identity-pools providers describe dcf-gke-provider \
  --project=venturseed-website-dev \
  --location=global \
  --workload-identity-pool=dcf-gke-pool

gcloud iam service-accounts get-iam-policy \
  dcf-dev-1@venturseed-website-dev.iam.gserviceaccount.com \
  --project=venturseed-website-dev

gcloud services list --enabled \
  --filter="NAME:(iam.googleapis.com OR iamcredentials.googleapis.com OR sts.googleapis.com)"

Expected results:

  • The workload identity pool is ACTIVE.

  • The workload identity provider is ACTIVE.

  • The provider attribute mapping includes google.subject: assertion.sub.

  • The provider issuerUri matches the DCF runtime issuer.

  • The provider allowedAudiences contains that same DCF runtime issuer value.

  • The service account IAM policy includes roles/iam.workloadIdentityUser for the correct federated principal://…​ member.

  • iam.googleapis.com, iamcredentials.googleapis.com, and sts.googleapis.com are enabled.

6. Enter The Values In DCF And Verify

After the customer-side setup is complete, enter these values in DCF:

  • gcpProjectId

  • serviceAccountEmail

  • workloadIdentityProjectNumber

  • workloadIdentityPool

  • workloadIdentityProvider

Then run the DCF verify step.

Complete Example For The Venturseed Development Project

PROJECT_ID="venturseed-website-dev"
PROJECT_NUMBER="$(gcloud projects describe "$PROJECT_ID" --format='value(projectNumber)')"

CUSTOMER_SA="dcf-dev-1@venturseed-website-dev.iam.gserviceaccount.com"
POOL_ID="dcf-gke-pool"
PROVIDER_ID="dcf-gke-provider"

DCF_ISSUER="https://container.googleapis.com/v1/projects/aortem-prod/locations/us-central1/clusters/aortem-infrastructure-core-new"
DCF_SUBJECT="system:serviceaccount:dartcloudfunctions-dev:flux-system-dartcloudfunctions-dev"

gcloud iam workload-identity-pools create "$POOL_ID" \
  --project="$PROJECT_ID" \
  --location="global" \
  --display-name="DCF GKE Pool"

gcloud iam workload-identity-pools providers create-oidc "$PROVIDER_ID" \
  --project="$PROJECT_ID" \
  --location="global" \
  --workload-identity-pool="$POOL_ID" \
  --display-name="DCF Dev Provider" \
  --issuer-uri="$DCF_ISSUER" \
  --allowed-audiences="$DCF_ISSUER" \
  --attribute-mapping="google.subject=assertion.sub"

gcloud iam service-accounts add-iam-policy-binding \
  "$CUSTOMER_SA" \
  --role="roles/iam.workloadIdentityUser" \
  --member="principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/subject/$DCF_SUBJECT"

Then enter:

Validated bootstrap checks for the Venturseed example:

  • pool state is ACTIVE

  • provider state is ACTIVE

  • provider mapping is google.subject: assertion.sub

  • provider issuerUri and allowedAudiences both match the DCF development issuer

  • the customer service account includes the required roles/iam.workloadIdentityUser binding for the DCF development subject

  • iam.googleapis.com, iamcredentials.googleapis.com, and sts.googleapis.com are enabled

  • the DCF values to save are: venturseed-website-dev, dcf-dev-1@venturseed-website-dev.iam.gserviceaccount.com, 1085359854476, dcf-gke-pool, dcf-gke-provider

Current Deployment Note

The current DCF GCP runner does not deploy arbitrary Cloud Functions directly. The implemented GCP path currently:

  • builds a container image with Cloud Build

  • pushes that image to Artifact Registry

  • updates the selected runtime target

Cloud Run is the standard runtime target. GKE remains available as an advanced target for enterprise customers that already provide the cluster, namespace, deployment, and container references.

For Cloud Run, DCF runs gcloud run deploy against the configured serviceName. Public functions use --allow-unauthenticated; private functions use --no-allow-unauthenticated.

For GKE, DCF updates an existing Kubernetes deployment image and waits for the rollout to complete.

That means WIF onboarding is only the trust step. The customer project still needs the separate Cloud Build, Artifact Registry, and runtime-target prerequisites required by the selected target.

Minimum Cloud Run setup normally includes:

  • enabling run.googleapis.com, cloudbuild.googleapis.com, artifactregistry.googleapis.com, iam.googleapis.com, iamcredentials.googleapis.com, and sts.googleapis.com

  • creating the target Artifact Registry Docker repository

  • granting the impersonated customer service account permissions to upload artifacts, start Cloud Build, write the resulting image, and update the Cloud Run service

  • granting roles/iam.serviceAccountUser on the Cloud Run runtime service account if the deployment attaches a user-managed service identity

Security-first customers do not have to grant broad Cloud Run Admin by default. roles/run.developer can be enough to create and update services, but making a service public through IAM requires run.services.setIamPolicy or a customer managed public roles/run.invoker binding.

Common Mistakes

  • Granting roles/iam.serviceAccountTokenCreator to serviceAccount:flux-gsa-dcf-dev@aortem-prod.iam.gserviceaccount.com instead of granting roles/iam.workloadIdentityUser to the federated principal://…​ member.

  • Checking only the project IAM page instead of the service account IAM policy.

  • Entering the customer project ID instead of the numeric workload identity host project number when the pool is hosted in a different project.

  • Reusing a provider that does not trust the DCF issuer or does not map google.subject=assertion.sub.