Managing Cloud IAM: Roles, Policies, and Inheritance
Managing IAM in Google Cloud means controlling who (principal) can do what (role) on which resource — expressed as role bindings inside an IAM policy attached somewhere in the organization, folder, project, resource hierarchy. Policies inherit downward and are additive: the effective access on a resource is the union of every binding above it, and a lower level can never subtract a role granted higher up. You choose between three role types — basic roles that span an entire project, predefined roles maintained by Google per service, and custom roles you assemble yourself — and the exam consistently rewards predefined roles granted to groups at the lowest level that works. This lesson walks through the policy model, viewing and editing policies with gcloud, the three role types with a comparison table, how inheritance actually plays out in scenarios, and how to define custom roles with permissions and launch stages at the project or organization level.
On this page7 sections
- The IAM policy model: principals, roles, and bindings
- Viewing and creating IAM policies with gcloud
- Basic, predefined, and custom roles compared
- Policy inheritance in the organization hierarchy
- Defining custom IAM roles
- A worked scenario: least privilege for a deployment team
- IAM concepts and role-type quick reference
- Describe the IAM policy model: principals, roles, bindings, and the resources policies attach to
- View and modify IAM policies with gcloud projects get-iam-policy and add-iam-policy-binding
- Compare basic, predefined, and custom roles and choose the right type for a scenario
- Trace how IAM policy inheritance flows down the organization, folder, project, resource hierarchy
- Define custom IAM roles with specific permissions and launch stages at the project or organization level
- Apply least-privilege patterns: groups over users, lowest effective level, predefined over basic roles
The IAM policy model: principals, roles, and bindings
Cloud IAM answers one question — who can do what on which resource — with three building blocks. A principal (also called a member) is the identity requesting access: a Google Account (user:alice@example.com), a service account (serviceAccount:app@project.iam.gserviceaccount.com), a Google group (group:devs@example.com), a whole domain (domain:example.com), or the special principals allAuthenticatedUsers and allUsers. A role is a named bundle of permissions, where each permission is a verb on a service resource such as compute.instances.start or storage.objects.get. You never grant a permission directly to a principal — permissions travel only inside roles.
A role binding ties one role to a list of principals, and an IAM policy (also called an allow policy) is the set of bindings attached to a single resource. Policies can attach at any level of the hierarchy: the organization, a folder, a project, or an individual resource that supports its own policy, such as a Cloud Storage bucket, a Pub/Sub topic, or a service account. A binding can also carry an optional IAM condition — a logical expression that limits when the grant applies, for example only until an expiry date or only to resources whose name matches a prefix.
Two consequences of this model come up constantly in questions. First, because permissions only travel inside roles, the fix for a missing single permission is finding (or building) a role that carries it — not granting the permission by itself. Second, because the policy lives on the resource rather than on the user, auditing what a person can do means examining policies across the hierarchy, which is why the effective-policy and inheritance rules in the next sections matter so much.
Viewing and creating IAM policies with gcloud
You view a project's policy with gcloud projects get-iam-policy PROJECT_ID, which prints every binding — role, principals, and any conditions — plus an etag used for optimistic concurrency when you write the policy back. The equivalent exists at each level: gcloud organizations get-iam-policy ORG_ID, gcloud resource-manager folders get-iam-policy FOLDER_ID, and per-resource commands such as gcloud storage buckets get-iam-policy gs://my-bucket. In the Console, the IAM page shows the same data with inherited grants labelled by the level they come from.
To grant a role, add a binding: gcloud projects add-iam-policy-binding PROJECT_ID --member=group:devs@example.com --role=roles/compute.instanceAdmin.v1. To revoke, use remove-iam-policy-binding with the same flags. These two commands are read-modify-write helpers — they fetch the current policy, edit one binding, and write it back — and they are the day-to-day way to manage access. For bulk changes you can dump the policy to a file, edit it, and apply the whole document with gcloud projects set-iam-policy PROJECT_ID policy.json; the etag in the file protects you from silently overwriting someone else's concurrent change.
Editing a policy is itself a privileged operation: it requires the setIamPolicy permission on that resource, carried by roles like Owner or the resource-specific admin roles. Two supporting tools are worth knowing by name: Policy Troubleshooter answers why a specific principal does or does not have a specific permission on a resource, and IAM Recommender analyzes actual permission usage and suggests replacing over-broad grants with tighter roles — Google's own tooling for enforcing least privilege over time.
Basic, predefined, and custom roles compared
The three role types differ in who defines them, how broad they are, and when you should reach for each.
| Type | Defined by | Examples | Scope of powers | When to use |
|---|---|---|---|---|
| Basic | Google (legacy, project-wide) | roles/viewer, roles/editor, roles/owner | Thousands of permissions across every service in the project | Rarely — quick experiments; they violate least privilege in production |
| Predefined | Google, per service | roles/compute.instanceAdmin.v1, roles/storage.objectViewer, roles/pubsub.publisher | A curated permission set for one job on one service, kept current by Google as services add features | The default choice for almost every grant |
| Custom | You, at project or organization level | A role holding exactly compute.instances.start and compute.instances.stop | Precisely the permissions you list — and only those | When no predefined role matches the required permission set |
The basic roles predate the modern IAM system, and their reach is wider than people expect: Editor grants modify access to nearly all services in the project, and Owner adds the ability to manage IAM itself and grant roles to others. Billing management is handled separately through billing account roles rather than by project ownership alone. Any exam option that hands a human or a service account Editor to solve a narrow task is nearly always the wrong answer when a predefined role is on the list.
Predefined roles carry a maintenance advantage custom roles never get: when a service launches new features and permissions, Google updates its predefined roles so holders keep working. A custom role is frozen at the permissions you listed — you own its upkeep forever. That trade-off is exactly how the exam frames the choice: reach for custom roles only when least privilege genuinely demands a combination no predefined role offers.
Policy inheritance in the organization hierarchy
IAM policies inherit down the resource hierarchy: a binding on the organization applies to every folder, project, and resource beneath it; a binding on a folder applies to all projects inside it; a binding on a project applies to every resource in the project. The effective policy on any resource is the union of the policy set directly on it and every policy inherited from its ancestors.
The rule with teeth is that inheritance is additive and allow-only. Standard IAM policies only ever grant — there is no subtract-a-role binding — so a lower level can never narrow what an ancestor granted. If devs@example.com holds roles/editor on the folder, granting the same group roles/viewer on one project inside it changes nothing: the group still holds Editor there through inheritance. The only fix is to remove or tighten the grant where it was made, at the folder. (Google Cloud does offer separate deny policies as an advanced guardrail mechanism, but the default IAM model the exam tests is the additive allow model — assume no denies unless a question says otherwise.)
Inheritance is also why grant placement is a design decision. Grant at the highest level whose entire subtree genuinely needs the access — an organization-wide security team might hold roles/iam.securityReviewer on the organization — and at the lowest level otherwise: a contractor auditing one bucket gets roles/storage.objectViewer on that bucket, not on the project. When a scenario asks how to give a team the same access across the twelve projects in one department, the answer is one binding on the department's folder, not twelve project-level bindings you must keep synchronized by hand.
Defining custom IAM roles
A custom role is a permission bundle you define when least privilege requires a combination no predefined role offers — for example, operators who may start and stop VMs but never create or delete them. Custom roles can be created at the project level or the organization level, and that choice matters: a project-level custom role can only be used in bindings within that project, while an organization-level role can be used in any project in the organization. Notably, custom roles cannot be created at the folder level — a recurring trick option. If several projects need the same custom role, define it once at the organization level rather than cloning it per project.
Create one with gcloud by listing permissions inline: gcloud iam roles create vmOperator --project=PROJECT_ID --title=VM-Operator --permissions=compute.instances.start,compute.instances.stop --stage=GA, or from a YAML definition file with --file. Swap --project for --organization=ORG_ID for an org-level role. Useful companions: gcloud iam list-testable-permissions RESOURCE shows which permissions can be granted on a resource type, gcloud iam roles describe roles/storage.objectViewer reveals a predefined role's exact permission list to use as a starting point, and gcloud iam roles copy clones a role you can then trim. Not every permission is supported in custom roles — some are grantable only through predefined roles — so build from the testable-permissions list rather than guessing.
Every custom role carries a launch stage — ALPHA, BETA, or GA while it is live, plus DEPRECATED and DISABLED for retirement. The stage is metadata that signals maturity to your own admins; it does not change enforcement. Lifecycle management is on you: update a role with gcloud iam roles update, mark it deprecated to warn admins off new bindings, and disable it to inactivate its bindings. Remember the standing trade-off — Google never updates your custom roles, so when a service adds new permissions your role stays frozen until you edit it.
A worked scenario: least privilege for a deployment team
Scenario: your company has an organization with a retail folder containing the projects retail-prod, retail-staging, and retail-dev. The deployment team must manage Compute Engine instances in all three projects; the data science group needs read-only access to one Cloud Storage bucket in retail-prod; and a new platform admin must be able to grant roles across the whole retail estate. How do you set this up without touching basic roles?
Work each requirement from the model. The deployment team needs the same service-specific power in every project under the folder, so bind once at the folder: gcloud resource-manager folders add-iam-policy-binding FOLDER_ID --member=group:deploy@example.com --role=roles/compute.instanceAdmin.v1. Inheritance carries it into all three projects, and any future project created in the folder is covered automatically. The data science group's need is the narrowest, so bind at the resource itself: roles/storage.objectViewer on the single bucket, not on retail-prod — a project-level grant would expose every bucket in the project. The platform admin needs to manage IAM but should not inherit Owner's full powers, so grant roles/resourcemanager.folderIamAdmin on the folder, which permits editing folder and project policies beneath it without granting resource access.
Note the habits embedded here, because the exam tests them as reflexes: every grant went to a group rather than a named user, so team changes are a group-membership edit rather than an IAM edit; every grant used a predefined role scoped to one job; and every grant landed at the lowest level that satisfies the whole requirement — folder for the folder-wide need, bucket for the bucket-wide need. If the deployment team later needed start/stop only, that is the trigger to define an organization-level custom role and swap the folder binding to it.
IAM concepts and role-type quick reference
Use this reference to compress the lesson into the facts questions actually turn on.
| Concept | What it is | Exam anchor |
|---|---|---|
| Principal | Identity being granted access: user, group, service account, domain, allAuthenticatedUsers, allUsers | Grant to groups, not individual users |
| Role | Named bundle of permissions | Permissions are never granted directly |
| Binding | One role tied to a list of principals, optionally with a condition | Conditions can time-limit or scope a grant |
| IAM (allow) policy | All bindings attached to one resource | View with get-iam-policy; edit with add-iam-policy-binding |
| Effective policy | Union of the resource's policy and all inherited ancestor policies | Additive — lower levels cannot revoke inherited grants |
| Basic roles | Owner, Editor, Viewer across the whole project | Almost always the wrong answer in production scenarios |
| Predefined roles | Google-maintained, service-specific | The default least-privilege choice |
| Custom roles | Your own permission list, project- or organization-level | No folder-level custom roles; you maintain them yourself |
| Launch stage | ALPHA, BETA, GA, DEPRECATED, DISABLED on a custom role | Metadata signal, not an enforcement change |
When you hit an IAM question, run this triage: identify the principal (prefer a group), identify the narrowest role that carries the needed permissions (predefined before custom, custom before basic), then identify the lowest attachment point whose subtree matches the requirement (resource, then project, then folder, then organization). If the question involves someone having more access than a project-level policy suggests, the answer is inheritance from a folder or organization binding. If it involves needing a role in many projects at once, the answer is a single higher-level binding — or, for a custom role, defining it at the organization level so all projects can use it.
Tip. Expect scenario questions that hinge on where a binding attaches: one folder-level grant versus many project-level grants, and why a user retains access a project admin tried to remove (inheritance is additive). Role-type discrimination is constant — spotting that Editor is over-broad, that a predefined role fits, or that only a custom role satisfies an exact permission list. Know the gcloud verbs (get-iam-policy, add-iam-policy-binding, iam roles create) and the custom-role facts: project or organization level only, launch stages, and that Google never maintains them for you.
- An IAM policy is a set of role bindings on a resource; each binding ties one role to principals, optionally with a condition
- Permissions are never granted directly — they travel only inside basic, predefined, or custom roles
- Inheritance is additive and allow-only: effective access is the union of all ancestor policies, and a lower level cannot revoke an inherited grant
- Prefer predefined roles granted to groups at the lowest hierarchy level that satisfies the requirement; avoid basic Owner/Editor/Viewer in production
- gcloud projects get-iam-policy views a policy; add-iam-policy-binding and remove-iam-policy-binding edit it; set-iam-policy replaces it wholesale
- Custom roles exist at the project or organization level only — never at the folder level — and Google does not maintain them for you
- Custom role launch stages (ALPHA, BETA, GA, DEPRECATED, DISABLED) signal maturity to admins but do not change enforcement
- Grant the same access across many projects with one folder- or organization-level binding, not per-project copies
Frequently asked questions
What is the difference between basic, predefined, and custom roles in Google Cloud?
Basic roles (Owner, Editor, Viewer) are legacy project-wide roles spanning thousands of permissions across every service, so they violate least privilege. Predefined roles are Google-maintained, service-specific bundles like roles/storage.objectViewer — the default choice, kept up to date as services evolve. Custom roles are permission lists you define at the project or organization level for cases no predefined role covers; you maintain them yourself, and they cannot be created at the folder level.
How does IAM policy inheritance work in the Google Cloud hierarchy?
Policies attached to the organization, a folder, or a project are inherited by everything beneath them, and the effective policy on a resource is the union of its own policy plus all inherited ones. Inheritance is additive and allow-only: you cannot restrict or revoke an inherited role at a lower level. A user granted Editor on a folder keeps Editor in every project inside it regardless of what those projects' own policies say.
How do I grant an IAM role with gcloud?
Use gcloud projects add-iam-policy-binding PROJECT_ID --member=group:team@example.com --role=roles/compute.instanceAdmin.v1. The member flag takes a prefixed principal (user:, group:, serviceAccount:, or domain:), and the role flag takes the full role name. Equivalent commands exist for organizations, folders, and individual resources like buckets, and remove-iam-policy-binding reverses a grant.
When should I create a custom IAM role instead of using a predefined one?
Only when least privilege requires a permission combination no predefined role offers — for example start and stop instances without create or delete. Check first with gcloud iam roles describe to inspect predefined roles, since a close match usually exists. Remember the costs: Google never updates custom roles when services add permissions, some permissions cannot be used in custom roles at all, and a project-level custom role cannot be reused in other projects — define shared roles at the organization level.
Can I make a user's access narrower in one project than what they inherit from the folder?
Not with standard IAM allow policies. Inheritance is strictly additive, so a role granted on the folder applies to every project inside it and no project-level policy can subtract from it. The fix is to move or tighten the grant at the folder level — for example, replace the folder-wide binding with bindings on only the projects that need it. Deny policies exist as a separate advanced mechanism, but the default exam assumption is the allow-only model.
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.