DEV Community

iapilgrim
iapilgrim

Posted on

GCP The Hard Way — Part 3: Auditing IAM Misconfigurations Before They Become Incidents

Introduction

IAM misconfigurations rarely announce themselves. An over-permissioned
service account or a publicly readable storage bucket typically
continues functioning without error, which is precisely what makes
these issues dangerous — they persist silently until discovered by an
audit, or by an attacker. This post walks through introducing three
realistic IAM misconfigurations into a test project, then performing a
structured security review to identify and remediate them using native
GCP tooling.

Solution overview

We separate this exercise into two distinct phases to preserve the
integrity of the audit: a configuration phase where common
misconfigurations are introduced, and a review phase performed without
reference to the configuration phase, using only Cloud IAM and Cloud
Asset Inventory tooling.

┌───────────────────┐        ┌────────────────────┐
│  Configuration      │        │      Review          │
│  Phase               │──────▶│      Phase            │
│                      │ 15-30 │                      │
│  - Broad IAM role    │  min  │  - IAM policy audit   │
│  - Public bucket     │ gap   │  - Asset Inventory    │
│  - Exported SA key   │       │  - Key rotation       │
└───────────────────┘        └────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Prerequisites

  • A dedicated test project (do not perform this exercise against production infrastructure)
  • The Cloud Asset API enabled: gcloud services enable cloudasset.googleapis.com

Walkthrough

Phase 1: Introduce common misconfigurations

Overly permissive service account role:

gcloud iam service-accounts create sloppy-sa \
  --display-name="Sloppy Dev SA"

gcloud projects add-iam-policy-binding <PROJECT_ID> \
  --member="serviceAccount:sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com" \
  --role="roles/editor"
Enter fullscreen mode Exit fullscreen mode

Publicly readable storage bucket:

gsutil mb -l asia-southeast1 gs://<PROJECT_ID>-sloppy-bucket
gsutil iam ch allUsers:objectViewer gs://<PROJECT_ID>-sloppy-bucket
Enter fullscreen mode Exit fullscreen mode

Exported service account key:

gcloud iam service-accounts keys create sloppy-key.json \
  --iam-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com
Enter fullscreen mode Exit fullscreen mode

Deploy a minimal Cloud Run service using this service account to
simulate a realistic dependency:

gcloud run deploy sloppy-service \
  --image=gcr.io/cloudrun/hello \
  --service-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com \
  --region=asia-southeast1 --allow-unauthenticated
Enter fullscreen mode Exit fullscreen mode

Phase 2: Perform the security review

Identify over-permissioned identities:

gcloud projects get-iam-policy <PROJECT_ID> --format=json

gcloud asset search-all-iam-policies \
  --scope=projects/<PROJECT_ID> \
  --query="policy:roles/editor"
Enter fullscreen mode Exit fullscreen mode

Any service account bound to roles/editor or roles/owner warrants
scrutiny — these broad roles are rarely required for a well-scoped
workload identity.

Identify publicly accessible storage:

gsutil iam get gs://<PROJECT_ID>-sloppy-bucket

gcloud asset search-all-iam-policies \
  --scope=projects/<PROJECT_ID> \
  --query="policy:allUsers"
Enter fullscreen mode Exit fullscreen mode

Identify exported credentials:

gcloud iam service-accounts keys list \
  --iam-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com
Enter fullscreen mode Exit fullscreen mode

Phase 3: Remediate

gcloud projects remove-iam-policy-binding <PROJECT_ID> \
  --member="serviceAccount:sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com" \
  --role="roles/editor"

gcloud projects add-iam-policy-binding <PROJECT_ID> \
  --member="serviceAccount:sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"

gsutil iam ch -d allUsers:objectViewer gs://<PROJECT_ID>-sloppy-bucket

gcloud iam service-accounts keys delete <KEY_ID> \
  --iam-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com
Enter fullscreen mode Exit fullscreen mode

Redeploy or invoke the Cloud Run service to confirm it continues to
function correctly under the narrower storage.objectViewer role.

Design consideration: most GCP-managed compute services (Cloud
Run, GKE, Compute Engine) can use a service account's identity
directly without an exported JSON key. Keys should generally only be
created for workloads running outside Google Cloud — unnecessary key
exports are a frequent root cause of credential leakage incidents.

Clean up resources

gcloud run services delete sloppy-service --region=asia-southeast1 --quiet
gsutil rm -r gs://<PROJECT_ID>-sloppy-bucket
gcloud iam service-accounts delete \
  sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com --quiet
Enter fullscreen mode Exit fullscreen mode

Conclusion

This exercise illustrates why IAM review needs to be a routine,
tool-assisted process rather than a one-time configuration step.
gcloud asset search-all-iam-policies in particular scales to
project- and organization-wide queries that manual policy inspection
cannot practically match.

In Part 4, we turn to data modeling — deliberately selecting the
wrong database for a workload, and migrating once the cost and
performance implications become apparent.

Top comments (0)