Skip to main content
← Back to list
01Issue
BugShippedExtensions
Assigneesstack72

#401 cloudidentity API calls fail with 'requires a quota project' — bundle doesn't send x-goog-user-project header

Opened by thescarletmanuka · 5/21/2026· Shipped 5/21/2026

Summary

The auto-generated @swamp/gcp/cloudidentity models can't make API calls because the bundled HTTP request() doesn't send the x-goog-user-project header. The Cloud Identity API explicitly requires this header when authenticating via Application Default Credentials.

This blocks any swamp-driven management of Cloud Identity resources — groups, group memberships, policies (incl. Google Cloud session-control settings).

Affected

  • @swamp/gcp/[email protected] (and likely earlier)
  • All models in the extension that hit the API: groups, groups-memberships, policies, inboundsamlssoprofiles, etc.

Reproduction

swamp extension pull @swamp/gcp/cloudidentity
swamp model create @swamp/gcp/cloudidentity/groups my-group
# Edit YAML: set name=groups/<id>, groupKey.id=<email>, parent=customers/<id>, etc.
swamp model method run my-group get --input identifier=groups/<id>

Result:

{
  "error": "Read failed (403): { \"error\": { \"code\": 403, \"message\": \"Your application is authenticating by using local Application Default Credentials. The cloudidentity.googleapis.com API requires a quota project, which is not set by default. ... \", \"status\": \"PERMISSION_DENIED\" } }"
}

Workarounds tried

  • gcloud auth application-default set-quota-project <project>: does NOT propagate, because the bundle's auth path re-fetches the access token via gcloud auth application-default print-access-token, which returns just a token without the quota-project metadata.
  • Setting GCP_PROJECT env var: doesn't trigger the header to be sent either; the bundle uses it for URL substitution but not for the quota-project header.

For comparison, gcloud identity groups … accepts a --billing-project=<project> flag and threads it through as the quota project. The swamp model has no equivalent.

Why this matters

Two ongoing infra-bootstrap workstreams need Cloud Identity automation:

  1. Enforce baseline state of a security group ([email protected]) via swamp model … update — driftless assertion of labels + properties.
  2. Automate the Google Cloud session-control setting (1-hour session length with password reauth on root OU), which is configured as a policies resource via this same extension.

Both are currently click-driven through admin.google.com because the extension's models can't reach the API.

Proposed fix

In _lib/gcp.ts's request() function (or just for cloudidentity-specific calls):

  • Send x-goog-user-project: <quota-project> when the API host is cloudidentity.googleapis.com (or always, when a quota project is determinable).
  • Quota project sources, in order: a new --billing-project model global arg; GCP_BILLING_PROJECT env var (or the existing GCP_PROJECT); the gcloud config's billing/quota_project or core/project value.
  • For the gcloud auth application-default path, the SDK has been adding the x-goog-user-project header on its own when configured via set-quota-project; the swamp bundle bypasses that by using print-access-token. Either thread the quota project through or use the SDK client libraries directly.

Environment

Upstream repository: https://github.com/systeminit/swamp-extensions

Environment

  • Extension: @swamp/gcp/[email protected]
  • swamp: 20260521.121912.0-sha.f98578f3
  • OS: linux (x86_64)
  • Deno: 2.7.14+19bd3d8
  • Shell: /bin/bash
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 3 MOREPR_MERGEDCOMPLETE

Shipped

5/21/2026, 10:23:57 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack725/21/2026, 5:19:06 PM

Sign in to post a ripple.