GitHub

Impersonation

Every developer has different IAM permissions on their personal GCP account. One person might have roles/editor while another has roles/viewer. This means the same terraform plan command can produce different results for different developers — permissions errors, missing resources, or inconsistent state.

TFO solves this by routing all Terraform operations through a shared service account. The developer’s personal credentials are used only to impersonate this service account, never to access infrastructure directly. Every developer gets identical IAM permissions, producing identical plan results.

Authentication Flow

When running ./zig/zig build plan or ./zig/zig build apply, the system:

  1. Checks if impersonation is required — only in local mode when a project is selected. Global commands (fmt, check, clean) skip impersonation.
  2. Validates existing token — checks .token_metadata for a valid, non-expired token from the same Google account. Tokens within 90 seconds of expiration are proactively invalidated to prevent mid-operation failures.
  3. Generates a new token if needed — runs gcloud auth print-access-token --impersonate-service-account with the service account and lifetime from config.json.
  4. Fetches Azure credentials (if configured) — retrieves the Azure client secret from GCP Secret Manager using the impersonated service account.
  5. Writes credential files — creates development.local.tfvars with the impersonation token (and optional Azure credentials). Both this file and .token_metadata are written atomically using a temp-file-then-rename pattern to prevent corruption from concurrent TFO processes.

During recursive operations across many modules, the token is re-validated before each module. If it has expired, a new token is generated transparently.

Configuration

Each project’s impersonation is configured via infra/{project-name}/config.json:

{
  "service_account": "<project>-infra-dev-sa@<seed-project>.iam.gserviceaccount.com",
  "token_lifetime_seconds": 3600
}
Field Purpose
service_account GCP service account email used for impersonation
token_lifetime_seconds Token TTL in seconds (3600 = 1 hour)
azure_client_id Azure AD application client ID (null for GCP-only projects)
azure_secret_name Name of the secret in GCP Secret Manager (null for GCP-only)
secrets_project GCP project hosting the Azure secret (null for GCP-only)

File Locations

File Purpose
infra/{project-name}/config.json Impersonation configuration
infra/{project-name}/development.local.tfvars Auto-generated credential file (never committed)
infra/{project-name}/.token_metadata Token expiration and account metadata (never committed)
Edit this page