Google Cloud Platform How To Use

Google Cloud Platform How To Use

Reading time1 min
#Cloud#Security#Technology#GCP#IAM#GoogleCloud

Mastering Google Cloud Platform IAM: Secure Access with Least Privilege

Default IAM roles in GCP are a double-edged sword. They unlock velocity but nearly guarantee overprivilege. To actually secure production workloads, custom roles aligned to least privilege are indispensable—especially as audit and compliance requirements tighten.


Defining Least Privilege—Why “Editor” Is a Trap

Primitive roles (Owner, Editor, Viewer) are legacy holdovers. Assigning Editor to a team member is equivalent to handing out a wildcard—not just for the resources they own, but the entire project boundary. Expect auditors to highlight this as an immediate remediation item.

Instead, least privilege means paring permissions down to a precise set. Every additional permission compounds risk and broadens your blast radius. Consider a real incident—a junior developer with Editor role inadvertently deleted critical GCS buckets during a weekend migration. SLOs missed, incident review painful. That’s what over-entitlement looks like in practice.

Table: IAM Role Granularity in GCP

Role TypeExampleScopeUse in Production?
Primitiveroles/editorBroadNever
Predefined (Broad)roles/storage.adminStill broadOnly if strictly required
Predefined (Fine)roles/cloudfunctions.invokerNarrowYes, if fits exactly
CustomUser-definedExactYes—best for least privilege

Step 1: Define Task Boundaries

Jump to specifics: List actual work tasks for each persona.

  • DevOps engineer: Deploy new Cloud Functions; must not alter billing or IAM.
  • Data engineer: Read/write to specific BigQuery datasets, not create storage buckets.

Missed a task? Permissions gap. Over-included a resource? Overprivilege.

Example: Deploy rights for Cloud Functions, but not GKE, nor full access to Cloud Storage.


Step 2: Map Tasks to Permissions

GCP’s IAM permissions are atomic (e.g., compute.instances.get, cloudfunctions.functions.create). Aggregate them via docs or tooling:

# See permissions in a predefined role
gcloud iam roles describe roles/cloudfunctions.developer --project=my-project

Checklist when building permissions:

  • Start with the lowest possible predefined role.
  • Remove permissions not tied to actual use cases.
  • For code deployments, always check if iam.serviceAccounts.actAs is required (many GCP build pipelines fail without it).

Step 3: Build and Apply Custom Roles

You can use the GCP Console GUI, but for durability and automation, define roles as YAML. Note: custom roles are project-scoped by default. Moving them to organization-level later is a migration.

custom-role.yaml:

title: "Cloud Functions CI Deploy"
description: "CI pipeline deployment permissions for Cloud Functions only"
stage: "GA"
includedPermissions:
  - cloudfunctions.functions.create
  - cloudfunctions.functions.update
  - cloudfunctions.functions.get
  - cloudfunctions.functions.list
  - iam.serviceAccounts.actAs

Creation (tested with gcloud 448.0.0+):

gcloud iam roles create cloudFunctionsCiDeploy \
  --project=my-project-id \
  --file=custom-role.yaml

Known issue: API propagation can take up to 60 seconds after role creation before assignment is permitted. Don’t script retries too aggressively, or you’ll hit rate limits.


Step 4: Bind the Custom Role

Target lowest possible resource boundary. For CI/CD, bind at project unless you’re using folder-level delegation.

gcloud projects add-iam-policy-binding my-project-id \
  --member="serviceAccount:ci-bot@my-project-id.iam.gserviceaccount.com" \
  --role="projects/my-project-id/roles/cloudFunctionsCiDeploy"

Note: If you see PERMISSION_DENIED: The caller does not have permission, check Org Policy for role creation restrictions or ask for project owner rights temporarily.


Step 5: Add Conditional IAM (Optional but Powerful)

GCP IAM conditions refine privileges further. Example: restrict access to business hours only.

gcloud projects add-iam-policy-binding my-project-id \
  --member="user:dev@example.com" \
  --role="roles/cloudfunctions.developer" \
  --condition='expression=request.time.getHours() >= 8 && request.time.getHours() < 18,
    title=LimitingToBusinessHours,
    description=Allow deploys during office time only'

Side effect: API-driven deployments from CI outside allowed hours will fail with HTTP 403.

Tip: Conditions can check network tags or IPs but avoid overcomplicating. Complex policies often cause troubleshooting headaches (“Why is prod-deploy failing only on Fridays?”).


Step 6: Audit and Iterate—Don’t Set and Forget

  • Cloud Asset Inventory: Enumerate current bindings.
  • Cloud Audit Logs: Track failed permission attempts (PERMISSION_DENIED events), which reveal gaps or excesses.
  • Policy Troubleshooter: Confirm not just what should work, but what actually does.

Perform quarterly reviews. Remove roles or bindings unused for >90 days. The more friction, the faster out-of-date roles surface.

Sample audit log:

{
  "protoPayload": {
    "status": {"code": 7, "message": "PERMISSION_DENIED"},
    "authenticationInfo": {"principalEmail": "ci-bot@my-project-id.iam.gserviceaccount.com"},
    "serviceName": "cloudfunctions.googleapis.com"
  },
  "timestamp": "2024-06-12T10:04:21.777Z"
}

Non-Obvious Tips & Trade-Offs

  • Groups > Users. Assign roles to Google Groups, not individuals. Much easier onboarding/offboarding, especially for rotating engineers.
  • Infrastructure as Code. Control IAM through Terraform or Deployment Manager, not manual clicks. terraform plan surfaces drift quickly.
  • Service Account Keys. Disable where possible; use Workload Identity Federation or short-lived access tokens instead. Leaked keys are a recurring incident cause (see Google’s own incident postmortems).
  • Don’t Assume Logging Is Complete. Some GCP actions aren’t logged by default (e.g., GCS object reads). Explicitly enable Data Access logs for high-sensitivity projects.
  • Test in a Sandbox. Many permission errors only reveal themselves in real workflows. Spin up a temporary project, assign only the custom role, and try real pipelines first.

Bottom Line

Custom IAM roles require up-front effort but are the only viable path for regulated, secure workloads on GCP. Audit your current policy bindings. Shrink down every permission by starting from zero—not from Editor. Where precision is impossible, document the compromise.

If you hit edge cases (e.g., third-party tools demanding broader permissions than needed), flag and revisit after deployment. Not all IAM design ends perfect—just keep the blast radius as small as reality allows.


Stuck on an esoteric IAM binding or conditional? Post your scenario below. The nuances add up fast, but most problems are repeatable—and solvable.