> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/openshell/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/openshell/_mcp/server.

# Google Cloud

> Authenticate with GCP APIs inside OpenShell sandboxes.

The `google-cloud` provider gives sandboxes native GCP credentials so
any Google Cloud SDK works out of the box — Cloud Storage, BigQuery, Drive,
Maps, Discovery Engine, or any other GCP API. A GCE metadata server emulator
on loopback provides credential placeholders that the
sandbox proxy resolves to real tokens at request time. The sandbox process
never holds a real GCP credential.

## Quick Start

If you already have `gcloud` configured with Application Default Credentials,
create a provider with automatic credential refresh in one command:

```shell
openshell provider create \
  --name my-gcp \
  --type google-cloud \
  --from-gcloud-adc \
  --config project_id="$(gcloud config get-value project)" \
  --config region=global
```

`--from-gcloud-adc` reads your ADC file, configures OAuth2 refresh on the
gateway, and mints the first access token before the command returns. The
gateway rotates the token automatically — no manual refresh needed.

## Authentication Flows

Two credential flows are supported. Choose based on your environment.

### Application Default Credentials (gcloud ADC)

Use credentials from `gcloud auth application-default login`. The gateway
exchanges the refresh token for short-lived access tokens automatically.

```shell
openshell provider create \
  --name my-gcp \
  --type google-cloud \
  --config project_id=my-project \
  --config region=us-central1 \
  --credential GCP_ADC_ACCESS_TOKEN=placeholder
```

Configure credential refresh with the ADC JSON fields:

```shell
openshell provider refresh configure my-gcp \
  --credential-key GCP_ADC_ACCESS_TOKEN \
  --strategy oauth2-refresh-token \
  --material client_id=YOUR_CLIENT_ID \
  --material client_secret=YOUR_CLIENT_SECRET \
  --material refresh_token=YOUR_REFRESH_TOKEN \
  --secret-material-key client_secret \
  --secret-material-key refresh_token
```

Find these values in your ADC file at
`~/.config/gcloud/application_default_credentials.json`.

Trigger the first token mint:

```shell
openshell provider refresh rotate my-gcp \
  --credential-key GCP_ADC_ACCESS_TOKEN
```

### Service Account Key

Use a GCP service account JSON key file. The gateway signs JWTs and
exchanges them for access tokens using the `google-service-account-jwt`
strategy.

```shell
openshell provider create \
  --name my-gcp \
  --type google-cloud \
  --config project_id=my-project \
  --config region=us-central1 \
  --credential GCP_SA_ACCESS_TOKEN=placeholder
```

```shell
openshell provider refresh configure my-gcp \
  --credential-key GCP_SA_ACCESS_TOKEN \
  --strategy google-service-account-jwt \
  --material client_email=sa@my-project.iam.gserviceaccount.com \
  --material private_key="$(jq -r .private_key /path/to/sa-key.json)" \
  --secret-material-key private_key
```

```shell
openshell provider refresh rotate my-gcp \
  --credential-key GCP_SA_ACCESS_TOKEN
```

## Configuration Keys

Set these with `--config key=value` during provider creation:

| Key                     | Description                    | Example                           |
| ----------------------- | ------------------------------ | --------------------------------- |
| `project_id`            | GCP project ID                 | `my-project-123`                  |
| `region`                | GCP region                     | `us-central1`                     |
| `service_account_email` | SA email for metadata endpoint | `sa@proj.iam.gserviceaccount.com` |

## How It Works

When a sandbox starts with the `google-cloud` provider attached:

1. The gateway mints a fresh GCP access token and stores it in the
   sandbox proxy's credential resolver.
2. A loopback HTTP server on `127.0.0.1:8174` emulates the GCE instance
   metadata API, serving **credential placeholders** (not real tokens) to
   GCP SDKs. The sandbox process never holds a real GCP credential.
3. When the SDK makes an API call, it sends the placeholder in the
   `Authorization` header. The sandbox proxy TLS-terminates the
   outbound connection, resolves the placeholder to the real token,
   and forwards the request to GCP.
4. When the token approaches expiry, the gateway refreshes it. The
   proxy's resolver is updated atomically — subsequent API calls
   use the new token automatically.

Configuration values (`project_id`, `region`, `service_account_email`)
are **visible in plain text** inside the sandbox — they appear as
environment variables and are served by the metadata endpoint. These are
non-secret identifiers, not credentials. Access tokens are never exposed;
only placeholders reach the sandbox process.

### Injected Environment Variables

The provider automatically injects these into the sandbox. Non-secret
vars are resolved to real values at process spawn time; token vars stay
as placeholders for proxy-time resolution.

| Variable                    | Value                    | Purpose                                      |
| --------------------------- | ------------------------ | -------------------------------------------- |
| `GCE_METADATA_HOST`         | `127.0.0.1:8174`         | GCP SDK metadata discovery (loopback server) |
| `GCE_METADATA_IP`           | `127.0.0.1:8174`         | Python google-auth ping detection            |
| `METADATA_SERVER_DETECTION` | `assume-present`         | Node.js gcp-metadata skip detection          |
| `GCP_PROJECT_ID`            | from `project_id` config | GCP SDK project                              |
| `GOOGLE_CLOUD_PROJECT`      | from `project_id` config | Alternative project var                      |
| `CLOUD_ML_REGION`           | from `region` config     | GCP region                                   |
| `GCP_LOCATION`              | from `region` config     | Alternative region var                       |

## Using with GCP APIs

The metadata emulator serves tokens with the `cloud-platform` OAuth2 scope,
which grants access to any GCP API the underlying service account has IAM
permissions for. Add the target API hosts to your sandbox network policy:

```yaml
network_policies:
  gcp_apis:
    name: gcp-apis
    endpoints:
      - host: "*.googleapis.com"
        port: 443
        protocol: rest
        access: read-write
        enforcement: enforce
    binaries:
      - { path: /usr/bin/curl }
      - { path: /usr/bin/node }
      - { path: "/sandbox/.uv/python/**" }
      - { path: "/sandbox/.venv/**" }
```

Or update a live sandbox directly:

```shell
openshell policy update my-sandbox \
  --add-endpoint "*.googleapis.com:443:read-write:rest:enforce" \
  --binary "/usr/bin/curl" \
  --binary "/usr/bin/node" \
  --binary "/sandbox/.uv/python/**" \
  --binary "/sandbox/.venv/**" \
  --wait
```

## Network Policy

The `google-cloud` provider type does not include any network policy
endpoints by default. You must add endpoint rules to your sandbox policy
for each GCP API the sandbox needs to reach. See "Using with GCP APIs"
above for an example.