Google Cloud IAM Basics: Principals, Roles, and Permissions
Google Cloud IAM rests on three core ideas: principals, roles, and permissions, joined together by policy bindings on a resource hierarchy. Learn how they interact.
Google Cloud IAM Basics: Principals, Roles, and Permissions
Overview
Google Cloud IAM authorizes API calls based on three core concepts joined by policy bindings attached to a resource hierarchy:
- Principals — who is making the request.
- Permissions — what atomic action is requested.
- Roles — named collections of permissions assignable to principals.
A policy binding says "this principal has this role on this resource (optionally under this condition)." Policies inherit down the hierarchy.
1. Principals
Types
- Google Account:
user:[email protected] - Google Group:
group:[email protected] - Service Account:
serviceAccount:[email protected] - Cloud Identity / Workspace Domain:
domain:example.com - Workforce / Workload Identity Pool members: federated identities.
allAuthenticatedUsers— any authenticated Google account.allUsers— public.
Best Practices
- Prefer groups over individual users for role assignment.
- Tag service accounts with owner/purpose.
- Eliminate
allUsers/allAuthenticatedUsersoutside intentional public surfaces.
2. Permissions
Format
service.resource.verb
Examples:
storage.objects.getcompute.instances.startiam.serviceAccounts.actAsbigquery.datasets.create
There are thousands of permissions across Google Cloud services.
Granularity
Permissions are atomic — a single permission usually corresponds to a single API method. This enables fine-grained control.
3. Roles
Roles bundle permissions for assignment.
Three Types
- Basic roles (legacy):
roles/owner,roles/editor,roles/viewer. Each has thousands of permissions across services. Strongly discouraged in production. - Predefined roles: maintained by Google per service (e.g.,
roles/storage.objectViewer,roles/compute.instanceAdmin). Recommended starting point. - Custom roles: org or project-scoped, with selected permissions. Use when no predefined fits.
Examples
roles/storage.objectAdmin— full control of GCS objects.roles/bigquery.dataViewer— read BigQuery tables.roles/iam.serviceAccountUser— use service accounts for resources.roles/iam.serviceAccountTokenCreator— impersonate service accounts.
4. Policy Bindings
Bindings attach roles to principals on resources:
bindings:
- role: roles/storage.objectViewer
members:
- user:[email protected]
- group:[email protected]
- role: roles/storage.objectAdmin
members:
- serviceAccount:[email protected]
condition:
title: "Working hours only"
expression: 'request.time.getHours("UTC") >= 9 && request.time.getHours("UTC") <= 18'
Where Bindings Live
- Organization node.
- Folder node.
- Project node.
- Resource (some services support resource-level bindings).
Inheritance
Bindings on parent nodes apply to all descendants.
5. Resource Hierarchy
Organization
├── Folder: Workloads
│ ├── Folder: Production
│ │ ├── Project: prod-app-001
│ │ │ ├── GCS Bucket
│ │ │ ├── BigQuery Dataset
│ │ │ └── Compute Engine VM
│ │ └── Project: prod-app-002
│ └── Folder: Non-Production
└── Folder: Shared Services
Bindings at Organization level affect everything below; folder-level bindings affect all projects in that folder; etc.
6. Conditions
IAM Conditions narrow when a binding applies based on:
- Time (
request.timeoperations). - Resource (resource type, name, tag).
- Request attributes (caller IP, etc.).
Useful for time-bound access (just-in-time), tag-based ABAC, etc.
7. Deny Policies
A newer feature where you can explicitly deny specific principals from specific permissions across an organization or folder. Deny always wins over Allow. Useful for org-wide guardrails (e.g., deny iam.roles.create for non-admin teams).
Putting It All Together
Example 1: Read-Only Auditor
Binding at Organization: roles/viewer to group:[email protected] with condition restricting to certain folders.
Example 2: ETL Service Account
Service account etl-sa has roles/storage.objectViewer on source bucket and roles/bigquery.dataEditor on destination dataset.
Example 3: Just-In-Time Admin
User has roles/compute.admin on production project but with condition request.time < expiration_time set per-request via approval workflow.
Common Mistakes
- Basic roles in production (Owner / Editor / Viewer at project or org).
- Bindings at Organization level for resource-specific access.
allUsersbinding for "demos" never removed.- Service Account Token Creator assigned broadly.
- Default Compute Service Account with Editor retained.
- Service account keys generated and forgotten.
- Custom roles bloated like basic roles.
- No use of folders — flat structure.
Best Practices
- Use predefined roles by default; custom when needed.
- Avoid basic roles.
- Bindings at the smallest necessary scope (resource > project > folder > org).
- Use groups for principal assignment, not individuals.
- Use conditions for context restriction.
- Use Deny policies for org-wide guardrails.
- Workload Identity Federation instead of service account keys.
- Service account impersonation instead of key distribution.
- IAM Recommender for least-privilege suggestions.
- Cloud Audit Logs for IAM events; centralized.
Checklist
- No basic roles in production?
- Bindings scoped tightly (resource/project/folder)?
- Group-based assignment dominant?
- No
allUsers/allAuthenticatedUsersunless intentional? - Default service accounts tamed?
- Workload Identity Federation in CI/CD and on-premises?
- Conditions used for context?
- Deny policies for org guardrails?
- IAM Recommender findings actioned?
- Audit logs centralized?
How Forestall Helps
Forestall analyzes principals, roles, permissions, and bindings across your hierarchy:
- Effective permissions per principal.
- Over-permissioning detection (compared to usage).
- Privilege escalation chains via service account impersonation.
- Public exposure findings.
- Recommendations ranked by impact.
Frequently Asked Questions
Why avoid basic roles?
They include thousands of permissions across services — far broader than any specific job needs.
Can I deny via IAM?
Yes — Deny policies (separate from Allow policies). Deny wins.
Should bindings live on the resource or the project?
As specific as possible. Resource-level if supported; otherwise project; only org/folder if truly needed.
Are custom roles always best?
No — predefined are maintained by Google and cover most needs. Use custom only when no predefined fits.
What's the relationship between IAM and Org Policies?
IAM controls who can do what. Org Policies (separate service) restrict what configurations and resources are allowed (e.g., "no public IPs"). Different layers.
Conclusion
Principals, roles, permissions, and policy bindings are the four foundational concepts of Google Cloud IAM. Combined carefully — least privilege at the smallest scope, group-based principals, no basic roles, conditions for context, federation in lieu of keys — they provide a powerful, hierarchical access control model. Misused, they create the silent over-permissioning paths attackers exploit. Use predefined / custom roles, scoped bindings, and continuous review to keep IAM tight as your GCP estate scales.
Bring least privilege to your Google Cloud projects.
Forestall maps principals, roles, and bindings across your GCP estate to surface over-permissioning.