Cloud Security 12 min read

    GCP IAM and Workload Identity: A Practical Guide for Modern Workloads

    GCP's IAM model is genuinely different from AWS and Azure. A grounded guide to organization policies, predefined vs. custom roles, and why Workload Identity Federation should be your default for everything outside Google Cloud.

    GCP IAM and Workload Identity: A Practical Guide for Modern Workloads

    How GCP IAM Is Different

    If you've come from AWS, GCP's IAM model has a few specific traps:

    • Roles bind to principals, not to resources. You can't write a resource policy on a Cloud Storage bucket the way you'd write an S3 bucket policy. Permissions live at project / folder / org levels.
    • Predefined roles are huge. roles/editor grants thousands of permissions across hundreds of services. It's almost never what you actually want.
    • Service accounts are first-class identities — and historically, their keys were the most-leaked GCP credential type.

    Doing Least Privilege Without Pain

    The right tooling makes least privilege achievable:

    • IAM Recommender — surfaces unused permissions and suggests narrower roles based on observed usage. Run it monthly.
    • Custom roles — only when no predefined role fits. Predefined roles are maintained by Google as services evolve; custom roles aren't.
    • Conditional IAM — bind roles only when conditions match (e.g. specific resource names, request times, or attribute tags).
    • VPC Service Controls — service-perimeter boundaries that block data exfiltration even if IAM is misconfigured. Worth the configuration effort for sensitive datasets.

    Workload Identity Federation: Stop Issuing Static Keys

    The single highest-impact security improvement in any GCP environment is retiring service account JSON keys. They're long-lived, easy to leak, and the most common compromised-credential type for GCP.

    The replacement is Workload Identity Federation — short-lived OIDC tokens minted on demand:

    • From AWS, Azure, on-prem — the workload's existing identity (IAM role, managed identity, OIDC token) is exchanged for a Google access token.
    • From GitHub Actions — GitHub's OIDC token authenticates to GCP. No GOOGLE_APPLICATION_CREDENTIALS in repository secrets.
    • From Kubernetes — Workload Identity for GKE binds K8s service accounts to GCP service accounts.

    Organization Policies for Defense-in-Depth

    Organization Policy Service applies guardrails at the org / folder / project level that supersede IAM. The high-impact ones:

    • iam.disableServiceAccountKeyCreation — make it physically impossible to create JSON keys in your org.
    • compute.requireOsLogin — central SSH/identity for VMs.
    • storage.publicAccessPrevention — the GCP equivalent of S3 Block Public Access.
    • iam.allowedPolicyMemberDomains — restrict IAM bindings to your own org domain only (no @gmail.com grants).
    • compute.disableSerialPortAccess and compute.skipDefaultNetworkCreation.

    Logging and Detection That Pays Off

    GCP's audit logging is granular and free for Admin Activity logs. Specific high-value detections:

    • Service account key creation events (after the org policy above, these should be zero — alert on any).
    • setIamPolicy events at project/folder/org level.
    • Failed and successful authentication for service accounts impersonated across boundaries.
    • Any change to organization policies themselves.

    Pipe everything into a single security project's BigQuery dataset (or Chronicle / Splunk / Sentinel — whatever your SOC actually uses) and write detections there.