> For the complete documentation index, see [llms.txt](https://docs.forestall.io/forestall/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.forestall.io/forestall/edges/gcp/gcp_parent.md).

# GCP\_PARENT

## Summary

|                            |                                                                                                                                                                                                                                             |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Forestall ACL Alias**    | GCP\_PARENT                                                                                                                                                                                                                                 |
| **GCP Alias**              | Entity Relation (Structural)                                                                                                                                                                                                                |
| **Affected Object Types**  | Organizations, Organizational Units, Folders, Projects, Users, Groups, Roles, Devices, Service Accounts, Virtual Machines, KMS Keys, Workload Identity Pools, Workforce Identity Pools, Workload Providers, Workforce Providers, Principals |
| **Exploitation Certainty** | Certain                                                                                                                                                                                                                                     |

## Description

`GCP_PARENT` is the structural edge representing **parent-to-child containment in the Google Cloud resource hierarchy and at the Google Workspace Customer root**.

The **Customer** is the Google Workspace tenancy root, identified by a Customer ID (e.g. `C0xxxxxxx`), and is linked 1:1 to the GCP Organization that roots the resource hierarchy:

```
Customer (root)
├── Organization                      ← the linked GCP resource hierarchy root
│   ├── Folder ──► Folder ──► Project
│   ├── Project                       (top-level, no folder)
│   └── Workforce Identity Pool
│       ├── Workforce Provider
│       └── Principal
├── Organizational Unit                  (top-level only)
├── Group
├── User
├── Role                                 (admin role definition)
└── Device
```

Projects are the leaf containers for the bulk of GCP resources:

```
Project
├── Service Account
├── Virtual Machine
├── KMS Key
└── Workload Identity Pool
    ├── Workload Provider
    └── Principal
```

Workforce Identity Pools similarly contain Workforce Providers and federated Principals. Because one edge type spans every tier, the **child and parent object types determine what the edge means** in a given traversal. A `GCP_PARENT` from a Folder to a Project carries IAM inheritance, while one from an Identity Pool to a Provider identifies the trust configuration contained by that pool.

**Why the edge matters for attack paths:**

IAM bindings in GCP are inherited downward. A role granted at the organization, folder, or project level applies to every resource beneath it, at any depth. `GCP_PARENT` is the chain that traversal follows to resolve that scope, so it determines the blast radius of every scoped role binding:

* An organization-scoped binding reaches every folder, project, and resource in the tenancy.
* A folder-scoped binding reaches all nested folders and projects, regardless of depth.
* A project-scoped binding reaches the service accounts, VMs, and keys inside that project. This is what makes project-level `GCP_ACT_AS_SA` fan out to every service account whose parent is that project.

For identity federation, `GCP_PARENT` also joins a Workload or Workforce Identity Pool to each Provider configured inside it. The Provider contains the issuer, audience, attribute mappings, and attribute conditions that decide which external identities the Pool trusts.

## Identification

### gcloud CLI

```bash
# --- Customer root (Workspace tenancy) ---
# (Access token should be authorized on scope: https://www.googleapis.com/auth/admin.directory.customer.readonly)
ACCESS_TOKEN="your-access-token"
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://admin.googleapis.com/admin/directory/v1/customers/my_customer" \
  | jq '{customerId: .id, customerDomain: .customerDomain}'

# --- GCP resource hierarchy ---
# Top-level folders (direct children of the org)
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
gcloud resource-manager folders list --organization=$ORG_ID \
  --format="table(name, displayName, createTime)"

# Top-level projects (directly under the org, in no folder)
gcloud projects list \
  --filter="parent.type=organization AND parent.id=$(echo $ORG_ID | cut -d/ -f2)" \
  --format="table(projectId, name, projectNumber)"

# Subfolders and projects of a folder
FOLDER_ID="123456789"
gcloud resource-manager folders list --folder=$FOLDER_ID \
  --format="table(name, displayName)"
gcloud projects list --filter="parent.id=$FOLDER_ID" \
  --format="table(projectId, name, projectNumber)"

# --- Resources inside a project ---
PROJECT_ID="my-project"
gcloud iam service-accounts list --project=$PROJECT_ID \
  --format="table(name, email, disabled)"
gcloud compute instances list --project=$PROJECT_ID \
  --format="table(name, zone, status, serviceAccounts[0].email)"

# Full resource inventory for a project (all child object types at once)
gcloud asset search-all-resources \
  --scope=projects/$PROJECT_ID \
  --format="table(name, assetType, location)"

# --- Workspace Customer-root children ---
# Top-level OUs
# (Access token should be authorized on scope: https://www.googleapis.com/auth/admin.directory.orgunit.readonly)
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://admin.googleapis.com/admin/directory/v1/customer/my_customer/orgunits?type=children" \
  | jq '.organizationUnits[] | {name: .name, path: .orgUnitPath}'

# Customer-scoped Users
# (Access token should be authorized on scope: https://www.googleapis.com/auth/admin.directory.user.readonly)
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://admin.googleapis.com/admin/directory/v1/users?customer=my_customer&maxResults=500" \
  | jq '.users[] | {email: .primaryEmail, isAdmin: .isAdmin}'

# --- Identity Pool children ---
# Workload Providers contained in a Workload Identity Pool
POOL_ID="my-workload-pool"
gcloud iam workload-identity-pools providers list \
  --workload-identity-pool=$POOL_ID --location=global --project=$PROJECT_ID \
  --format="table(name, state, oidc.issuerUri, aws.accountId, attributeCondition)"

# Workforce Providers contained in a Workforce Identity Pool
WORKFORCE_POOL_ID="my-workforce-pool"
gcloud iam workforce-pools providers list \
  --workforce-pool=$WORKFORCE_POOL_ID --location=global \
  --format="table(name, state, oidc.issuerUri, attributeCondition)"
```

### GCP Console

1. **GCP hierarchy**: Open **GCP Console** → **IAM & Admin** → **Manage Resources**. The tree renders the `GCP_PARENT` chain directly — the Organization is the root, and each folder or project is drawn beneath its parent.
2. **Project contents**: Select a project from the project picker. The project has a `GCP_PARENT` edge to each resource it contains — **IAM & Admin** → **Service Accounts**, **Compute Engine** → **VM Instances**, **Security** → **Secret Manager**, and so on.
3. **Workspace Customer root**: Open **Google Admin Console** (`admin.google.com`) → **Directory** → **Organizational units** for top-level OUs, and **Directory** → **Users** / **Groups** for Customer-scoped objects.
4. **Identity federation**: Open **IAM & Admin** → **Workload Identity Federation** or **Workforce Identity Federation**. Expand a Pool to see the Providers connected to it by `GCP_PARENT`.
5. **Inherited IAM**: On any project's IAM page, enable **Include Google-provided role grants** and review the **Inheritance** column — it names the ancestor the binding was granted on, which is the `GCP_PARENT` chain resolved by GCP itself.

## Exploitation

`GCP_PARENT` has no direct exploit — it is a structural edge. Its value to an attacker is as a **reachability and blast-radius map**, and each tier it spans carries a distinct consequence:

* **Organization** — any binding at org scope reaches every resource in the tenancy. Roles such as `roles/resourcemanager.organizationAdmin` and `roles/iam.securityAdmin` create [`GCP_SET_ORG_IAMPOLICY`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_set_org_iampolicy) against the org node, which is full control of the organization.
* **Folder** — a folder-level binding applies to every nested folder and project without a separate grant on each. An attacker holding [`GCP_SET_FOLDER_IAMPOLICY`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_set_folder_iampolicy) controls all child projects at once. Where prod and non-prod share a folder with inherited admin bindings, a staging compromise pivots to production through that shared scope.
* **Project** — the project is the primary blast radius for lateral movement. An identity with project-scoped `roles/iam.serviceAccountUser` gains [`GCP_ACT_AS_SA`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_act_as_sa) against every service account whose parent is that project, and project-scoped compute roles reach every VM in it.
* **Customer root** — Customer-scoped Users, Groups, Roles, Devices, and top-level OUs reveal the Workspace identity surface connected to the GCP Organization. OU membership and policy inheritance are traversed separately through [`GCP_IN_OU`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_in_ou).
* **Identity Pool** — Providers and federated Principals hang off Workforce and Workload Identity Pools. The Provider's issuer and attribute conditions determine who can cross the trust boundary, so enumerating Pool children reveals both existing federation paths and malicious Providers planted through [`GCP_CREATE_WIF_POOL`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_create_wif_pool). This is the precondition for [`GCP_FEDERATE_IDENTITY`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_federate_identity).

Two structural observations are worth recording during assessment:

* **Cross-boundary service accounts.** A service account's parent project is not the same as where it holds roles. An SA parented in Project A can hold bindings in Project B, so `GCP_PARENT` combined with [`GCP_HAS_ROLE`](https://docs.forestall.io/fsprotect/edges/gcp/gcp_has_role) exposes cross-project risk that neither edge shows on its own.
* **Hierarchy sprawl.** Many projects parented directly to the organization rather than to folders indicates weak governance and makes consistent folder-level controls impossible to apply.

## Mitigation

1. **Grant roles at the narrowest scope that works.** Prefer project-level bindings over folder-level, and folder-level over organization-level. Every tier upward multiplies the number of resources the binding reaches through `GCP_PARENT`.
2. **Minimize organization-level bindings.** Restrict `roles/resourcemanager.organizationAdmin`, `roles/iam.securityAdmin`, and `roles/owner` at org scope to break-glass accounts with just-in-time activation.
3. **Separate environments by folder.** Keep production and non-production in different folders and never share high-privilege bindings between them.
4. **Do not co-locate high-privilege service accounts with general workloads.** Place org-admin and CI/CD service accounts in dedicated admin projects, so a workload project compromise does not expose them.
5. **Organize projects into folders.** Projects parented directly to the organization cannot be governed with folder-level controls; move them under appropriately scoped folders.
6. **Minimize Super Admin assignments.** Super Admin is always Customer-scoped. Limit it to two or three break-glass accounts with hardware security keys and no day-to-day use.
7. **Audit every Pool's Providers.** Require narrowly scoped attribute conditions and alert on unknown issuers or Providers added to existing Pools.
8. **Bind specific federated subjects instead of whole Pools.** Avoid broad pool-wide bindings when a Provider attribute can identify the intended repository, account, tenant, or group.
9. **Audit the hierarchy for inherited bindings regularly.** Review folder- and org-level grants on a schedule, since these carry the largest blast radius of any assignment.

## Detection

| Log Type             | Method                                     | Key Fields                                                                         |
| -------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- |
| Admin Activity       | `SetIamPolicy`                             | Binding added at org, folder, or project scope — note `resource.type` for the tier |
| Admin Activity       | `CreateFolder` `MoveFolder` `DeleteFolder` | Folder structure changes that alter inheritance scope                              |
| Admin Activity       | `CreateProject` `MoveProject`              | Project created or reparented under a new container                                |
| Admin Activity       | `CreateServiceAccount`                     | New service account parented to a project                                          |
| Admin Activity       | `*compute.instances.insert`                | New VM parented to a project                                                       |
| Admin Activity (GWS) | `CREATE_ORG_UNIT` `MOVE_ORG_UNIT`          | Top-level OU created or moved to or from the Customer root                         |
| Admin Activity       | `CreateWorkloadIdentityPoolProvider`       | Workload Provider added beneath a Pool                                             |
| Admin Activity       | `CreateWorkforcePoolProvider`              | Workforce Provider added beneath a Pool                                            |

```bash
# Organization-scoped IAM changes (highest blast radius)
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
gcloud logging read \
  'protoPayload.methodName="SetIamPolicy" AND resource.type="organization"' \
  --organization=$ORG_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.serviceData.policyDelta)"

# Folder-scoped IAM changes and hierarchy moves
gcloud logging read \
  'protoPayload.methodName=~"SetIamPolicy|CreateFolder|MoveFolder|DeleteFolder|MoveProject"' \
  --organization=$ORG_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.methodName, protoPayload.resourceName)"

# New children appearing in a project
PROJECT_ID="my-project"
gcloud logging read \
  'protoPayload.methodName="google.iam.admin.v1.CreateServiceAccount" OR protoPayload.methodName=~"compute.instances.insert"' \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.resourceName)"

# Workload Pool/Provider containment changes
gcloud logging read \
  'log_id("cloudaudit.googleapis.com/activity")
   AND protoPayload.serviceName="iam.googleapis.com"
   AND (protoPayload.methodName:"CreateWorkloadIdentityPoolProvider"
        OR protoPayload.methodName:"DeleteWorkloadIdentityPoolProvider")' \
  --project=$PROJECT_ID --freshness=400d --limit=1000 \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.methodName, protoPayload.resourceName)"
```

Alert on:

* Privileged roles (`roles/owner`, `roles/editor`, org and folder admin roles) added at organization or folder scope by non-infrastructure accounts.
* Projects or folders moved so that they inherit broader bindings than before.
* New projects parented directly to the organization instead of a folder.
* Service accounts or VMs created in sensitive projects, particularly VMs with high-privilege service accounts attached.
* New top-level OUs created under the Customer root.
* Providers created beneath existing Pools, especially with an unknown issuer or an overly broad or missing `attributeCondition`.

## References

* <https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy>
* <https://cloud.google.com/iam/docs/resource-hierarchy-access-control>
* <https://cloud.google.com/resource-manager/docs/creating-managing-folders>
* <https://cloud.google.com/iam/docs/service-account-overview>
* <https://developers.google.com/admin-sdk/directory/reference/rest/v1/orgunits>
* <https://cloud.google.com/resource-manager/docs/organization-policy/overview>
* <https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers>
* <https://cloud.google.com/iam/docs/manage-workforce-identity-pools-providers>
