Skip to main content

IAM Best Practices

Exam guide§4.1

The exam rewards the "most secure, least-privilege" answer. When two options both work, pick the one that grants less, to a group, without a key.

Core principles:

  • Least privilege - grant the narrowest predefined role, at the lowest scope, for the shortest time. Start from zero and add.
  • Groups over individuals - bind roles to Google Groups, then manage membership in the group. Access changes = add/remove from group, not re-edit IAM policies everywhere.
  • Avoid basic roles - Owner/Editor/Viewer are too broad for production; prefer predefined.
  • Avoid SA keys - use attached SAs, impersonation, or Workload Identity Federation instead of downloaded JSON keys.
  • Separate duties - don't give one person both Owner and billing/security admin unless required.
GotchaGrant at the right scope, not the convenient one

Granting a role at the org or project level "so it just works" is the classic least-privilege violation. Grant at the highest level where the access is needed everywhere below, and no higher. One bucket → grant on the bucket, not the project.

GotchaRotate and eliminate keys

If an SA key must exist, rotate it regularly and never commit it to source control. Better: disable key creation entirely with the org policy constraints/iam.disableServiceAccountKeyCreation. Prefer Workload Identity Federation so no key exists at all.

NumbersGuardrails to remember
  • Policy Analyzer / IAM Recommender - surface and remove over-granted roles automatically.
  • Org policies to enforce hygiene: disableServiceAccountKeyCreation, disableServiceAccountKeyUpload, iam.allowedPolicyMemberDomains (block external members). More: Organization policies.
  • Service Account Token Creator for impersonation instead of keys.
  • IAM Conditions to time-box or resource-scope a grant.
GotchaRecommender works from real usage

IAM Recommender flags roles that grant more than a principal actually uses and suggests you remove or replace them. It bases this on policy insights - ML analysis of roughly the last 90 days of permission usage - so at scale you enforce least privilege without hand-auditing every binding.

Groups for role assignment

A group is not only a job title. You can create a group purely to carry a role, and split one team across several such groups when its members need different access. Then you grant access by changing group membership, never by re-editing an IAM policy.

Example: a Network Admin Group whose members all do networking, but some need read_write on a Cloud Storage bucket and others only read_only. Make one group per role and drop each person into the group that matches their access. Total access is controlled by add/remove on the groups.

NetworkAdmin GroupGroup needingview_only roleGroup needingread_write role
Groups can exist purely for role assignment - split one team into per-role groups and manage access by membership.
GotchaA group binding is only as safe as the group's owner

Whoever owns the Google Group used in a policy can silently add members and hand out that access. So control ownership of any group used in IAM policies and audit its membership - the IAM policy can look untouched while access changed underneath it.

Service accounts

  • Give every service account a display name that states its purpose, using an established naming convention - guessable names are the difference between an auditable project and a pile of sa-1, sa-2.
  • Establish key rotation policies and audit existing keys with the serviceAccount.keys.list method.
GotchaService Account User is transitive access

Granting roles/iam.serviceAccountUser on a service account lets the grantee act as that SA - so they inherit everything the SA can reach, not just the SA itself. Treat it as granting all of the SA's access at once, and grant it only on the specific SA that a workflow needs.

CommandsAudit service-account keys
# List keys on a service account (spot stale / unrotated keys)
gcloud iam service-accounts keys list \
--iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

Identity-Aware Proxy (IAP)

IAP puts a single identity-checked gate in front of applications reached over HTTPS, so you authorize by who the user is rather than where they connect from. It replaces network-level firewalls / VPNs with an application-level access model: a request only reaches the app if its user or group holds the right IAM role, and the app's own fine-grained controls still apply afterward.

Google CloudUsersIAPERPCRMIdentity
IAP is a central authorization layer: users reach ERP / CRM only through the proxy, and only if their IAM role allows it - no VPN.
GotchaIAP authorizes after authentication, not instead of it

IAP checks identity first, then applies the IAM policy. Granting someone an IAP role does not bypass the application's own permission checks - the fine-grained access controls of the product in use still apply once past the proxy.

Recap

CommandsAudit and tighten
# Find who can do what across the project
gcloud projects get-iam-policy PROJECT_ID --format=json
 
# Enforce: no new SA keys anywhere under a project
gcloud resource-manager org-policies enable-enforce \
constraints/iam.disableServiceAccountKeyCreation \
--project=PROJECT_ID
 
# Prefer group bindings
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="group:data-viewers@example.com" \
--role="roles/bigquery.dataViewer"
DECISIONTwo options both work - which is "correct"?
Choice AChoice BPrefer
Bind to group:Bind to each user:Group
Predefined roleBasic (Editor)Predefined
Attached SA / federationDownload SA keyKeyless
Grant on the resourceGrant on the projectLowest scope
Pick this when: choose the answer that grants the least, to a group, at the lowest scope, with no key