Skip to main content

Access Tiers and Granted Privileges

Every manifest that grants human access does it through the same three-tier permissions block. This page states exactly what each tier can and cannot do in Google Cloud.

The tiers are cumulative, and they differentiate on the data plane only — the infrastructure control plane is read-only in all three. Nobody gets to change infrastructure directly, because infrastructure is declared in manifests; a direct console change would only produce drift that the engine reconciles away on the next run.

Naming​

Three vocabularies refer to the same three tiers, so you will meet all of them:

Manifest fieldCommon nameCustom role
permissions.administratorsadmin (applicative admin)managed_admin
permissions.contributorsdevmanaged_editor
permissions.viewersreadmanaged_viewer

Declare them with OrganizationUser and OrganizationUserGroup names, never raw email addresses:

spec:
permissions:
administrators:
groups: [platform-admins]
contributors:
groups: [payments-team]
members: [alice]
viewers:
groups: [finance-readers]

The permission sets are identical in both hosting modes — Infrastream SaaS and self-hosted in your own GCP organization. There is one definition to audit and one never-grant list to enforce; the only difference is which organization defines and holds the role.

What each tier grants​

Capabilityreaddevadmin
Infrastructure control-plane read✓✓✓
Spanner / Cloud SQL / BigQuery control-plane read✓✓✓
Cloud Storage object read (get, list)✓✓✓
Spanner data read (select, read)✓✓✓
BigQuery data read (query)✓✓✓
Identity Platform user read✓✓✓
Cloud Storage object create (add only)—✓✓
Logging, mesh and edge configuration read—✓✓
Cloud Storage object overwrite and delete——✓
Spanner DML (insert / update / delete)——✓
Cloud SQL connect and IAM login——✓
BigQuery load / insert——✓
Identity Platform user create / update / delete——✓
Schema or DDL changes, anywhere———
Secret payloads, IAM policy, impersonation———

Three shapes in that table are worth explaining, because each is a deliberate decision rather than a gap.

dev's write access is append-only, and only on objects​

Cloud Storage is the one data plane where "add but do not destroy" is actually expressible: storage.objects.create without storage.objects.delete is genuinely append-only, because a GCS overwrite-in-place is a delete underneath. A dev can drop a new file and cannot replace or remove an existing one.

Spanner and BigQuery have no equivalent. spanner.databases.write is insert-update-delete indivisibly, and bigquery.tables.updateData covers WRITE_TRUNCATE as well as append. A dev database write would therefore be full CRUD, which is not "slight", so dev gets no database write — that remains a deliberate expansion decision rather than a default.

admin has authority over contents, not structure​

admin can write every row and every object, and stops at the schema line. admin cannot alter a table's shape, drop a database, or change a bucket's policy, because those are declared in manifests. That is the applicative-admin boundary: full authority over data, none over structure.

read reads application data, never credential material​

The line is not read-versus-write. It is application data versus Infrastream-managed credentials. A reader can select a Spanner row and get a Cloud Storage object — that is the tier's purpose. A reader can never reach a Secret Manager payload, a Kubernetes Secret, a KMS key, an identity-provider client secret, a VM serial port, or a service-account key.

Bulk-extraction APIs are also held above the read tier, because streaming a whole table is a different act from reading a record to verify it: Cloud SQL backup export, the BigQuery Storage Read API, and Spanner partitionQuery / partitionRead are admin-only.

What no tier can do​

These are withheld from every tier, including admin.

WithheldWhat it would otherwise expose
secretmanager.versions.accessSecret payloads
container.secrets.*Kubernetes Secrets via GKE RBAC
firebaseauth.configs.getHashConfigIdentity Platform password-hash parameters
firebaseauth.configs.getSecretUpstream identity-provider OAuth client secrets
iam.serviceAccountKeys.create / .getLong-lived service-account credentials
cloudkms.cryptoKeyVersions.useToDecryptAnything wrapped with a tenant CMEK
cloudsql.sslCerts.createA client certificate, which is a database credential
compute.instances.getSerialPortOutputVM startup secrets

Any *.setIamPolicy and any form of service-account impersonation are withheld too. Those two are what make the ladder hold: no tier can promote itself into the tier above, because no tier can edit an IAM policy or borrow another identity.

All control-plane mutation is withheld on the same grounds — it would be drift. That includes compute.*, run.* and container.* create/update/delete, Spanner updateDdl / drop, BigQuery table and dataset mutations, cloudsql.instances.update / .delete, storage.buckets.update, logging.sinks.*, serviceusage.services.enable, orgpolicy.*, and resourcemanager.projects.delete / .update / .move.

Two of those deserve a note on why they are withheld rather than merely unnecessary:

  • storage.buckets.update would let admin disable the object versioning that makes admin's own object deletes recoverable.
  • logging.sinks.* and logging.logs.delete would let a tier that can write data destroy the audit trail recording that it did.

How grants are resolved​

Highest tier wins. If a principal appears in more than one tier — directly in viewers and via a group in administrators, say — they receive the widest tier's role once, not one binding per tier.

Grants are per project. A tier binding is applied at the project level, not on the tenant folder, so it does not inherit across your whole tenant tree. The folder carries only roles/resourcemanager.folderViewer, enough to navigate the hierarchy.

A tier with no configured role grants nothing. If the role backing a tier is not configured, those principals are skipped rather than falling through to a wider tier. They keep folder navigation and get no project-level access.

Two boundaries this model does not cover​

The tier ladder governs Google Cloud IAM. Two authorization systems sit beyond its edge, and access there is decided by their own rules:

  • Kubernetes RBAC. container.clusters.connect is held at dev and above. It opens a session against the cluster's API server, and what that session may do is decided by RBAC bindings that this IAM model neither describes nor controls. No tier holds container.secrets.* or container.pods.exec on the GCP side.
  • PostgreSQL roles. admin's Cloud SQL connect permission gets you a connection. What you can do once connected is governed by database roles and grants, which are declared separately — see Database.