Least-Privilege GCP IAM With AI: Roles, Conditions, and Service Accounts
GCP IAM is a sprawl of predefined roles and primitive grants that nobody fully reads. Here's how I use AI to draft tight custom roles, IAM conditions, and service accounts.
- #gcp
- #ai
- #iam
- #least-privilege
- #security
I inherited a GCP project where a single service account had roles/editor and was attached to every Compute Engine instance, every Cloud Function, and the CI deploy pipeline. One leaked key would have been a full-project breach. The person who set it up was long gone, and nobody could tell me what permissions the workloads actually needed. That’s the IAM trap on Google Cloud: the easy path is a primitive role like Editor or Owner, and the correct path — a custom role scoped to exactly the permissions in use — requires reading through thousands of permission strings nobody has memorized.
This is where AI earns its keep. Not to grant access — I do that, with my eyes open — but to decode the permission namespace, draft a tight custom role from observed usage, and write the IAM conditions I’d otherwise skip because they’re fiddly.
Start from what the workload actually used
Never design a role from imagination. GCP records which permissions a principal exercised. Pull recommendations from the IAM Recommender and the policy analyzer first:
# Roles the recommender thinks are over-granted on this project
gcloud recommender recommendations list \
--project=my-prod-project \
--location=global \
--recommender=google.iam.policy.Recommender \
--format="table(content.overview.member, content.overview.removedRole)"
That gives you the “this binding is too broad” signal. To go further, export the service account’s recent permission usage and hand the raw list to AI to cluster into a coherent role. The model is genuinely good at turning a flat list of 60 resourcemanager.* and storage.objects.* permissions into a named, minimal custom role.
Prompt: “Here is the list of IAM permissions a service account actually used in the last 90 days (pasted below). Group them into a single custom GCP role. Output a valid
gcloud iam roles createYAML definition. Flag any permission that implies write or delete access so I can confirm the workload truly needs it. Do not add permissions that aren’t in my list.”
The “do not add permissions that aren’t in my list” clause matters. Without it, models pad roles with “you’ll probably want this too” grants, which is exactly the sprawl I’m trying to kill.
Draft the custom role, then read every line
Here’s the kind of definition I get back, which I then review by hand before applying:
title: "image-pipeline-runner"
description: "Minimal role for the CI build pipeline service account"
stage: "GA"
includedPermissions:
- storage.objects.create
- storage.objects.get
- storage.objects.list
- artifactregistry.repositories.uploadArtifacts
- artifactregistry.repositories.downloadArtifacts
- logging.logEntries.create
gcloud iam roles create imagePipelineRunner \
--project=my-prod-project \
--file=image-pipeline-runner.yaml
I read every permission. The AI proposed storage.buckets.delete because the usage log showed one delete during a cleanup job — but that was a one-off I didn’t want to bless permanently, so I cut it. The model surfaces candidates; the judgment about whether a rare action belongs in a standing role is mine.
Use IAM conditions to scope grants by time and resource
Most teams never touch IAM conditions because CEL expressions are annoying to write from scratch. This is a perfect AI task. I describe the constraint in English and let it produce the expression, then I test it.
Prompt: “Write a GCP IAM condition (CEL) that grants this binding only for objects in the bucket named
my-prod-uploads, and only until 2026-12-31. Explain each clause.”
gcloud storage buckets add-iam-policy-binding gs://my-prod-uploads \
--member="serviceAccount:image-pipeline@my-prod-project.iam.gserviceaccount.com" \
--role="projects/my-prod-project/roles/imagePipelineRunner" \
--condition='expression=resource.name.startsWith("projects/_/buckets/my-prod-uploads") && request.time < timestamp("2026-12-31T00:00:00Z"),title=uploads-only-2026'
A time-bound condition turns a permanent grant into one that expires on its own. For contractor access or migration windows, that’s the difference between cleaning up later (you won’t) and the grant cleaning up itself.
Kill long-lived service account keys
The single highest-leverage IAM change on GCP is getting rid of exported service account JSON keys. They don’t rotate, they end up in repos, and they’re the root cause of most GCP breaches I’ve seen. For workloads on GKE, use Workload Identity; for CI, use Workload Identity Federation with your provider’s OIDC token. Ask AI to convert a key-based setup:
Prompt: “I have a GitHub Actions workflow authenticating to GCP with a service account JSON key in a secret. Rewrite it to use Workload Identity Federation with OIDC. Give me the
gcloud iam workload-identity-poolscommands and the updatedgoogle-github-actions/authstep.”
Verify the resulting trust condition restricts to your specific repo — a misconfigured federation pool that trusts * is worse than the key you replaced. Check the attribute.repository mapping by hand.
Audit before you trust the policy
After changes, I have AI summarize the effective policy so I’m reviewing intent, not JSON:
gcloud projects get-iam-policy my-prod-project --format=json > policy.json
Prompt: “Summarize this GCP IAM policy JSON. List every principal that can read or write Cloud Storage, every principal with a primitive role (owner/editor/viewer), and any binding without an IAM condition that grants delete permissions. Plain table, no commentary.”
That report is what I actually act on. The pattern across all of this: AI reads the namespace, drafts the CEL, and writes the federation config, while I decide what gets granted and confirm every scope. For more on directing models toward defensive, minimal output, see my collection of reusable prompts, and the rest of the GCP with AI guides.
Least privilege on GCP isn’t hard because the concepts are hard. It’s hard because the busywork — reading permission lists, writing conditions, untangling key-based auth — is tedious enough that people skip it. Hand the tedium to AI and keep the decisions for yourself.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.