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:
- Checks if impersonation is required — only in local
mode when a project is selected. Global commands (
fmt,check,clean) skip impersonation. - Validates existing token — checks
.token_metadatafor a valid, non-expired token from the same Google account. Tokens within 90 seconds of expiration are proactively invalidated to prevent mid-operation failures. - Generates a new token if needed — runs
gcloud auth print-access-token --impersonate-service-accountwith the service account and lifetime fromconfig.json. - Fetches Azure credentials (if configured) — retrieves the Azure client secret from GCP Secret Manager using the impersonated service account.
- Writes credential files — creates
development.local.tfvarswith the impersonation token (and optional Azure credentials). Both this file and.token_metadataare 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) |