-
Notifications
You must be signed in to change notification settings - Fork 28
OpenGraph Node Edge Tables
Table reference for the main node and edge types emitted by GCPwn OpenGraph.
Coverage note:
- Some edge kinds are rule-driven from
og_privilege_escalation_paths.json. - Some node types are generated dynamically from resource types.
- This page covers major emitted families and the default built-in rule kinds.
| Node Type | Meaning | Emitted By |
|---|---|---|
GoogleUser |
Human IAM principal (user:<email>) |
users/groups + IAM binding stages |
GoogleGroup |
Group principal (group:<email>) |
users/groups + IAM binding stages |
GCPServiceAccount |
Service account principal (serviceAccount:<email>) |
IAM binding + resource expansion stages |
GCPPrincipalSet |
Principal set principal (principalSet://...) |
IAM binding + resource expansion stages |
GCPDomainPrincipal |
Domain principal (domain:<domain>) |
users/groups stage |
GCPAllUsers / GCPAllAuthenticatedUsers
|
Global wildcard principal nodes | IAM binding stage |
GCPPrincipal |
Generic fallback principal type | IAM binding stage |
GCPProject |
Project resource node | IAM binding + resource expansion stages |
GCPFolder |
Folder resource node | IAM binding stage |
GCPOrganization |
Organization resource node | IAM binding stage |
GCPIamSimpleBinding |
Binding node used for principal -> binding -> resource modeling | IAM binding stage |
GCPIamMultiBinding |
Combo binding node for multi-permission rule matches | IAM binding multi-permission stage |
GCPServiceAccountKey |
Service account key node | resource expansion stage |
GCPExternalIdentitySource |
Synthetic external identity source used to highlight broad/no-condition federation trust | resource expansion stage |
GCPIamCapability |
Optional intermediate capability node for combo-hop rules | IAM binding multi-permission stage |
GCPIamBinding / GCPIamGrant
|
Compatibility/internal IAM graph node aliases used by styling and export logic | internal compatibility layer |
| Node Type | Example resource family |
|---|---|
GCPBucket |
Cloud Storage |
GCPComputeInstance |
Compute Engine |
GCPCloudFunction |
Cloud Functions |
GCPCloudRunService, GCPCloudRunJob
|
Cloud Run |
GCPWorkloadIdentityPool, GCPWorkloadIdentityProvider
|
IAM Workload Identity Federation |
GCPCloudSQLInstance |
Cloud SQL |
GCPArtifactRegistryRepo |
Artifact Registry |
GCPBigQueryDataset, GCPBigQueryTable, GCPBigQueryRoutine
|
BigQuery |
GCPPubSubTopic, GCPPubSubSubscription, GCPPubSubSchema, GCPPubSubSnapshot
|
Pub/Sub |
GCPServiceDirectoryNamespace, GCPServiceDirectoryService
|
Service Directory |
GCPCloudTasksQueue |
Cloud Tasks |
GCPKmsKeyRing, GCPKmsCryptoKey, GCPKmsCryptoKeyVersion
|
KMS |
GCPSpannerInstance, GCPSpannerDatabase
|
Spanner |
GCPSecret |
Secret Manager |
| Edge Type | Meaning | Emitted By |
|---|---|---|
GOOGLE_MEMBER_OF |
Principal is a member of a Google Group | users/groups stage |
DOMAIN_MEMBER_OF |
Principal maps into a domain node by email suffix | users/groups stage |
HAS_IAM_BINDING |
Principal contributes to a binding node | IAM binding stage |
HAS_COMBO_BINDING |
Principal contributes to a combo binding node | IAM binding multi-permission stage |
HAS_IMPLIED_PERMISSIONS |
Principal contributes to an inferred-permission binding node | inferred-permissions stage |
POLICY_BINDINGS |
Generic binding-to-target edge (mainly visible with --include-all) |
IAM binding stage |
ROLE_OWNER / ROLE_EDITOR
|
Collapsed high-signal role edges for roles/owner and roles/editor
|
IAM binding stage |
EXISTS_IN_PROJECT |
Resource is modeled inside a project | resource expansion stage |
EXECUTES_WITH |
Compute instance executes as attached service account | resource expansion stage |
GCP_SERVICE_ACCOUNT_KEY_FOR |
Service account key belongs to service account | resource expansion stage |
GCP_PRINCIPAL_SET |
Principal set includes service account membership | resource expansion stage |
WIF_PROVIDER_IN_POOL |
Workload Identity Provider belongs to Workload Identity Pool | resource expansion stage |
WIF_PRINCIPAL_IN_POOL |
WIF principal or principal set belongs to a workload identity pool | resource expansion stage |
GCP_FEDERATION_POSSIBLE |
No-condition external identity source can federate into a provider | resource expansion stage |
Inferred-permissions builder emits edge kinds in this pattern:
INFERRED_<EDGE_KIND>
Examples:
INFERRED_RESET_COMPUTE_STARTUP_SAINFERRED_START_COMPUTE_STARTUP_SAINFERRED_CREATE_AND_INVOKE_CLOUDFUNCTION_AS_SAINFERRED_UPDATE_AND_INVOKE_CLOUDFUNCTION_AS_SAINFERRED_CREATE_CLOUDSCHEDULER_JOB_AS_SAINFERRED_CAN_MODIFY_PROJECT_IAM
OpenGraph expands Cloud Resource Manager principal sets for service accounts into explicit membership edges:
principalSet://cloudresourcemanager.googleapis.com/projects/<PROJECT_NUMBER>/type/ServiceAccountprincipalSet://cloudresourcemanager.googleapis.com/folders/<FOLDER_NUMBER>/type/ServiceAccountprincipalSet://cloudresourcemanager.googleapis.com/organizations/<ORG_NUMBER>/type/ServiceAccount
Graph shape:
serviceAccount:<email>
-> GCP_PRINCIPAL_SET
-> principalSet://cloudresourcemanager.googleapis.com/.../type/ServiceAccount
Interpretation note:
-
GCP_PRINCIPAL_SETonly models principal-set membership, not permission grants by itself. - Effective access still comes from the IAM binding path:
serviceAccount:<email> -> GCP_PRINCIPAL_SET -> principalSet://... -> HAS_IAM_BINDING -> binding -> target resource - So even when a folder/org principal set member is bound at project scope, the grant still applies to that bound project resource (not arbitrary resources in other projects).
- Membership is dynamic with hierarchy changes. If a project moves into or out of a folder or organization, the service accounts included by that principal set change as well.
Reference: Google Cloud principal identifiers
OpenGraph also expands cached IAM Workload Identity Federation resources into explicit nodes:
project
-> EXISTS_IN_PROJECT
-> workload identity pool
project
-> EXISTS_IN_PROJECT
-> workload identity provider
workload identity provider
-> WIF_PROVIDER_IN_POOL
-> workload identity pool
Interpretation note:
- This first-pass model is inventory/topology only.
- It shows that a provider exists and which pool it belongs to.
- It does not yet imply that any external identity can actually federate or that any service account impersonation path exists.
OpenGraph also enriches workload identity pool principals seen in IAM bindings:
principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/subject/<SUBJECT>principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/group/<GROUP_ID>principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/attribute.<ATTRIBUTE_NAME>/<ATTRIBUTE_VALUE>principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<POOL_ID>/*principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID>.svc.id.goog/kubernetes.serviceaccount.uid/<SERVICEACCOUNT_UID>principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID>.svc.id.goog/namespace/<NAMESPACE>principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID>.svc.id.goog/kubernetes.cluster/https://container.googleapis.com/v1/projects/<PROJECT_ID>/locations/<LOCATION>/clusters/<CLUSTER_NAME>- Legacy GKE format:
serviceAccount:<PROJECT_ID>.svc.id.goog[<NAMESPACE>/<KSA>]
Graph shape:
principal://... or principalSet://...
-> WIF_PRINCIPAL_IN_POOL
-> workload identity pool
Provider nodes are also enriched with configuration metadata such as:
provider_source_kindprovider_typeissuer_uriallowed_audiencesattribute_mappingattribute_conditionhas_attribute_condition
Currently recognized provider_source_kind values in the graph:
githubgitlabterraformawsazuresamloidcunknown
For providers that have no attribute condition, OpenGraph emits a broad-trust external-source warning node:
GitHubNoCondition / GitLabNoCondition / AWSNoCondition / ProviderNoCondition
-> GCP_FEDERATION_POSSIBLE
-> workload identity provider
Selector interpretation note:
-
subject,group, andattribute.NAMEselectors are only fully satisfiable when at least one provider in the pool maps the corresponding value. - For GKE-managed pools (
<PROJECT_ID>.svc.id.goog), GKE selector kinds are treated as natively supported (kubernetes.serviceaccount.name,kubernetes.serviceaccount.uid,kubernetes.namespace,kubernetes.cluster) even when external-provider mappings are not present. - OpenGraph records whether the selector appears supported by the currently discovered provider mappings with properties such as:
wif_selector_supportedwif_selector_support_statuswif_selector_support_reasonwif_supporting_provider_names
Practical provider-classification note:
- GitHub detection is based on the GitHub Actions OIDC issuer.
- GitLab detection is based on GitLab OIDC issuer strings.
- Terraform detection is based on Terraform Cloud issuer strings.
- Azure detection is based on Microsoft Entra / Azure AD issuer strings.
- Other OIDC providers fall back to
oidc. - Providers that do not match the current heuristics fall back to
unknown.
These edge kinds come from gcpwn/mappings/og_privilege_escalation_paths.json.
CAN_MODIFY_PROJECT_IAMCAN_MODIFY_FOLDER_IAMCAN_MODIFY_ORG_IAMCAN_MODIFY_SA_IAMCAN_MODIFY_COMPUTE_INSTANCE_IAMCAN_MODIFY_ClOUD_RUN_FUNCTION_IAMCAN_MODIFY_SECRET_MANAGER_SECRET_IAMCAN_IMPERSONATE_SACAN_CREATE_SA_ACCESS_TOKENCAN_CREATE_SA_KEYCAN_READ_SECRET_DATA
RESET_COMPUTE_STARTUP_SASTART_COMPUTE_STARTUP_SACREATE_AND_INVOKE_CLOUDFUNCTION_AS_SAUPDATE_AND_INVOKE_CLOUDFUNCTION_AS_SACREATE_CLOUDSCHEDULER_JOB_AS_SA-
CAN_RESET_COMPUTE_WITH_STARTUP_SCRIPT(hop edge used inside combo path) -
CAN_START_COMPUTE_WITH_STARTUP_SCRIPT(hop edge used inside combo path) -
CAN_CREATE_DEPLOY_INVOKE_CLOUDFUNCTION(hop edge used inside combo path) -
CAN_UPDATE_DEPLOY_INVOKE_CLOUDFUNCTION(hop edge used inside combo path) -
CAN_CREATE_CLOUDSCHEDULER_JOB(hop edge used inside combo path)
For rule definitions and customization workflow, see OpenGraph - Add Your Own Content.
Because some edge kinds are rule-driven and some node types are data-driven, the exact set can vary by environment and flags.
Use SQL to enumerate what your current workspace actually emitted:
data sql --db service "SELECT DISTINCT node_type FROM opengraph_nodes ORDER BY node_type;"
data sql --db service "SELECT DISTINCT edge_type FROM opengraph_edges ORDER BY edge_type;"- 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