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 │
└───────────────────┘ └────────────────────┘
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"
Publicly readable storage bucket:
gsutil mb -l asia-southeast1 gs://<PROJECT_ID>-sloppy-bucket
gsutil iam ch allUsers:objectViewer gs://<PROJECT_ID>-sloppy-bucket
Exported service account key:
gcloud iam service-accounts keys create sloppy-key.json \
--iam-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com
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
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"
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"
Identify exported credentials:
gcloud iam service-accounts keys list \
--iam-account=sloppy-sa@<PROJECT_ID>.iam.gserviceaccount.com
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
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
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)