What is IAM Policy Binding in Google Cloud?
An IAM policy binding in Google Cloud links a principal to a role on a resource (optionally with a condition). Learn how bindings drive every IAM decision.
What is IAM Policy Binding in Google Cloud?
Definition
An IAM policy binding in Google Cloud is the fundamental unit of access grant: it links a role to one or more principals on a specific resource node (organization, folder, project, or supported resource), optionally restricted by an IAM condition.
A policy is a collection of bindings attached to a resource node.
In simple terms:
A binding says "these principals have this role here, optionally only when this condition is true." Stack many bindings together and you have an IAM policy.
Why Bindings Matter
- They are the unit of access in Google Cloud IAM.
- Every IAM decision aggregates the bindings relevant to the resource (own + ancestors).
- Misconfigured bindings (broad principals, broad roles, no conditions) drive most GCP exposure.
Anatomy
bindings:
- role: roles/storage.objectViewer
members:
- user:[email protected]
- group:[email protected]
- role: roles/storage.objectAdmin
members:
- serviceAccount:[email protected]
condition:
title: "Production hours only"
description: "Restrict to 08:00-20:00 UTC weekdays"
expression: |
request.time.getHours("UTC") >= 8 &&
request.time.getHours("UTC") < 20 &&
request.time.getDayOfWeek("UTC") >= 1 &&
request.time.getDayOfWeek("UTC") <= 5
Required Fields
- role — the role being granted.
- members — principals (one or more).
Optional Fields
- condition — Common Expression Language (CEL) expression.
Where Bindings Live
- Organization node.
- Folder node.
- Project node.
- Resource node (some services, e.g., GCS bucket, BigQuery dataset, Cloud Storage object, Pub/Sub topic).
A request's effective permissions are the union of bindings on the resource and all its ancestors.
Conditions: Context-Based Bindings
CEL expressions can reference:
request.time— request time.resource.name,resource.type,resource.service— the target resource.request.auth— request authentication info.
Common Condition Patterns
- Time-bound (JIT):
request.time < timestamp("2026-06-01T00:00:00Z") - Resource tag:
resource.matchTag("123/env", "prod") - IP restriction: at the perimeter (VPC Service Controls / Access Context Manager) — IAM Conditions don't directly support IP.
- Resource name pattern:
resource.name.startsWith("projects/_/buckets/public-")
Deny Policies
Beyond Allow bindings, Google Cloud offers Deny policies at Organization, Folder, or Project level. They explicitly deny specific principals from specific permissions, regardless of allow bindings.
denyRules:
- deniedPrincipals:
- principalSet://goog/public:all
deniedPermissions:
- iam.googleapis.com/roles.create
Deny always wins. Use for org-wide guardrails.
Inheritance and Aggregation
For a request on projects/myproj/buckets/mybucket/objects/myobj:
- Aggregate bindings on Organization.
- Aggregate bindings on the Folder containing the project.
- Aggregate bindings on the project.
- Aggregate bindings on the bucket.
- Aggregate bindings on the object (rare).
- Apply Deny policies (which override).
- Determine if the requested permission is granted.
Common Binding Mistakes
Owner/Editorat Organization level — full reach.allUsers/allAuthenticatedUsersin any binding outside intentional public.domain:example.comfor resource access — extremely broad.- Ad-hoc user bindings (instead of group) — drift over time.
- Bindings at Org level for project-specific roles.
- No conditions for time-bound or context-sensitive grants.
- Stale bindings for departed users / removed teams / decommissioned vendors.
- Bindings via service accounts in unmanaged ways (cross-project sprawl).
Real-World Examples
1. Org-Level Editor
A new SRE got Editor at Organization "for setup speed." Compromise of their account = full org modify capability.
2. Public Pub/Sub Topic
A binding roles/pubsub.subscriber to allAuthenticatedUsers on a topic carrying internal events. Any Google account could subscribe.
3. Time-Bound Admin
JIT admin pattern: bindings created with condition request.time < expiration, automatically expiring. Reduces standing admin count.
4. Conditional Bucket Access
roles/storage.objectAdmin with condition resource.name.startsWith("projects/_/buckets/data-"). Principal admin only on data- buckets.
Best Practices
- Bindings at smallest scope (resource > project > folder > org).
- Group-based members for lifecycle hygiene.
- No
allUsers/allAuthenticatedUsersoutside intentional public. - No domain-wide bindings outside high-trust scenarios.
- Predefined / custom roles, never basic in production.
- Conditions for time-bound and context-sensitive access.
- Deny policies for org-wide guardrails.
- Audit log alerts on binding changes.
- Quarterly review of bindings (especially privileged).
- IAM Recommender for over-permissioning suggestions.
- Manage as IaC (Terraform); peer review.
Checklist
- No
Owner/Editorat Org level (outside emergency)? - No
allUsers/allAuthenticatedUsers(outside intentional)? - Group-based members?
- Predefined / custom roles only?
- Conditions used for context-sensitive grants?
- Deny policies in place for org guardrails?
- Bindings in Terraform / IaC?
- Quarterly binding review?
- Audit log alerts on binding changes?
How Forestall Helps
Forestall analyzes every binding across your GCP hierarchy:
- Effective permissions per principal.
- Risky binding detection (public, domain-wide, basic roles, broad scope).
- Over-permissioning relative to usage.
- Privilege escalation paths created by binding combinations.
- Recommendations for least-privilege replacement.
Frequently Asked Questions
Can a binding have multiple roles?
No — one role per binding entry. But multiple bindings can exist in the same policy.
Can multiple bindings include the same principal?
Yes — all are aggregated on evaluation.
Are conditions supported on all roles?
Most predefined roles support conditions; some legacy or service-specific bindings have limitations. Check role docs.
What happens if a principal is in both Allow and Deny?
Deny wins.
Can I bind a role to a service account in another project?
Yes — service accounts are valid principals across projects.
Conclusion
IAM policy bindings are the unit of access in Google Cloud IAM. Get them right — small scopes, group-based members, predefined / custom roles, conditions for context, no public exposure — and your IAM stays tight. Get them wrong and a single broad binding can expose vast surfaces. Manage them as code, review them quarterly, and use Forestall (or similar tooling) to catch the risky combinations as they emerge.
Audit every IAM policy binding across your GCP hierarchy.
Forestall surfaces risky bindings and over-permissioned principals across all your projects.