In Cloud IAM, access control is expressed as an explicit rule: WHO (Identity) can do WHAT (Roles) on WHICH (Resource).
Understanding how GCP structures Cloud IAM roles and non-human Service Accounts is critical to preventing credential leaks and privilege escalation.
Topic 1: The Anatomy of an IAM Policy Binding
An IAM Policy is a collection of bindings. Each binding maps one or more Principals (Members) to exactly one Role:
- Principals (Members):
- Google Account: An individual user email (
dev@company.com). - Service Account: A special non-human account used by applications or GCE VMs (
sa-payment@project.iam.gserviceaccount.com). - Google Group: A managed group of Google accounts (
devs@company.com). Best Practice: Assign roles to Groups rather than individual emails! - Domain / Cloud Identity: All accounts in a Google Workspace domain.
- Special Identifiers:
allAuthenticatedUsers(anyone with a valid Google account worldwide) andallUsers(public internet access).
- Google Account: An individual user email (
Topic 2: Primitive vs. Predefined vs. Custom Roles
GCP categorizes roles into three distinct tiers:
| Role Category | Scope | Examples | Production Recommendation |
|---|---|---|---|
| Primitive Roles | Project-wide | roles/viewer, roles/editor, roles/owner | NEVER in production — editor contains thousands of permissions across all GCP products |
| Predefined Roles | Fine-grained per service | roles/storage.objectAdmin, roles/pubsub.publisher | PREFERRED — Maintained by Google, follows least privilege per service |
| Custom Roles | User-defined permissions | Custom array of gcp.service.verb permissions | Use when predefined roles are still too permissive for compliance |
# Bad Practice: Granting primitive Editor role
gcloud projects add-iam-policy-binding my-project-id \
--member="user:engineer@company.com" \
--role="roles/editor" # DO NOT DO THIS IN PROD!
# Good Practice: Granting a Predefined Least-Privilege Role
gcloud projects add-iam-policy-binding my-project-id \
--member="group:backend-team@company.com" \
--role="roles/storage.objectViewer"
Topic 3: Service Accounts & The Trap of Default Service Accounts
Service accounts represent non-human workloads (applications, GCE VMs, GKE pods, Cloud Functions).
The Default Service Account Trap:
When you enable the Compute Engine API in a new project, GCP automatically creates the Compute Engine Default Service Account (PROJECT_NUMBER-compute@developer.gserviceaccount.com) and automatically grants it the primitive roles/editor role!
If an attacker compromises a GCE VM running with this default service account, they gain full Editor rights across your entire GCP project.
Remediation Steps:
- Disable automatic default service account role grants at the Organization level (
iam.automaticIamGrantsForDefaultServiceAccounts). - Create dedicated, workload-specific service accounts for every service.
- Grant only the exact predefined roles required by that specific service.
Topic 4: Key Security: Service Account Impersonation vs. Key Files
Historically, developers downloaded .json private key files to authenticate local code or CI/CD pipelines. These keys are a major security vulnerability: they do not expire automatically and frequently leak in git repositories.
Modern Security Standard: Service Account Impersonation: Instead of creating static key files, authorized users or CI/CD workers trade their identity for a short-lived OAuth2 access token (valid for 1 hour) by impersonating the target service account:
# Grant an engineer permission to impersonate a service account
gcloud iam service-accounts add-iam-policy-binding \
sa-deployment@my-project-id.iam.gserviceaccount.com \
--member="user:lead-dev@company.com" \
--role="roles/iam.serviceAccountTokenCreator"
# Local CLI or CI script uses short-lived impersonation token (NO JSON KEY NEEDED)
gcloud auth print-access-token \
--impersonate-service-account=sa-deployment@my-project-id.iam.gserviceaccount.com
Common mistake: Downloading a service-account key because impersonation looked like extra work. The key never expires, is copied into a laptop and a CI variable, and appears in the audit log as the service account rather than as the person using it. Impersonation and Workload Identity Federation give you short-lived credentials and a real caller identity — and there is almost always a path to one of them.