IAM Overview¶
A flat list of every GCP service account this Terraform module creates, what roles each one holds, and which Kubernetes service account (if any) impersonates it via Workload Identity.
Code: infrastructure/gcp/gke_iam.tf, cloudbuild_iam.tf, image_updater_iam.tf, plus the SA blocks inside backup.tf and tempo.tf. The photon-indexer SA is not Terraform-managed — it lives outside Terraform alongside the Photon GCS bucket (see bootstrap doc) to keep the planet index safe from terraform destroy.
Workload Identity at a glance¶
Workload Identity is enabled on the cluster with the pool ${project_id}.svc.id.goog. Every binding follows the same shape:
serviceAccount:${project_id}.svc.id.goog[<namespace>/<ksa-name>]
The K8s SA on the left of the arrow can call gcloud auth print-identity-token and pretend to be the GCP SA on the right.
flowchart LR
subgraph K8s["GKE"]
KSA1[argocd/argocd-image-updater]
KSA2[data/postgres-dev]
KSA3[data/postgres-prod]
KSA4[data/photon-indexer]
KSA5[monitoring/tempo]
end
subgraph GCP["GCP service accounts"]
SA1[argocd-image-updater-sa]
SA2[cnpg-backup-sa]
SA3[photon-indexer]
SA4[cloudbuild-worker-sa]
SA5[tempo]
end
KSA1 -. WI .-> SA1
KSA2 -. WI .-> SA2
KSA3 -. WI .-> SA2
KSA4 -. WI .-> SA3
KSA5 -. WI .-> SA5
SA1 -->|artifactregistry.reader| AR[(Artifact Registry)]
SA2 -->|objectAdmin on backup bucket| BK[(tomoda-db-backups-…)]
SA3 -->|objectAdmin on index bucket| PI[(…-photon-index)]
SA4 -->|writer + logger + container.developer| CB[Cloud Build]
SA5 -->|objectAdmin on traces bucket| TR[(…-tomoda-traces)]
The full table¶
| GCP SA | Created in | K8s SA via WI | Roles | What it lets the workload do |
|---|---|---|---|---|
cloudbuild-worker-sa@… |
cloudbuild_iam.tf |
(none — used directly by Cloud Build) | roles/logging.logWriter (project), roles/artifactregistry.writer (project), roles/container.developer (project) |
Cloud Build can write logs, push Docker images to both registries, and (future) deploy to GKE. |
argocd-image-updater-sa@… |
image_updater_iam.tf |
argocd/argocd-image-updater |
roles/artifactregistry.reader (project) |
Argo CD Image Updater lists image tags in both Artifact Registry repos. |
cnpg-backup-sa@… |
backup.tf |
data/postgres-dev and data/postgres-prod |
roles/storage.objectAdmin on tomoda-db-backups-${project_id} |
CNPG Barman writes WAL + base backups for both Postgres clusters into the backup bucket. |
photon-indexer@… |
manual bootstrap (bootstrap doc) | data/photon-indexer |
roles/storage.objectAdmin on ${project_id}-photon-index |
Photon indexer (CronJob, currently suspended; or scripts/photon-index-local.sh) uploads index tarballs. SA + bucket detached from Terraform so destroy can't touch the $500-per-rebuild planet index. |
tempo@… |
tempo.tf |
monitoring/tempo |
roles/storage.objectAdmin on ${project_id}-tomoda-traces |
Grafana Tempo writes trace chunks to (and reads from) the traces bucket. |
Default compute SA 287267207777-compute@developer.gserviceaccount.com |
gke_iam.tf (binding only) |
(implicitly used by GKE nodes) | roles/artifactregistry.reader (project) |
Every GKE node can pull images from both Artifact Registry repos. |
Cross-references¶
| Where to read more | Doc |
|---|---|
| Cloud Build SA + IAM in context | Cloud Build |
| Image Updater flow end-to-end | Artifact Registry |
| CNPG backup wiring | Backup |
| Photon indexer wiring | Photon Indexer |
| GKE node identity & cluster shape | GKE |
Things worth knowing¶
- No SA keys. Every binding above uses Workload Identity or the platform's own impersonation chain. There are no JSON key files in this Terraform — and there should never be. If you see one being added, push back.
- Project-level roles.
roles/artifactregistry.writerandroles/artifactregistry.readerare granted at the project level, not per-repo. Adding a third Artifact Registry repo does not require new IAM. - Bucket-scoped roles.
roles/storage.objectAdminis always granted on a specific bucket viagoogle_storage_bucket_iam_member, never at the project level. Adding a new bucket means adding a new binding. - The Cloud Build platform SA (
287267207777@cloudbuild.gserviceaccount.com) is grantedroles/iam.serviceAccountUseroncloudbuild-worker-sa(cloudbuild_iam.tf). That binding is what lets Cloud Build impersonate the worker SA when executing a build. 287267207777is the project number fordevelopment-485000— it appears in multiple bindings (default compute SA, Cloud Build platform SA). If you ever migrate to a new project, every binding using that literal will need to be updated.