IAM
IAM is the authorization system for everything on Google Cloud. The core model: principals (users, groups, service accounts, workload identities) get roles on resources. That binding — principal plus role plus resource — is the unit of permission. Get the bindings right and security follows naturally; get them wrong and every other security control compensates for the gap.
Two threads run through this chapter. The first is the resource hierarchy: bindings inherit from organization to folder to project to resource, and the right level of binding matters. The second is service account keys versus Workload Identity Federation — the single most common security trap on GCP and the modern pattern that eliminates it.
The IAM Model
An IAM policy is a list of bindings; each binding pairs one or more principals with one role. The role names the set of permissions. The policy attaches to a resource — a project, a bucket, a BigQuery dataset, the organization itself. When a request arrives, GCP checks every policy in scope (the resource and all its ancestors) and grants access if any binding allows it.
Principals are who. Users, groups, service accounts, and (with Workload Identity Federation) external identities. Roles are what they can do. Resources are where they can do it. The simplicity of that triple is what makes IAM tractable; the depth is in the role catalog and the hierarchy.
Resource Hierarchy and Inheritance
The org-level grant reaches every resource below it. Grant at the narrowest level that works: broad grants are easy to audit but over-privileged; resource-level grants are precise but brittle.
GCP organizes resources hierarchically: Organization → Folders → Projects → Resources. An IAM policy at any level applies to everything below it. A role granted at the organization level applies to every project; granted on a folder, it applies to every project in that folder; granted on a project, it applies to every resource in the project.
The practical rule: bind at the highest level where the binding is still correct. Patterns that should apply across the company belong at the organization or folder level — bind them once. Patterns specific to one project belong at the project level. Resource-level bindings are reserved for the rare case where one bucket or one dataset has different rules from the rest of its project.
Role Types
Three flavors of role, in decreasing order of how often each is correct:
- Predefined roles — the default. Curated by Google, named like
roles/storage.objectViewer, scoped to specific permissions on specific services. Use these wherever possible. The catalog is broad and Google maintains it. - Custom roles — when no predefined role matches and the team can commit to maintaining the role's permission list as services evolve. Useful in regulated environments where minimum permissions matter; expensive in maintenance burden everywhere else.
- Basic roles — Owner, Editor, Viewer. Legacy from before predefined roles existed. Absurdly broad. Acceptable in personal sandbox projects, never in production.
Service Accounts — Right Way and Wrong Way
A service account is an identity for a workload — a Cloud Run service, a GCE VM, a CI pipeline, a script. Service accounts can be granted IAM roles just like users. The trap is how the workload proves it is the service account.
The wrong way: generate a service account key (a JSON file with a private key), distribute it to the workload, let it authenticate by signing requests with the key. The key is a long-lived credential that gets committed to git, embedded in container images, leaked through logs, or copied into wikis. Service account keys are responsible for a disproportionate share of GCP security incidents.
The right way: attach the service account directly to the workload (GCE VM, Cloud Run service, GKE pod via Workload Identity, etc.). The platform mints short-lived tokens on demand; no key file exists. The workload authenticates by being the workload, not by holding a secret.
Workload Identity Federation
For workloads outside GCP — CI in GitHub Actions, a Lambda function on AWS, an on-prem Kubernetes cluster — there is no GCP service account to attach. Workload Identity Federation solves this. Configure GCP to trust an external IdP (GitHub's OIDC, AWS STS, an on-prem OIDC provider) for specific identities; the external workload exchanges its native token for a short-lived GCP access token. No service account key is ever created.
Service account keys — a JSON file with a private key. Long-lived, easily leaked, the most common source of GCP credential incidents. Acceptable only as a last resort when the workload genuinely cannot reach an OIDC-trustable identity.
Workload Identity Federation — the workload's native identity (GitHub Actions token, AWS STS credential, on-prem OIDC) is exchanged for a short-lived GCP token. No key file. No long-lived secret to leak. The right default for any workload outside GCP that needs GCP access.
IAM Conditions
A binding can carry a condition — a CEL expression that further restricts when the binding applies. Examples: "this role applies only to resources tagged env=prod", "this binding is active only between 09:00 and 18:00 on weekdays", "this access is granted only until 2026-12-31". Conditions are how IAM gets fine-grained without exploding into thousands of resource-specific bindings.
IAM Recommender and Policy Intelligence
IAM Recommender analyzes actual usage and suggests dropping unused permissions or replacing broad roles with narrower ones. It runs continuously and surfaces findings in the console. Most organizations have years of accumulated over-privilege; running the Recommender once and acting on the high-confidence recommendations is usually a multi-thousand-permission cleanup. Schedule a quarterly review for the rest.
- Basic roles (Owner, Editor, Viewer) in production. Predefined roles exist precisely because Basic roles are too broad.
- Service account keys stored in source control, environment variables, container images, or shared drives. Every leak path that has ever existed has been used.
- IAM bindings repeated at the project level when one folder-level binding would cover every project in the org. Drift accumulates, audit is harder.
- Long-lived service account keys for workloads outside GCP. Workload Identity Federation eliminates the key file entirely; if it can be used, it should be.
- Custom roles created where a predefined role fits. The custom role drifts as Google adds new permissions; the predefined role tracks the service automatically.
- IAM Recommender output ignored. Over-privilege accumulates indefinitely; the Recommender is one of the few free wins in security hygiene.
- Cross-project service account impersonation set up without auditing the chain. Compromised principal A can act as service account B in another project — exactly the kind of lateral movement attackers exploit.
- Predefined roles as the default. Custom roles only when no predefined role fits and the team can maintain the custom list.
- Workload Identity Federation for every workload outside GCP that needs GCP access. Service account keys only when federation is genuinely impossible.
- Bind IAM at the highest level where the binding is still correct — organization or folder for shared patterns, project for project-specific, resource for the rare exception.
- Bind to groups, never to individual users. (See Cloud Identity for the underlying reason.)
- Quarterly IAM Recommender review. Act on high-confidence recommendations as they appear.
- Time-bounded or attribute-bounded IAM Conditions for temporary or scoped access — better than removing the binding later and remembering.
- Cloud Audit Logs on IAM policy changes. Every grant and revoke is a security event worth investigating after an incident.
Knowledge Check
Which role type should be the default choice for production workloads?
- Basic roles — Owner, Editor, and Viewer — chosen for their simplicity and consistency across every project
- Predefined roles — curated by Google, scoped to specific permissions on specific services, automatically updated as those services evolve
- Custom roles — defined individually per binding to give the most fine-grained control possible over exactly which permissions are granted on each resource
- Workload Identity Federation roles — automatically inferred from the calling workload's external identity
What is the principal risk of service account keys?
- Service account keys can never be rotated once they have been created
- A key is a long-lived credential — it ends up committed to git, embedded in images, leaked through logs, and reused after the workload that needed it is gone
- Service account keys silently disable Cloud Audit Logs on every resource they are used to touch
- Service account keys are billed at a metered per-API-call rate every time they authenticate, which makes them substantially more expensive over time than the keyless alternatives
When should Workload Identity Federation be preferred over a service account key?
- Only when the workload happens to be a containerized GKE pod running inside GCP itself
- For any workload outside GCP that needs GCP access — GitHub Actions, AWS Lambda, on-prem Kubernetes — federation exchanges the workload's native identity for a short-lived GCP token, with no key file to leak
- Only when the workload is deployed and actively running across multiple separate public cloud providers at the same time, since any single-cloud external workload can still safely rely on a downloaded key file
- Workload Identity Federation is a paid Premium add-on feature, so it is never the right default to reach for
At which level of the GCP resource hierarchy should you bind IAM roles?
- Always at the individual resource level to guarantee the tightest possible scope on every grant
- Always at the top organization level so that every single policy stays centrally visible and fully auditable from one consolidated place across the entire resource hierarchy
- At the highest level where the binding is still correct — organization or folder for shared patterns, project for project-specific, resource for rare exceptions
- At the project level uniformly, since folder and organization bindings have been deprecated
What does IAM Recommender do?
- Suggests which predefined roles to apply to brand-new resources, choosing the starter role based on the resource type
- Analyzes actual usage and suggests dropping unused permissions or replacing broad roles with narrower ones — surfacing over-privilege that accumulated over time
- Generates a tailored custom role from a plain natural-language description of the permissions you need
- Recommends and automatically drafts ready-to-apply Workload Identity Federation configurations for any external workloads that happen to be running outside of GCP
You got correct