Every IAM decision answers one question:

who
can do what
on which
Principal
Role
Resource
bound together by
the glue
IAM Policy
{ bindings: [{ role, members }] }

A principal is any identity that can be authenticated. These are the “who” in IAM.

Google Account
user:alice@example.com
A real human user
Service Account
serviceAccount:api@proj.iam.gserviceaccount.com
Identity for apps/workloads — also a resource!
Google Group
group:backend-team@company.com
Bundle of users — recommended for scale
Domain
domain:company.com
Everyone in a Workspace domain
allUsers
allUsers
Anyone — including anonymous
allAuthenticatedUsers
allAuthenticatedUsers
Any logged-in Google account
Service accounts have a dual nature — they act as an identity (can call APIs), but are also a resource (you can grant others permission to impersonate them).

Roles are bundles of permissions. You never assign permissions directly — always through roles.

AVOID IN PROD Basic Roles
Owner Editor Viewer
Very broad — Editor gives write to almost everything. Violates least privilege.
RECOMMENDED Predefined Roles
roles/storage.objectViewer roles/cloudsql.client roles/container.developer
Curated by Google, scoped tightly per service. Hundreds available — use these most of the time.
WHEN NEEDED Custom Roles
Cherry-pick exact permissions you need. You define and maintain them. Use when predefined roles are too broad or too narrow.
roles contain
storage.objects.get storage.objects.list storage.buckets.get compute.instances.start ... granular permissions

IAM policies inherit downward. A role granted higher up applies to everything below it.

Organization
company.com
Policy here → applies everywhere
Folder
Engineering / Backend
Group projects by team or env
Project
acme-prod
Most common level for IAM
Resource
GKE cluster, Cloud SQL, Bucket
Most granular level
Policies are additive — you can grant more access lower in the hierarchy, but you can’t revoke what’s granted above (unless using deny policies).

Service accounts are how your applications authenticate. Here’s how credentials flow in GKE.

Your Application
GKE Pod (Go API)
runs as K8s ServiceAccount
Workload Identity maps to
GCP Service Account
my-api@proj.iam.gserviceaccount.com
No keys needed — credentials provided transparently
granted these roles
roles/cloudsql.client
Connect to Cloud SQL
roles/storage.objectViewer
Read from buckets
roles/pubsub.publisher
Publish messages
Workload Identity
No keys to manage or rotate. GCP provides short-lived tokens automatically. Recommended for GKE.
JSON Key Files
Long-lived credentials. If leaked, anyone can act as the SA. Security risk — avoid when possible.

An IAM policy is a JSON document that binds principals to roles on a resource. It’s the central artifact.

{
"bindings": [
{
"role": "roles/storage.objectViewer",
"members": [
"user:alice@example.com", ← human
"serviceAccount:api@proj.iam..." ← app
]
}, {
"role": "roles/storage.admin",
"members": [
"group:storage-admins@company.com" ← group
]
}
]
}
Additive Model
Policies can only GRANT access. No explicit deny in standard IAM.
Deny Policies
Newer feature — adds explicit deny rules. Evaluated before allow policies.

How IAM evaluates an API request — the complete flow from request to decision.

1
API Request
my-api SA calls storage.objects.get on bucket X
2
Authentication
GCP verifies the SA identity via Workload Identity token
3
Collect Policies
Gather IAM policies from: Org → Folders → Project → Bucket
4
Check Deny Policies
If any deny policy matches → DENIED (checked first)
5
Check Allow Policies
Union of all policies — does any binding grant the permission?
6
Decision
If allowed by any policy and not denied → ACCESS GRANTED

Related Topics