-
Notifications
You must be signed in to change notification settings - Fork 28
IAM Enumeration and Analysis Workflow
This is the recommended path if your goal is permission mapping and escalation-path analysis.
modules run enum_gcp --iam
modules run enum_gcp_policy_bindings --ensure-treeIf you need to constrain deep Resource Manager checks to specific IDs while retaining broad discovery:
modules run enum_gcp --modules resource-manager --iam --get --project-allowlist-file projects.txt --folder-allowlist 123456789012 --org-allowlist-file org_ids.txtWith allowlists present:
-
enum_gcpstill performs broad Resource Manager discovery. - If no allowlist flags are supplied, all discovered resources/projects are treated as in scope.
- non-Resource-Manager service modules only run for projects that resolve into the effective allowlist scope.
- If only one direct allowlist type is provided, other direct resource types are out of scope unless explicitly allowlisted.
- Parent allowlist flags constrain by descendant hierarchy depth and intersect with direct allowlists when both are present.
- Exception:
enum_gcp_policy_bindingsstill runs once on the finalenum_gcploop. -
enum_gcp_policy_bindingsreads cached workspace resources; if you previously enumerated resources outside the allowlist, those can still be included unless you reset/clean cache first.
enum_gcp_policy_bindings supports service scoping:
modules run enum_gcp_policy_bindings --resource-manager --storage --compute --secretsAlongside the allow-policies (getIamPolicy), enum_gcp_policy_bindings also enumerates IAM
deny policies (the iam.googleapis.com v2 Policies API — a separate API that can
revoke permissions an allow grant would otherwise give). For every cached
organization / folder / project node it lists the attached deny policies and fetches each
one's rules (denied principals, denied permissions, exception principals, denial
condition), caching them into the iam_deny_policies table. The
iam.denypolicies.list / iam.denypolicies.get permissions are recorded as evidence per
scope. It's best-effort: if the IAM API is disabled or you lack the permission, deny
enumeration is skipped without affecting the allow-policy pass (a run prints
[*] IAM deny policies cached: N).
# deny policies land automatically with the bindings run — inspect them via `data`:
data sql --db service "SELECT scope_type, scope_name, policy_id, denied_principals, denied_permissions FROM iam_deny_policies;"Deny policies inherit downward: a policy attached to an org or folder applies to every descendant folder / project / resource (like allow-policy inheritance). GCPwn currently enumerates and stores them; folding their effect into the OpenGraph effective-access model (subtracting denied permissions down the hierarchy) is planned but not yet wired into the graph.
If direct per-service IAM enumeration is denied but you hold cloudasset.*, a single
Cloud Asset Inventory scan can populate the same IAM tables (iam_allow_policies,
hierarchy, service accounts/keys/roles, compute instances, WIF) in one call:
modules run enum_asset_inventory --scope organizations/123456789012--scope accepts projects/<id>, folders/<id>, or organizations/<id> (defaults to the
current project). Inside enum_gcp this is opt-in — add --asset-inventory to run it in
addition to everything else.
modules run process_gcp_iam_bindingsOptional outputs:
modules run process_gcp_iam_bindings --csv --txt
modules run process_gcp_iam_bindings --silent --csv --txt
modules run process_gcp_iam_bindings --force-refresh-bindingsWhat this gives you:
- flattened member-to-role/resource summaries
- inheritance-aware organization/folder/project context
- per-member rows stored for downstream reporting
creds info
creds info --csv--csv is useful when terminal truncation hides long permission sets.
modules run process_og_gcpwn_data --expand-inherited --reset --out ./bh_out--out/-o is an output directory; files are written as opengraph_<folder>.json.
Key behaviors:
-
--expand-inheritedfans ancestor (org/folder) bindings down to every descendant scope. Each descendant binding node gets a@<scope>#src:<source>provenance suffix and its own dangerous edges. Without it, an ancestor binding stays attached to the ancestor only and descendants are not materialized. - Conditioned bindings always carry a
#cond:<hash>suffix (see the conditionals FAQ in Troubleshooting). Inherited + conditioned bindings carry both:...#src:<source>#cond:<hash>. - Default mode collapses dangerous
CAN_*edges intoROLE_OWNER/ROLE_EDITOR. Add--include-allto keep the generic binding edges as well.
You can also build the graph directly from a Cloud Asset Inventory export file with
--cai-file <export> (no prior enumeration / no SQLite); that output is exported but not
persisted to the workspace.
Then import JSON into BloodHound CE.
analyze_vulns is currently a scaffold and returns:
[*] analyze_vulns is coming soon.
Use process_gcp_iam_bindings + OpenGraph for current operational analysis.
- Authentication Reference
- Workspace Instructions
- Google Workspace Enumeration
- CLI Module Reference
- Enumeration Module Reference
- Exploit Module Reference
- Downloads to Disk
- Logging & Verbosity
- Data View/Export
- IAM Enumeration and Analysis Workflow
- Troubleshooting and FAQ