UprootSecurityUprootSecurity

Phase 2 · GCP and Azure IAM · Lesson 1 of 3

GCP IAM: Members, Roles, and Service Accounts

Article

·

20 min

·

+10 pts

If you have been working through the AWS IAM lessons, you have internalized a specific mental model: policies attach to identities (users, roles, groups), and those identities use the policies to access resources. GCP flips this. In GCP, policies attach to resources, and those policies declare which members get which roles on that resource. The distinction sounds subtle, but it changes how you audit, how you investigate access, and how you write control narratives.

This lesson covers GCP's IAM model from the ground up: members, roles, policy bindings, the resource hierarchy, service accounts, and the organization-level controls that function as guardrails. By the end, you will understand how to evaluate a GCP environment with the same rigor you applied to AWS.

Switching between 3 cloud consoles

The GCP IAM model

GCP IAM is built on three concepts: members, roles, and policy bindings. Every access decision in GCP resolves to a binding that says "this member has this role on this resource."

Members (principals)

A member is any identity that can be granted access to a GCP resource. GCP supports five types of members:

  • Google accounts — individual users identified by a Gmail or Google Workspace email address (e.g., user:alice@company.com)
  • Service accounts — machine identities used by applications and workloads (e.g., serviceAccount:my-app@my-project.iam.gserviceaccount.com)
  • Google groups — collections of Google accounts and service accounts (e.g., group:security-team@company.com)
  • Google Workspace domains — every account in a Google Workspace domain (e.g., domain:company.com)
  • Cloud Identity domains — similar to Workspace domains but for organizations that do not use Google Workspace for email

There is also allUsers (anyone on the internet, authenticated or not) and allAuthenticatedUsers (anyone with a Google account). Both are dangerous in production and should trigger immediate findings during an audit.

Roles

Roles in GCP define a collection of permissions. There are three categories:

Primitive roles (also called basic roles) are the legacy roles: Owner, Editor, and Viewer. They grant broad permissions across all services in a project. Owner can do everything including manage IAM. Editor can modify all resources but not IAM. Viewer can read everything.

Primitive roles are almost never appropriate in production. They violate least privilege by design. If you find roles/editor assigned to a service account in a production project, that is a finding.

Predefined roles are Google-managed roles scoped to specific services. Examples: roles/storage.objectViewer (read objects in Cloud Storage), roles/bigquery.dataEditor (read and write BigQuery data), roles/compute.networkAdmin (manage networking resources). There are hundreds of predefined roles, and they are the right choice for most access grants.

Custom roles let you define a specific set of permissions when no predefined role matches your needs. They are useful for enforcing least privilege but add operational overhead — you must maintain them as new permissions are added to GCP services.

Policy bindings

Here is where GCP diverges from AWS. In GCP, you do not attach a policy to a user. You attach a policy to a resource, and that policy contains bindings that map members to roles.

A single IAM policy on a Cloud Storage bucket might say:

{
  "bindings": [
    {
      "role": "roles/storage.objectViewer",
      "members": [
        "group:data-analysts@company.com"
      ]
    },
    {
      "role": "roles/storage.admin",
      "members": [
        "user:storage-admin@company.com"
      ]
    }
  ]
}

This policy lives on the bucket, not on the users. To answer "what can Alice access?", you need to examine policies across every resource she might have bindings on — or use IAM Policy Analyzer, which GCP provides specifically because this question is harder to answer in a resource-centric model.

Key difference from AWS

In AWS, policies attach to identities. You look at a user or role and see its permissions. In GCP, policies attach to resources. You look at a resource and see who has access. Both models achieve the same goal, but the audit approach is different: in AWS, you audit from the identity outward. In GCP, you audit from the resource inward — or you use IAM Policy Analyzer to query effective access.

The resource hierarchy

GCP organizes resources in a strict hierarchy, and IAM policies inherit downward through it. Understanding this hierarchy is essential for auditing because a role granted at a higher level applies to every resource below it.

┌─────────────────────────────────────────┐
│           Organization                   │
│  (company.com)                           │
│  Policy: Security team gets              │
│  roles/iam.securityReviewer              │
│  on ALL projects and folders             │
├────────────┬────────────────────────────┤
│            │                             │
│     ┌──────▼──────┐    ┌──────────────┐ │
│     │  Folder:     │    │  Folder:      │ │
│     │  Production  │    │  Development  │ │
│     │              │    │               │ │
│     │  Policy:     │    │  Policy:      │ │
│     │  No external │    │  Wider access │ │
│     │  IP access   │    │  for devs     │ │
│     ├──────┬───────┤    ├───────┬───────┤ │
│     │      │       │    │       │       │ │
│     │  ┌───▼───┐   │    │  ┌────▼────┐ │ │
│     │  │Project │   │    │  │ Project │ │ │
│     │  │prod-app│   │    │  │ dev-app │ │ │
│     │  │        │   │    │  │         │ │ │
│     │  │ ┌────┐ │   │    │  │ ┌─────┐ │ │ │
│     │  │ │ GCS│ │   │    │  │ │ GCS │ │ │ │
│     │  │ │ VM │ │   │    │  │ │ VM  │ │ │ │
│     │  │ │ BQ │ │   │    │  │ │ BQ  │ │ │ │
│     │  │ └────┘ │   │    │  │ └─────┘ │ │ │
│     │  └────────┘   │    │  └─────────┘ │ │
│     └───────────────┘    └──────────────┘ │
└───────────────────────────────────────────┘

Inheritance: Org → Folder → Project → Resource
A role granted at the Org level applies everywhere.
A role granted at the Project level applies only
within that project.

GCP resource hierarchy — IAM policies set at any level inherit downward to all children

The hierarchy has four levels: Organization (the root, tied to your Google Workspace or Cloud Identity domain), Folders (optional groupings for departments, environments, or teams), Projects (the primary container for GCP resources — every VM, bucket, and database lives in a project), and Resources (individual services within a project).

Policy inheritance means that if you grant roles/editor at the organization level, that principal has Editor access to every project and every resource in the entire organization. This is why organization-level bindings must be audited with extreme care. A single overprivileged binding at the top cascades everywhere.

You cannot deny access by removing an inherited binding at a lower level. If someone has Owner at the organization level, you cannot remove that at the project level. GCP's IAM Deny policies (a newer feature) can block specific permissions, but the default model is additive — permissions granted at any level in the hierarchy are cumulative.

Service accounts

Service accounts are GCP's machine identity. They serve the same purpose as IAM roles in AWS: they give workloads an identity and permissions without embedding long-lived credentials in code.

Every GCP project has default service accounts (the Compute Engine default service account, the App Engine default service account), and you can create user-managed service accounts for specific workloads.

Service accounts can authenticate in two ways:

Service account keys are JSON key files that you download and use to authenticate as the service account. They are long-lived credentials that do not expire automatically. If a key file is committed to a Git repository, leaked in a log, or stored on a developer's laptop, an attacker can impersonate the service account from anywhere.

Attached service accounts (also called metadata-based identity) are the preferred method. When a VM, Cloud Function, or Cloud Run service is configured with an attached service account, the workload receives short-lived credentials automatically through the metadata server. No key files, no credential management, no rotation — the platform handles everything.

# Bad: Creating and downloading a service account key
gcloud iam service-accounts keys create key.json \
  --iam-account=my-app@my-project.iam.gserviceaccount.com

# Good: Assigning a service account to a Cloud Run service
gcloud run deploy my-app \
  --service-account=my-app@my-project.iam.gserviceaccount.com \
  --region=us-central1

Quick check

A GRC engineer reviewing a GCP project finds 14 service accounts. Nine of them have user-managed key files, some created over two years ago. What is the primary risk?

Workload Identity Federation

Workload Identity Federation is GCP's solution for cross-cloud and external identity access. Instead of creating a GCP service account key and storing it in AWS, Azure, or your CI/CD system, you configure GCP to trust tokens from an external identity provider.

The flow works like this: your AWS workload obtains an AWS STS token (which it already has if running on EC2 or Lambda), presents that token to GCP's Security Token Service, and GCP exchanges it for a short-lived access token scoped to a specific service account. No key files cross cloud boundaries. No long-lived credentials to rotate or leak.

This is the modern replacement for service account key files in cross-cloud scenarios. If a company running workloads in AWS needs to access GCP resources, Workload Identity Federation is the architecturally correct answer. If they are using downloaded service account key files stored in AWS Secrets Manager instead, that is a finding.

Workload Identity Federation supports AWS, Azure AD, any OIDC-compliant provider, and SAML 2.0 providers. It also works with GitHub Actions, GitLab CI, and other CI/CD platforms that issue OIDC tokens.

Organization Policy Service

The Organization Policy Service provides constraints that are enforced across the entire GCP organization, similar in purpose to AWS Service Control Policies (SCPs) but different in implementation. Where SCPs deny specific IAM actions, GCP Organization Policies enforce constraints on resource configuration.

Examples of organization policy constraints:

  • constraints/iam.disableServiceAccountKeyCreation — prevent anyone from creating service account keys across the entire organization
  • constraints/compute.vmExternalIpAccess — restrict which VMs can have external IP addresses
  • constraints/sql.restrictPublicIp — prevent Cloud SQL instances from having public IPs
  • constraints/iam.allowedPolicyMemberDomains — restrict IAM bindings to only members from specific domains (prevents sharing resources with external Google accounts)

These constraints operate at the resource configuration level, not the IAM action level. You cannot use organization policies to say "no one can delete Cloud Storage buckets." You use them to say "no Cloud Storage bucket can be created with public access enabled." The distinction matters for how you map controls to these guardrails.

IAM Conditions

GCP supports conditions on IAM bindings that restrict when a binding is effective. Conditions are evaluated at request time and can reference:

  • Time — grant access only during business hours or until a specific date (useful for temporary access)
  • Resource attributes — grant access only to resources with specific tags or names
  • IP address — grant access only from specific network ranges
{
  "bindings": [
    {
      "role": "roles/storage.objectViewer",
      "members": ["user:contractor@external.com"],
      "condition": {
        "title": "Temporary access until project completion",
        "expression": "request.time < timestamp('2026-07-01T00:00:00Z')"
      }
    }
  ]
}

IAM Conditions are a powerful mechanism for implementing time-bound access and just-in-time (JIT) access patterns without a third-party PAM tool. For a GRC engineer, conditions provide auditable, declarative evidence that access is scoped — the binding itself encodes the restriction.

Quick check

A company has a GCP organization with three folders: Production, Staging, and Development. A developer is granted roles/editor at the Organization level. They do not need access to Production. What is the correct assessment?

GRC Engineer's focus

When auditing a GCP environment, verify these five things: (1) No primitive roles (Owner, Editor, Viewer) assigned in production projects — use predefined or custom roles instead. (2) No service account key files — all workloads should use attached service accounts or Workload Identity Federation. (3) Organization policies enforced — at minimum, disable service account key creation and restrict external IP access. (4) Workload Identity Federation configured for any cross-cloud access — no key files crossing cloud boundaries. (5) Organization-level IAM bindings are minimal and justified — every binding at the org level cascades everywhere, so it should be limited to security reviewers and organization admins, not developers or application service accounts.

Mapping GCP concepts to what you already know

If you have completed the AWS IAM lessons, here is how the concepts translate:

AWS ConceptGCP EquivalentKey Difference
IAM UserGoogle Account (member)GCP prefers federated identity over local accounts
IAM Role (for services)Service AccountService accounts are members, not roles — they can have roles granted to them
IAM Policy (attached to identity)IAM Binding (attached to resource)GCP policies live on resources, not identities
AWS Organizations SCPOrganization Policy ConstraintSCPs deny IAM actions; GCP constraints restrict resource configuration
Permission BoundaryCustom Role + IAM ConditionsNo direct equivalent — GCP uses custom roles and conditions to scope access
Cross-account role assumptionWorkload Identity FederationGCP uses token exchange instead of role chaining
AWS Config RulesOrganization Policy ConstraintsGCP constraints are preventive (block at creation time), not detective

The biggest mental shift: in AWS, you ask "what can this identity do?" In GCP, you ask "who can access this resource?" Both questions lead to the same security outcomes, but the audit methodology differs. GCP's IAM Policy Analyzer and Asset Inventory are the tools that let you query access from the identity perspective when needed.

What to carry forward

GCP's resource-centric IAM model, strict hierarchy with downward inheritance, and organization-level constraints create a different security architecture than AWS. The principles are identical — least privilege, no long-lived credentials, guardrails at the top — but the implementation details matter when you are writing control narratives, collecting audit evidence, or investigating access.

In the next lesson, you will learn Azure's IAM model, which introduces yet another approach: a two-plane system with Entra ID for identity and Azure RBAC for resources. After that, you will map an AWS architecture to GCP and Azure equivalents, cementing your ability to work across all three clouds.

GCP IAM: Members, Roles, and Service Accounts — UprootSecurity Bootcamp