14.1 IAM Policies: Structure, Bindings & Policy Hierarchy

Key Takeaways

  • An IAM allow policy is a JSON/YAML object made of role bindings, each pairing principals (members) with a role and an optional CEL condition
  • Policy inheritance in the Organization → Folder → Project → resource hierarchy is strictly additive — a lower level can grant more access but can never revoke an inherited grant
  • The only way to block an inherited allow grant is an IAM Deny policy; edits at a lower-level allow policy cannot subtract ancestor access
  • Conditions on a binding require the policy's version field to be set to 3, not 1
  • The etag field enables a read-modify-write pattern that prevents two administrators from silently overwriting each other's concurrent policy edits (a mismatched etag returns HTTP 409)
Last updated: July 2026

Why IAM Policies Matter on the ACE Exam

Official Domain 5, "Configuring access and security," is only 17.5% of the exam by weight, but Identity and Access Management (IAM) concepts bleed into nearly every other domain — you cannot correctly answer a Compute Engine, Google Kubernetes Engine (GKE), or Cloud Storage question without understanding who is allowed to do what to that resource. The exam guide itself lists "Viewing and creating IAM policies" as a testable skill under this section. Expect scenario questions that describe a company's org chart and ask exactly which resource level to attach a role binding to, or a question that shows a partial policy and asks what its effective, real-world result is.

The IAM Allow Policy: Terminology

Google Cloud's access-control layer is built around the IAM allow policy (often shortened to just "IAM policy") — a JSON or YAML object attached to a specific resource. Every allow policy is a collection of role bindings. Each binding maps one or more principals (Google's current term for who is being granted access — the underlying API field is still literally named members) to exactly one role (a named bundle of permissions), and optionally attaches a condition.

FieldPurposeExample value
roleThe permission bundle being grantedroles/compute.viewer
membersPrincipals receiving the roleuser:ana@example.com, serviceAccount:sa@project.iam.gserviceaccount.com, group:devs@example.com, domain:example.com, allAuthenticatedUsers
conditionOptional Common Expression Language (CEL) expression that scopes when or where the grant appliesrequest.time < timestamp(\"2026-12-31T00:00:00Z\")

Underlying permissions always follow a service.resource.verb naming pattern — compute.instances.start, storage.objects.get, resourcemanager.projects.get — and a role is nothing more than a named list of permission strings like these. On Google Cloud you never grant a bare permission directly; you always grant a role that happens to contain it.

Policy Hierarchy and Inheritance

Google Cloud resources sit inside a strict hierarchy: Organization → Folder(s) → Project(s) → individual resources (VM instances, buckets, datasets, and so on). You can attach an allow policy at any level of that hierarchy, and IAM's policy inheritance rule states that a policy set on a container resource automatically applies to every resource nested inside it. The effective policy on any given resource is the union of the policy attached directly to that resource plus every policy attached to each of its ancestors, all the way up to the Organization node.

This produces the single most heavily tested IAM trap on the ACE exam: allow policies are strictly additive down the hierarchy. A grant made at the Organization or Folder level cannot be revoked by editing a lower-level policy — a project owner who does not want an org-level Viewer to see their project has no way to remove that inherited access using an allow policy alone. The only tools that can carve out an exception are an IAM Deny policy (which explicitly blocks specified permissions for specified principals regardless of any allow grant) or narrowing the grant itself with an IAM Condition at the point it was created.

Reading, Writing, and the etag Race Condition

Because an allow policy is a single JSON object per resource, IAM uses an optimistic-concurrency pattern to stop two administrators from clobbering each other's edits. Every policy carries an etag — a fingerprint of its current state — and the required workflow is read → modify → write:

  1. gcloud projects get-iam-policy PROJECT_ID (or the equivalent getIamPolicy API call) reads the current policy, including its etag.
  2. You add or remove bindings in the retrieved JSON locally.
  3. You call gcloud projects set-iam-policy PROJECT_ID policy.json (or setIamPolicy), submitting the same etag you just read.

If a different administrator wrote a change between steps 1 and 3, the etag you submit no longer matches the current state, and the write fails with an HTTP 409 Conflict — the client must re-read and retry rather than blindly overwrite whatever changed. For quick one-off edits, gcloud also exposes shorthand commands that internally handle this read-modify-write cycle for you: gcloud projects add-iam-policy-binding PROJECT_ID --member=user:x@example.com --role=roles/viewer and the matching remove-iam-policy-binding variant.

One more schema detail worth memorizing: allow-policy JSON carries a version field (1 or 3; 2 is reserved). Conditions require version: 3. If you add a condition to a binding but leave the policy at version 1, the condition is effectively meaningless — a classic distractor on scenario questions that show you policy JSON.

Diagnosing Access Problems

When a user reports "Permission denied," Google Cloud provides two purpose-built tools instead of manual policy archaeology:

  • Policy Troubleshooter — you supply a principal, a resource, and a permission, and it walks the entire ancestor chain to report exactly which binding (or the absence of one) produced the current outcome.
  • Policy Analyzer (part of Policy Intelligence) — answers broader audit questions like "which principals have any access to this resource" or "where does this principal have access across my whole organization," rather than diagnosing a single denied request.

Exam Scenario

A finance company structures its Google Cloud Organization with a Prod folder and a Dev folder. The security team grants roles/viewer to the entire auditors@example.com group at the Organization node so auditors can review every environment without per-project setup. Later, a Dev team lead asks to hide one sensitive Dev project from the auditors. Can this be done by editing that project's own allow policy? No — the Organization-level grant is inherited by every folder and project beneath it, and no lower-level allow-policy binding can subtract inherited access. The only correct fix is an IAM Deny policy scoped to that project (or moving the original grant so it only targets the folders that should be visible in the first place).

Key Takeaways Recap

  • An allow policy = a set of role bindings, each pairing principals + a role + an optional condition.
  • Policy inheritance is additive only — lower levels can grant more, never revoke ancestor grants.
  • Conditions need version: 3; the etag prevents concurrent-write conflicts (409).
  • Policy Troubleshooter diagnoses one denied request; Policy Analyzer audits access broadly.
Test Your Knowledge

In Google Cloud IAM, what is the correct relationship between an allow policy attached to a Folder and the allow policies attached to Projects nested inside that folder?

A
B
C
D
Test Your Knowledge

An administrator wants to stop one specific service account from deleting Compute Engine instances, even though that service account inherits the Editor basic role from an organization-level allow policy. Which mechanism accomplishes this?

A
B
C
D
Test Your Knowledge

What does the etag field in an IAM allow policy protect against?

A
B
C
D