# Google Cloud IAM: — Least Privilege Without Breaking Everything

Source: https://ai.techclick.in/blog_gcp_iam_least_privilege
Markdown: https://ai.techclick.in/blog_gcp_iam_least_privilege.md
Publisher: Techclick Infosec Pvt Ltd

GCP IAM least privilege for L1/L2 engineers and the Professional Cloud Security Engineer exam: members, basic vs predefined vs custom roles, the resource hierarchy, service-account key risk, impersonation, and IAM Recommender.

Google Cloud IAM: — Least Privilege Without Breaking Everything student learning map
                     A visual study map for Google Cloud IAM: — Least Privilege Without Breaking Everything showing learning path, evidence, traps, and practice sequence.

                     TECHCLICK STUDY MAP
                     Google Cloud IAM: — Least Privilege Without Breaking...
                     GCP · learn the flow, prove with evidence, avoid unsafe shortcuts

   1. Start
   🎯 By the end you will be able to

   2. Understand
   Pick where you want to start

   3. Prove
   ② Roles — basic, predefined &amp;...

   4. Practice
   ③ Service accounts — the #1 GCP...

                     How to use this page
                     First build the mental model, then connect the concept to a realistic production decision. Finish by testing yourself.
                     Techclick Infosec Pvt Ltd | ai.techclick.in | Training Contact: WhatsApp +91 92772 29456

             Content-specific feature visual for this lesson: use it as the 60-second map before reading the full detail.

             Most engineers think…

             Most engineers think least privilege means "lock everything down, then add permissions back when people complain" — so they either over-grant Editor to avoid the complaints, or under-grant and spend all day firefighting AccessDenied tickets.

             Wrong framing. Least privilege in GCP is a  scope + role-type + identity  decision you make once, with data: grant the  narrowest predefined (or custom) role , at the  smallest resource in the hierarchy  that works, to a  group not a person  — then let  IAM Recommender  trim what's unused after 90 days. The tools (Recommender, Policy Analyzer, deny policies, org-policy guardrails) exist precisely so you don't have to choose between over-granting and firefighting.

## ① The GCP IAM model — members, roles, resources & the inheriting allow policy

 Picture Sneha, an L1 cloud engineer at  Flipkart . On her first day she's told "give the payments team read access to the logs." To do that safely she has to understand three nouns and one rule. The three nouns:  member  (who),  role  (what they can do), and  resource  (on what). The rule: those three are tied together by an  allow policy  that  inherits downward  through the resource tree. Get those four ideas and the rest of IAM is detail.

 Start with  members  (Google's docs now call them  principals ; older APIs still say members). Four kinds matter on day one: a  Google account  (sneha@flipkart.com), a  Google group  (payments-readers@flipkart.com — grant to the group, not the person, so leavers lose access automatically), a  service account  (the robot identity your app runs as), and a  workload identity  (an outside workload — GitHub Actions, a Kubernetes pod — that gets short-lived GCP credentials with no key file to leak).

 Next,  roles . A role is a bundle of  permissions , and every permission is written  service.resource.verb  — for example  logging.logEntries.list  or  storage.objects.get . You grant the  role , never the raw permission. A  binding  is one member plus one role on one resource — that's literally a line in the allow policy.

 👉 So far: member + role on a resource = a binding, stored in that resource's allow policy. Next: the rule that makes one careless binding dangerous — inheritance.

 Now the rule that L1 engineers underestimate:  the allow policy inherits down the hierarchy . GCP arranges everything as  Organization → Folder → Project → resource . If you set  roles/viewer  for a group at the  Organization  node, that group can now view  every folder, every project, every bucket  beneath it — possibly hundreds of projects you've never seen. Inheritance is one-directional (downhill): a grant on a single bucket does NOT bubble up to the project. That asymmetry is the whole game — bind at the  smallest  scope that does the job.

  Figure 1 — Members + role = binding, attached to a resource, inherited down the hierarchy

 The GCP IAM model drawn as a pyramid. At the top is the Organization, below it Folders, then Projects, then resources like a Cloud Storage bucket and a Compute VM. A role binding (member plus role) attached at the Organization node flows down to every node below through inheritance, shown by green arrows. Members on the left are a Google account, a Google group, a service account and a workload identity. The role is the bundle of permissions in service dot resource dot verb format. The amber binding box is the allow policy decision point.

 members + role = binding → attached to a resource → inherited DOWN

 Members (who)
  👤 Google account
  👥 Google group
  🤖 service account
  🔗 workload identity
  + role (bundle)  storage.objects.get  = service.resource.verb

- binding = member+role Organization bind roles/viewer here… 📁 Folder (prod / dev) 📦 Project (flipkart-pay-prod) 🪣 bucket 🖥️ VM Inheritance is downhill ONLY A grant at Org lands on EVERY folder, project & resource below. Bind at the SMALLEST scope that works — not at the Org. untrusted / attacker trusted / inspected policy / decision key insight allowed Read the green arrows: a binding attached high in the tree rains down on everything below. Bind at the bucket, not the Org, unless every project truly needs it. gcloud — read the allow policy on a project and see its bindings gcloud projects get-iam-policy flipkart-pay-prod --format=json Expected output { "bindings": [ { "role": "roles/logging.viewer", "members": ["group:payments-readers@flipkart.com"] }, { "role": "roles/owner", "members": ["user:sneha@flipkart.com"] } ], "etag": "BwYg7x1kQ2c=", "version": 1 } ### The four nouns, one tap each Tap each card — every IAM question on the job and the exam is built from these. 👤 Member tap to flip Who is asking: account, group, service account, or workload identity. So: prefer groups — access follows the team, not the person. 🎁 Role tap to flip A named bundle of permissions (service.resource.verb). So: you grant a role, never a raw permission. 📦 Resource tap to flip What's protected — Org, Folder, Project, bucket, VM. So: where you attach the binding decides the blast radius. ⬇️ Inheritance tap to flip Allow policies flow DOWN the tree, never up. So: a grant at the Org touches every project below it. Daily-life analogy — the society gate-pass register Think of your apartment society's gate-pass register . A pass issued at the main gate (the Organization) lets the visitor into every tower and flat inside — that's an Org-level binding. A pass issued by one flat's resident (a single bucket) only opens that flat. The guard always checks the register (the allow policy) before letting anyone in, and a pass for the whole society is exactly what you should hesitate to hand out. Least privilege is just: issue the narrowest pass, for the smallest area, that gets the job done. Quick check · Q1 of 10 Sneha needs to let the payments team read logs in ONE project. A senior says "just grant roles/viewer at the Organization, it's faster." Why is that the wrong move? a) Org-level grants aren't allowed by GCP at all b) Because the allow policy inherits down — that grant would let the team view every project under the Org, not just the one c) roles/viewer can't read logs; you need Owner d) Logs live outside the resource hierarchy, so it has no effect Correct: b. Allow policies inherit downward, so a binding at the Organization applies to every folder, project and resource beneath it — far more than the one project. roles/viewer DOES include log-read; Owner is overkill; and logs are project resources, squarely inside the hierarchy. Bind roles/logging.viewer on the single project (or a log bucket) instead. Pause & Predict Predict: you grant roles/storage.admin to a group on a single bucket. Does that group now also have storage.admin on a DIFFERENT bucket in the same project? Type your guess. Reveal answer Answer: No. Inheritance only flows DOWNWARD from a container to the things inside it — never sideways between siblings and never upward. A binding on bucket-A stays on bucket-A; bucket-B in the same project is unaffected unless you bind the role at the project (or higher) level. This is exactly why scoping to the single resource is the safest default — the blast radius is contained to that one resource. ## ② Roles — basic, predefined & custom (and why Editor on prod hurts) There are exactly three families of role, and picking the right family is most of least privilege. Basic roles — roles/owner , roles/editor , roles/viewer — are the oldest and the broadest. Editor alone carries thousands of permissions across nearly every service. Predefined roles are service-scoped and maintained by Google (e.g. roles/storage.objectViewer , roles/pubsub.publisher ) — this is your default. Custom roles are ones you build from a hand-picked list of permissions, for when even the tightest predefined role is still too wide. Why is Editor on a production project the classic interview red flag? Because Editor can create, modify and delete resources across the whole project — start and stop VMs, edit firewall rules, rewrite Cloud Functions, drop database instances. The trap is that Editor cannot change IAM, so people convince themselves it's "safe." It isn't: an attacker (or a buggy script) with Editor can still take down or tamper with your entire payments stack. Google's own guidance is blunt — don't grant basic roles in production unless there's genuinely no predefined alternative. 👉 So far: basic = too broad, predefined = default, custom = tightest. Next: how to actually find the right predefined role instead of reaching for Editor. The practical workflow when someone asks for access: name the service they need (Cloud Storage? BigQuery? Pub/Sub?), name the verb (read? write? admin?), then look up the predefined role that matches — for read-only object access it's roles/storage.objectViewer , not roles/editor . Only if no predefined role fits — say they need three specific compute permissions and nothing more — do you build a custom role . The cost of custom is that you now own it: when Google adds a new permission to a service, your custom role won't pick it up automatically. Figure 2 — Three kinds of key A three-column comparison of role types. Left, basic roles Owner Editor Viewer drawn as a giant master key opening every door — thousands of permissions, marked red as too broad and dangerous on production. Middle, predefined service-scoped roles drawn as a labelled key opening one service door — the sensible default, marked blue. Right, a custom role drawn as a key cut to exactly the few permissions needed, marked green as true least privilege. A note warns Editor can change almost anything but cannot manage IAM, which lulls people into thinking it is safe. Three kinds of key: master, labelled, or cut-to-fit Basic — Owner / Editor / Viewer 🗝️ ✗ thousands of perms, all services ✗ Editor can change almost anything ✗ Owner can also re-grant IAM ✗ huge blast radius on prod avoid on production projects "tighten later" rarely happens one master key for the whole project Predefined — the default choice 🔑 ✓ scoped to one service + job roles/storage.objectViewer roles/pubsub.publisher ✓ Google maintains it as APIs change start here for 90% of grants a labelled key for one door opens just the service it names Custom — true least privilege 🗝 ✓ only the exact perms you list compute.instances.get compute.instances.list ✓ when predefined is still too wide you maintain it as perms appear key cut to exactly these teeth opens nothing more than listed untrusted / attacker trusted / inspected policy / decision key insight allowed Left (red) = a master key to the whole project. Middle (blue) = a labelled key for one service — your default. Right (green) = a key cut to exactly the teeth you listed. GCP Console → IAM & Admin → IAM → Grant access . (Recreated for clarity — your console matches this.)"> 🖥️ This is the screen you'll use to grant a role — GCP Console → IAM & Admin → IAM → Grant access . (Recreated for clarity — your console matches this.) console.cloud.google.com · IAM & Admin · IAM · Grant access 1 New principals payments-readers@flipkart.com 2 Select a role Cloud Storage › Storage Object Viewer 3 Resource Project: flipkart-pay-prod IAM condition (optional) Add condition — limit by time / resource name 4 Role being added roles/storage.objectViewer Save gcloud — grant a narrow predefined role at the smallest scope (a single bucket) gcloud storage buckets add-iam-policy-binding gs://flipkart-pay-receipts \ --member="group:payments-readers@flipkart.com" \ --role="roles/storage.objectViewer" Expected output bindings: - members: - group:payments-readers@flipkart.com role: roles/storage.objectViewer etag: CAE= Updated IAM policy for bucket [gs://flipkart-pay-receipts]. Common mistake — "Editor is fine, it can't touch IAM" Symptom you'll hear: "why did our staging DB get deleted overnight? The CI service account only had Editor." Cause: Editor includes cloudsql.instances.delete (and thousands more) — not being able to change IAM does not make it harmless. A compromised key with Editor can still wipe or tamper with the whole project. Fix: replace the basic role with the specific predefined role the pipeline actually needs (often just roles/cloudsql.client + a deploy role), and let IAM Recommender confirm what's truly used. Quick check · Q2 of 10 Rahul at TCS needs a service account that ONLY uploads objects to one bucket from a nightly job. Which role choice best follows least privilege? a) roles/editor on the project — simplest to set up b) roles/owner on the bucket so it never hits permission errors c) roles/storage.objectCreator (or objectAdmin) bound on that single bucket d) A basic roles/viewer at the Organization level Correct: c. A predefined, service-scoped role bound on the one bucket gives exactly the upload ability and nothing else. Editor and Owner are massively over-scoped; roles/viewer is read-only (uploads would fail) AND binding it at the Org sprays view access across every project. Match the service + verb, bind at the smallest resource. Pause & Predict Predict: you build a custom role with compute.instances.get and compute.instances.list. Six months later Google adds compute.instances.osLogin as a new permission needed to SSH. Does your custom role get it automatically? Type your guess. Reveal answer Answer: No — that's the maintenance cost of custom roles. Predefined roles are updated by Google as services evolve, so a predefined role would pick up sensible new permissions. A custom role is frozen to the exact list you wrote; it won't gain the new permission until YOU add it. That's why the guidance is: reach for a predefined role first, and only drop to custom when no predefined role is tight enough — then accept that you now own its upkeep. ## ③ Service accounts — the #1 GCP risk (keys, impersonation & how to cap it) If there's one thing to remember from this lesson for the job, it's this: service-account keys are GCP's number-one IAM risk . A service-account key is a JSON file holding a long-lived private key. Whoever has the file can authenticate as that service account and inherit everything it can do. There's no password, no MFA, no expiry. So when a key lands in a public Git repo, a CI log, a Slack message, or a leaked laptop, the attacker doesn't need to break anything — they just use the file. The fix Google now pushes hard: stop downloading keys . For workloads outside GCP (GitHub Actions, an on-prem job, an EKS pod) use Workload Identity Federation ; for one identity acting as another inside GCP use impersonation to mint short-lived tokens on demand. Both replace a permanent, leakable file with credentials that expire in about an hour. If your org was created on/after 3 May 2024 , GCP even blocks external key creation by default via an org policy. 👉 So far: downloaded keys leak and never expire; prefer workload identity / short-lived tokens. Next: the escalation that turns a small role into a big one — impersonation and actAs. Now the privilege-escalation trap that the Professional Cloud Security Engineer exam loves. Two role/permission names matter. roles/iam.serviceAccountTokenCreator grants iam.serviceAccounts.getAccessToken — meaning the holder can mint a token for the target SA and become it. actAs (from roles/iam.serviceAccountUser ) lets a principal attach an SA to a new VM or function, so that resource runs as the SA. The danger: if either role is granted at the project, folder or org level , the holder can act as every current and future SA below it — and if one of those SAs is an Owner, a low-privileged user has just escalated to Owner. Worse, impersonation chains : A impersonates B impersonates C, walking up to the most powerful account. Figure 3 — How a small grant becomes Owner A request evaluation flow. A principal makes an API call to a resource. First an organisation-policy guardrail (a constraint) is checked: if it forbids the action class, access is denied no matter what. Next the deny policy is evaluated: an explicit deny wins over any allow. Finally the allow policy (inherited bindings) is evaluated: if a binding grants the permission, the call is allowed; otherwise it is denied by default. Amber diamonds are decision points, red is denied, green is allowed. How one API call is decided: guardrail → deny → allow Priya (member) calls storage.objects.delete Org-policy guardrail? Deny policy? explicit deny wins Allow binding? role grants it? pass no deny ✗ DENIED — constraint forbids it e.g. iam.disableServiceAccountKeyCreation blocked class ✗ DENIED — explicit deny rule ✓ ALLOWED a binding grants the permission ✗ DENIED by default no binding Key insight: a deny policy and an org-policy guardrail are how you CAP a role you can't fully remove yet. untrusted / attacker trusted / inspected policy / decision key insight allowed Follow the red arrows: a junior with tokenCreator at the PROJECT level can impersonate a high-privilege SA and chain up to Owner. The fix (green) is to grant it on ONE specific SA only. ### ▶ Watch a leaked key escalate — and where each cap stops it Karthik's nightly-backup service account key gets pasted into a public Gist. Follow the attacker's path, and notice the three points where a guardrail would have stopped them. Press Play for the healthy path, then Break it to see the failure. ① Key leaks backup-sa key.json found in a public Gist; attacker authenticates as the SA ▼ ② Enumerate attacker runs get-iam-policy ; sees backup-sa holds roles/iam.serviceAccountTokenCreator on the project ▼ ③ Impersonate mints a token for deploy-sa (an Owner) via getAccessToken — now effectively Owner ▼ ④ Exfiltrate reads every bucket , adds an SSH key, leaves; only the audit log noticed Press Play to step through the healthy path. Then press Break it . ▶ Play Next ▶ ⚠ Break it ↺ Reset gcloud — the RIGHT way: impersonate per-task (short-lived), no downloaded key # grant tokenCreator on ONE specific SA, to ONE group — not the project gcloud iam service-accounts add-iam-policy-binding \ deploy@flipkart-pay-prod.iam.gserviceaccount.com \ --member="group:release-eng@flipkart.com" \ --role="roles/iam.serviceAccountTokenCreator" # now run a command AS that SA with a 1-hour token, no key file gcloud storage ls gs://flipkart-pay-receipts \ --impersonate-service-account=deploy@flipkart-pay-prod.iam.gserviceaccount.com Expected output Updated IAM policy for serviceAccount [deploy@flipkart-pay-prod.iam.gserviceaccount.com]. WARNING: This command is using service account impersonation. All API calls will be executed as [deploy@flipkart-pay-prod...]. gs://flipkart-pay-receipts/2026-06/ gs://flipkart-pay-receipts/2026-05/ Prove no leakable keys exist for an SA Don't assume — list them. Run gcloud iam service-accounts keys list --iam-account=deploy@PROJECT.iam.gserviceaccount.com --managed-by=user . The --managed-by=user filter shows only the downloadable keys you created (Google-managed keys never leave Google and are fine). If that list is empty, there's no JSON file out there to leak. If it isn't, rotate/delete the key and switch the workload to impersonation or workload identity. Meera at ICICI faces this Meera, an L2 cloud-security analyst, gets a CSPM alert: a low-privilege analytics service account can somehow read the production secrets bucket it was never granted on. Likely cause The analytics SA holds roles/iam.serviceAccountTokenCreator at the PROJECT level. That lets it impersonate the data-pipeline SA, which DOES have access to the secrets bucket — classic impersonation escalation, not a direct grant. Diagnosis She stops looking at the bucket's own bindings and instead asks 'who can become an SA that can reach this bucket?' — she checks the project-level tokenCreator/actAs grants and the audit logs for GenerateAccessToken calls. GCP Console → IAM & Admin → IAM (filter role: Service Account Token Creator) → then Logging → GenerateAccessToken events Fix Remove tokenCreator at the project level; re-grant it only on the one SA that truly needs it, scoped to the release-eng group. Add an org policy disabling SA key creation, and an IAM deny policy on iam.serviceAccounts.getAccessToken for non-release identities. Verify Re-run a Policy Analyzer query 'who can access gs://icici-prod-secrets' — the analytics SA no longer appears in the access path, and a test impersonation attempt returns PERMISSION_DENIED. Quick check · Q3 of 10 Arjun at Airtel finds roles/iam.serviceAccountTokenCreator granted to a developer group at the PROJECT level. Why is the scope, not just the role, the problem? a) tokenCreator is harmless; only Owner can escalate b) At project scope it lets the group impersonate every current and future SA in the project — including any high-privilege one c) Project-scope grants are read-only by design d) The role can't mint tokens, only list service accounts Correct: b. Granting tokenCreator (or actAs) at the project/folder/org level extends to all SAs below it, so the group can impersonate any SA in the project — if one is an Owner, that's a path to Owner. The role absolutely mints access tokens (iam.serviceAccounts.getAccessToken), and project-scope grants aren't read-only. The fix is scope: bind it on one named SA, not the project. Pause & Predict Predict: your org sets the iam.disableServiceAccountKeyCreation constraint at the Organization. A team genuinely needs a key for one legacy app in one project. What happens, and what's the clean way out? Type your guess. Reveal answer Answer: Key creation is blocked everywhere the constraint is inherited — so that one legacy project also can't create keys, and you'll see a 'Service account key creation is disabled' error. The clean way out is NOT to remove the org-wide guardrail. Instead, set an exception (override) on that single project's org-policy node to allow it, or better, migrate the legacy app to workload identity / impersonation. Guardrail stays org-wide; exception is surgical and scoped to the one place that needs it. ## ④ Tightening down — Recommender, Policy Analyzer & a real investigation You've granted access carefully — but access drifts. People change teams, projects get over-permissioned "to unblock something," and nobody walks it back. GCP gives you tooling so you don't have to audit by hand. The headliner is IAM Recommender : it compares each principal's granted permissions against what they actually used in the last 90 days and recommends a tighter role. If a service account holds Editor but only ever called a handful of compute read APIs, the Recommender will suggest swapping Editor for roles/compute.viewer . In the Console, open IAM & Admin → IAM and watch the Analyzed permissions column. A green "Recommendation available" tick next to a principal means the Recommender has a safe trim ready — one click applies it. The column also shows exercised-vs-total permissions, so you can see at a glance who's wildly over-granted. Internally, Google found most granted permissions go unused in a 90-day window — which is exactly the slack least privilege removes. 👉 So far: Recommender trims by real usage; the IAM page flags it for you. Next: answering the question every audit asks — 'who can access this bucket?' Two more tools finish the kit. Policy Analyzer answers the two audit questions directly: who can access this bucket? and what can this principal reach? — and crucially it follows impersonation paths, so it catches the indirect access Meera found in section ③. Policy Troubleshooter answers the opposite: why was this exact call allowed or denied? — it walks the allow policy, deny policy and org-policy guardrails for you, which turns a 30-minute AccessDenied hunt into a 30-second one. And the resource hierarchy you learned in section ① is itself the control: it's your blast-radius boundary — keep prod in its own folder/project so a mistake in dev can't reach it. GCP Console → IAM & Admin → Policy Analyzer → Create query . (Recreated for clarity — your console matches this.)"> 🖥️ The "who can access this?" investigation — GCP Console → IAM & Admin → Policy Analyzer → Create query . (Recreated for clarity — your console matches this.) console.cloud.google.com · IAM & Admin · Policy Analyzer · Create query 1 Query scope Project: flipkart-pay-prod 2 Resource //storage.googleapis.com/.../flipkart-pay-receipts 3 Permission storage.objects.get Identity selector All principals (include impersonation) 4 Result 3 principals · 1 via impersonation of deploy-sa Analyze gcloud — the audit one-two: who can read the bucket, then trim what's unused # 1) WHO can access this bucket? (follows impersonation) gcloud asset analyze-iam-policy \ --scope=projects/flipkart-pay-prod \ --full-resource-name="//storage.googleapis.com/flipkart-pay-receipts" \ --permissions="storage.objects.get" # 2) WHAT least-privilege trims does GCP suggest? gcloud recommender recommendations list \ --project=flipkart-pay-prod \ --recommender=google.iam.policy.Recommender \ --location=global Expected output analysisResults: - identityList: {identities: [group:payments-readers@flipkart.com]} accessControlList: {accesses: [{role: roles/storage.objectViewer}]} - identityList: {identities: [serviceAccount:analytics@...]} # via impersonation of deploy-sa RECOMMENDATION PRIMARY_IMPACT DESCRIPTION projects/.../recommendations/abc123 SECURITY Replace roles/editor with roles/compute.viewer Daily-life analogy — Aadhaar e-KYC vs photocopying your card Handing out a downloaded SA key is like giving every shop a photocopy of your Aadhaar card — once it's out, you can't take it back, and anyone can reuse it. Impersonation / workload identity is like Aadhaar OTP e-KYC : the verifier gets a one-time, time-limited proof for one transaction, and it expires on its own. Same access, but nothing permanent leaks. When you see a JSON key in a repo, picture a photocopy of your Aadhaar blowing down the street. Figure 4 — GCP IAM least-privilege cheat-sheet A nine-tile cheat sheet. Tiles cover the three role types, the permission format, the resource hierarchy and inheritance, the service-account key risk, the impersonation and actAs escalation map, the org-policy and deny guardrails, the IAM Recommender, Policy Analyzer, and the first gcloud commands to run. GCP IAM least privilege — your one-glance card 3 role types basic (Owner/Editor/Viewer) = avoid predefined = default · custom = tightest perm = service.resource.verb Hierarchy = blast radius Org → Folder → Project → resource allow policy inherits DOWN only bind at smallest scope that works SA key = #1 risk downloaded JSON key leaks → game over prefer workload identity / short-lived rotate ≤90d, delete unused Escalation map tokenCreator → getAccessToken → become SA actAs (serviceAccountUser) → attach SA grant on ONE SA, never project-wide Guardrails (the caps) iam.disableServiceAccountKeyCreation deny policy beats every allow IAM Conditions = time/IP limits IAM Recommender reads last 90 days of usage suggests a narrower role to swap in ✓ Recommendation available icon Policy Analyzer "who can access this bucket?" + "what can this principal reach?" Troubleshooter = why a call was denied First commands gcloud projects get-iam-policy PROJECT gcloud asset analyze-iam-policy gcloud recommender recommendations list Golden rule grant the smallest role, at the smallest scope, to a group not a person — then audit. Your one-card map of this lesson — role types, the SA-key escalation map, the guardrails, Recommender/Analyzer, and the first commands to run. Keep it open in week one. Prove you own least privilege Cold, in 60 seconds: name the three role families and when to use each ( basic=avoid, predefined=default, custom=tightest ); say why a grant at the Org is dangerous ( inheritance is downhill ); explain the SA-key risk ( leakable, no expiry ) and the escalation ( tokenCreator/actAs at project scope → impersonate any SA ); and name the tool that answers "who can access this bucket?" ( Policy Analyzer ) and the one that trims unused roles ( IAM Recommender, 90-day usage ). If you can do that without notes, you're ready for the Security Engineer exam's IAM domain. Next: GCP VPC Service Controls — a perimeter around your data Quick check · Q4 of 10 An interviewer asks Neha: "You inherit a project where a service account has roles/editor. What's your first, lowest-risk step toward least privilege?" a) Immediately delete the service account b) Swap Editor for Owner so it's clearer c) Open IAM Recommender / the Analyzed-permissions column to see which permissions it actually used in 90 days, then apply the suggested narrower role d) Grant it tokenCreator on the project so it can self-manage Correct: c. IAM Recommender uses real 90-day usage to suggest a safe, narrower role you can apply with one click — the lowest-risk way to tighten without breaking the workload. Deleting the SA breaks whatever runs as it; Owner is broader than Editor (the wrong direction); and granting tokenCreator at project scope opens an escalation path. Measure usage first, then tighten. ### 🤖 Ask the AI Tutor Tap any question — instant, scoped to this lesson. No login, no waiting. Basic vs predefined vs custom — how do I instantly pick the right one? Why are service-account keys called the #1 GCP risk specifically? What's the real difference between actAs and tokenCreator? If inheritance only flows down, where exactly should I bind a role? How do I answer 'who can access this bucket?' on the job? How much of the Professional Cloud Security Engineer exam is this lesson? Pre-curated from GCP docs + community Q&A, scoped to this lesson. For a live prod issue, paste your export into chat.techclick.in. ## 📝 Wrap-up assessment — six more You've answered 4 inline. Six left. 70% (7 of 10) marks the lesson complete on your profile. Tap Submit all answers at the end. Q5 · Remember In GCP IAM, what does an allow policy do as you move down the resource hierarchy (Organization → Folder → Project → resource)? a) It applies only to the exact resource it's attached to and nowhere else b) It bubbles upward from a resource to its parent project c) It is re-evaluated randomly per request d) It inherits downward, so a binding on a container applies to every resource inside it Correct: d. Allow policies inherit downward: set one on a container (Org/Folder/Project) and it applies to everything inside. It does not bubble upward (a bucket grant doesn't reach the project) and it isn't limited to a single resource or random — so the other options are wrong. Q6 · Apply A Wipro developer needs to publish messages to exactly one Pub/Sub topic. Following least privilege, what do you grant and where? a) roles/pubsub.publisher bound on that single topic b) roles/editor on the project c) roles/owner on the project so nothing breaks d) A basic roles/viewer at the Organization Correct: a. roles/pubsub.publisher is the service-scoped predefined role for publishing; binding it on the one topic is the smallest scope that works. Editor/Owner on the project are wildly over-scoped, and roles/viewer is read-only AND binding it at the Org sprays access across every project. Q7 · Apply You need to find out which principals can read objects in gs://flipkart-pay-receipts, including any who get there by impersonating another SA. Which tool/command fits? a) gcloud projects get-iam-policy — read the project's bindings only b) Policy Analyzer / gcloud asset analyze-iam-policy with the bucket resource and storage.objects.get c) gcloud compute instances list d) IAM Recommender — it lists who can access a bucket Correct: b. Policy Analyzer (analyze-iam-policy) answers 'who can access this resource?' and follows impersonation paths, so it catches indirect access. get-iam-policy shows only direct project bindings and misses impersonation; instances list is unrelated; Recommender trims unused roles, it doesn't answer access-path queries. Q8 · Analyze A low-privilege analytics service account can read a production secrets bucket it was never directly granted on. Direct bindings on the bucket look clean. Most likely root cause? a) The bucket is public to all users b) roles/viewer at the Org gives write to secrets c) The analytics SA holds tokenCreator/actAs at project scope and impersonates an SA that DOES have access d) IAM Recommender granted it access automatically Correct: c. Clean direct bindings plus unexpected access is the signature of impersonation escalation: tokenCreator/actAs at project scope lets the SA become a stronger SA that can reach the bucket. A public bucket would show in the bindings; roles/viewer is read-only and Org-wide view ≠ secrets write; and Recommender only suggests trims, it never grants access. Q9 · Analyze Your org enforces iam.disableServiceAccountKeyCreation at the Organization. One legacy project legitimately needs a downloadable key. What's the correct, least-disruptive action? a) Set a scoped exception (override) on that one project's org-policy node, or migrate the app to workload identity b) Remove the org-wide constraint entirely so the key can be created c) Grant the team roles/owner so they bypass the policy d) Disable IAM on the legacy project Correct: a. Keep the org-wide guardrail and make a surgical exception on the single project node (or, better, remove the need for a key by moving to workload identity). Removing the org constraint re-exposes every project; Owner doesn't bypass an org policy and is over-granting; disabling IAM isn't a thing. Guardrail stays broad, exception stays narrow. Q10 · Evaluate Two ways to 'tighten' an over-permissioned service account: (A) immediately strip it to a guessed minimal role; (B) read IAM Recommender's 90-day usage and apply its suggested narrower role, plus scope any tokenCreator to one SA. Which is the stronger approach and why? a) A — acting fastest is always safest b) B — it tightens based on real usage data (so it won't break the workload) and closes the actual escalation path c) A — guessing a role is fine since you can re-add permissions later d) Identical — both reach the same end state Correct: b. B is evidence-based: Recommender's 90-day usage means the narrower role won't break what the SA actually does, and scoping tokenCreator removes the impersonation escalation that a guessed role-strip would miss. A risks an outage from guessing and leaves the escalation path open; they're clearly not identical. Submit all answers Try again Lesson complete — saved to your profile. Almost! You need 70% (7 of 10) — re-read the path that tripped you up and tap "Try again". ### 🧠 In your own words Type one line: In one line, why is binding roles/iam.serviceAccountTokenCreator at the project level dangerous even for a 'read-only' analyst group? Then compare to the expert version. Compare with expert answer Expert version: Because at project scope it lets the group impersonate every service account in the project — including any high-privilege one — so a read-only grant becomes a path to whatever the strongest SA can do; bind it on a single named SA instead. ### 🗣 Teach a friend Best way to lock it in — explain it in one line to a teammate. Tap to generate a paste-ready summary. Generate my one-liner 📩 Quiz me on this in 7 days. Opt in and we'll email 3 micro-questions on IAM & Least Privilege at Day 1, Day 7 and Day 30 — spaced repetition is how this sticks. Un-tick any time. ### 📖 Glossary Member / principal An identity that makes a request — Google account, group, service account, or federated workload identity. Role A named bundle of permissions you grant (e.g. roles/storage.objectViewer). You grant roles, never raw permissions. Permission The atomic unit of access, written service.resource.verb — e.g. storage.objects.get. Allow policy (IAM policy) The JSON/YAML object on a resource listing role bindings — which members hold which roles there. Resource hierarchy Organization → Folder → Project → resource. Allow policies inherit downward through it. Basic roles Owner / Editor / Viewer — very broad, thousands of permissions. Avoid in production. Predefined role A service-scoped role maintained by Google (e.g. roles/pubsub.publisher). The default choice. Custom role A role you build from a hand-picked permission list, for true least privilege when predefined is too wide. Service account key A downloadable JSON private key that authenticates as an SA with no expiry — GCP's #1 IAM risk if leaked. Workload Identity Federation Exchanges an external identity's token for a short-lived GCP token, so no JSON key is downloaded or leaked. Impersonation (tokenCreator) roles/iam.serviceAccountTokenCreator + iam.serviceAccounts.getAccessToken — mint a short-lived token to act as an SA. actAs (serviceAccountUser) iam.serviceAccounts.actAs — attach an SA to a resource so it runs as the SA; GCP's iam:PassRole. IAM Recommender Compares granted vs last-90-days-used permissions and suggests a narrower role to swap in. Policy Analyzer / Troubleshooter Analyzer answers who-can-access / what-can-reach; Troubleshooter explains why a call was allowed or denied. #### 📚 Sources Google Cloud IAM documentation — "IAM overview" (principals: Google account, group, service account, workload identity; basic/predefined/custom roles; permission format service.resource.verb; allow policy = role bindings; inheritance down Organization → Folder → Project → resource). docs.cloud.google.com/iam/docs/overview

- Google Cloud IAM documentation — "Best practices for using service accounts securely" (avoid downloaded keys; org-policy to limit key creation; rotate ≤90 days; dedicated SA per app; credential-leak / privilege-escalation threats). docs.cloud.google.com/iam/docs/best-practices-service-accounts

- Google Cloud IAM documentation — "Service account impersonation" + "Requiring permission to attach service accounts (actAs)" (iam.serviceAccounts.getAccessToken via roles/iam.serviceAccountTokenCreator; actAs via roles/iam.serviceAccountUser; granting at project/folder/org extends to all current & future SAs). cloud.google.com/iam/docs/service-account-impersonation · docs.cloud.google.com/iam/docs/service-accounts-actas

- Google Cloud blog + IAM docs — "IAM Recommender: least privilege with less effort" and "recommender overview" (compares granted permissions to last-90-days usage; Analyzed-permissions column + 'Recommendation available' icon; gcloud recommender recommendations list --recommender=google.iam.policy.Recommender). cloud.google.com/blog/products/identity-security/achieve-least-privilege-with-less-effort-using-iam-recommender · docs.cloud.google.com/iam/docs/recommender-overview

- Cisco-equivalent for GCP attackers — HackTricks Cloud "GCP - IAM Privesc" + Stratus Red Team "Impersonate GCP Service Accounts" (real tokenCreator/actAs escalation and impersonation chaining A→B→C used by red teams). cloud.hacktricks.xyz/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc · stratus-red-team.cloud/attack-techniques/GCP/gcp.privilege-escalation.impersonate-service-accounts/

- Google Cloud Organization Policy docs — "Restrict IAM service account usage" / iam.disableServiceAccountKeyCreation (enforced by default for orgs created on/after 3 May 2024) + IAM deny policies (explicit deny beats allow). docs.cloud.google.com/organization-policy/restrict-service-accounts · docs.cloud.google.com/iam/docs/deny-overview

- Google Professional Cloud Security Engineer — official exam guide (Section 2: configuring access within a cloud solution — resource hierarchy, least privilege, predefined vs custom roles, service-account & workload-identity security, Policy Intelligence). services.google.com/fh/files/misc/professional_cloud_security_engineer_exam_guide_english.pdf

### What's next?

             You've made sure the right identities have the right roles. But IAM alone can't stop a legitimately-authorised principal from copying data straight out to a personal project. Next we build a perimeter around the data itself.

                 Next · GCP VPC Service Controls: A Perimeter Around Your Data →
                 Practice on exam.techclick.in →

---
Cite this Techclick lesson with the source URL. Do not invent fees, batch dates, or job guarantees.
Browse all lessons: https://ai.techclick.in/blogs
AI index: https://ai.techclick.in/llms.txt
