> For the complete documentation index, see [llms.txt](https://docs.forestall.io/fsprotect/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/fsprotect/edges/gcp/gcp_has_role.md).

# GCP\_HAS\_ROLE

## Summary

|                            |                              |
| -------------------------- | ---------------------------- |
| **FSProtect ACL Alias**    | GCP\_HAS\_ROLE               |
| **GCP Alias**              | Entity Relation (Structural) |
| **Affected Object Types**  | Roles                        |
| **Exploitation Certainty** | Certain                      |

## Description

`GCP_HAS_ROLE` is a structural edge representing that a GCP identity (user, group, or service account) holds an **IAM role binding**. It connects principals to their role assignments in the graph. A role binding is a triple of (principal, role, resource). `GCP_HAS_ROLE` captures the principal → role binding relationship.

## Identification

### gcloud CLI

```bash
# List all roles granted to a specific user at project level
PROJECT_ID="my-project"
USER_EMAIL="user@example.com"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq --arg user "user:$USER_EMAIL" '.bindings[] | select(.members[] | contains($user)) | .role'

# List all roles granted to a specific service account
SA_EMAIL="my-sa@my-project.iam.gserviceaccount.com"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq --arg sa "serviceAccount:$SA_EMAIL" '.bindings[] | select(.members[] | contains($sa)) | .role'

# List all direct bindings for a principal across org, folder, and project scope
ORG_ID=$(gcloud organizations list --format="value(name)" | head -1)
echo "=== Org level ===" && gcloud organizations get-iam-policy $ORG_ID --format=json | \
  jq --arg user "user:$USER_EMAIL" '[.bindings[] | select(.members[] | contains($user)) | .role]'
echo "=== Project level ===" && gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq --arg user "user:$USER_EMAIL" '[.bindings[] | select(.members[] | contains($user)) | .role]'
```

### GCP Console

1. Open **GCP Console** → **IAM & Admin** → **IAM**.
2. Each row in the IAM table represents a `GCP_HAS_ROLE` edge between the listed principal and the shown role.
3. Use the **Principal** filter to view all roles held by a specific identity.
4. The **Inheritance** tag indicates bindings from parent scope resources.

## Exploitation

`GCP_HAS_ROLE` is the starting point for all privilege analysis. Every attack path edge in the system is derived from role bindings surfaced by this edge.

**Key risk patterns:**

* **Over-assignment**: Identities accumulating many role bindings over time, especially after project migrations or team changes.
* **Stale bindings**: Former employees or deprecated service accounts retaining `GCP_HAS_ROLE` edges to privileged roles.
* **Cross-project service accounts**: A service account from Project A holding roles in Project B creates cross-project attack paths.
* **Conditional bindings**: GCP IAM supports conditions on bindings (e.g., time-based access). `GCP_HAS_ROLE` edges may reflect conditional bindings that are inactive outside their condition window.

## Mitigation

1. **Enforce least privilege** — remove role bindings that are no longer needed. Conduct periodic access reviews, especially after team changes or project migrations.
2. **Eliminate stale bindings** — disable or delete service accounts and user accounts that are no longer active before removing their role bindings.
3. **Scope bindings narrowly** — prefer project-level bindings over folder- or org-level to limit blast radius.
4. **Review cross-project service account assignments** — a service account from Project A holding roles in Project B creates cross-project attack paths; document and minimize these.
5. **Audit conditional bindings** — verify that time-based or condition-based bindings are still appropriate and tightly scoped.

## Detection

| Log Type       | Method         | Key Fields                              |
| -------------- | -------------- | --------------------------------------- |
| Admin Activity | `SetIamPolicy` | New role binding added to any principal |

```bash
gcloud logging read \
  'protoPayload.methodName="SetIamPolicy"' \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.serviceData.policyDelta.bindingDeltas)"
```

Alert on:

* New privileged role bindings (`roles/owner`, `roles/editor`, admin roles) added to any identity.
* Role bindings added at org or folder scope — these carry the highest blast radius.
* Bindings added to external identities (Gmail accounts, federated identities outside the org domain).

## References

* <https://cloud.google.com/iam/docs/overview>
* <https://cloud.google.com/iam/docs/policies>
* <https://cloud.google.com/iam/docs/conditions-overview>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestall.io/fsprotect/edges/gcp/gcp_has_role.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
