> ## Documentation Index
> Fetch the complete documentation index at: https://ona.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# GCP OIDC Integration

> Access Google Cloud resources from Ona environments using Workload Identity Federation, without service account keys.

<Note>Available on the Enterprise plan. [Contact sales](https://ona.com/contact/sales) to learn more.</Note>

Ona environments can access Google Cloud resources using [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation). You create a workload identity pool with an OIDC provider that trusts Ona's tokens, then grant the federated identity access to GCP resources. No service account keys are needed.

## Prerequisites

* Enable V3 tokens on the [OIDC Token Configuration](https://app.gitpod.io/settings/security/oidc) page in your organization settings. See [Enable V3 tokens](/ona/configuration/oidc#enable-v3-tokens).
* Google Cloud CLI (`gcloud`) installed in your environment.

## How it works

1. Ona issues a JWT with claims about the environment, user, and organization.
2. The environment sends the JWT to Google's Security Token Service (STS).
3. STS validates the token against Ona's OIDC discovery endpoint and returns a federated access token.
4. The environment uses the federated token to access GCP resources directly, or impersonates a service account for broader access.

## Step 1: Create a workload identity pool

Create a [workload identity pool](https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers) to manage Ona's federated identities:

```bash theme={null}
gcloud iam workload-identity-pools create ona-pool \
  --location="global" \
  --display-name="Ona Environments" \
  --project=<PROJECT_ID>
```

## Step 2: Create an OIDC provider

Add an OIDC provider to the pool that trusts Ona's tokens:

```bash theme={null}
gcloud iam workload-identity-pools providers create-oidc ona-provider \
  --location="global" \
  --workload-identity-pool="ona-pool" \
  --issuer-uri="https://app.gitpod.io" \
  --allowed-audiences="https://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/providers/ona-provider" \
  --attribute-mapping="google.subject=assertion.sub,attribute.organization_id=assertion.organization_id,attribute.environment_id=assertion.environment_id,attribute.project_id=assertion.project_id" \
  --attribute-condition="assertion.organization_id == '<ONA_ORG_ID>'" \
  --project=<PROJECT_ID>
```

Key parameters:

| Parameter               | Description                                                                   |
| ----------------------- | ----------------------------------------------------------------------------- |
| `--issuer-uri`          | `https://app.gitpod.io`                                                       |
| `--allowed-audiences`   | The full provider resource name (used as the `--audience` in `ona idp token`) |
| `--attribute-mapping`   | Maps Ona token claims to GCP attributes                                       |
| `--attribute-condition` | CEL expression that restricts which tokens are accepted                       |

### Attribute mappings

Attribute mappings define how Ona token claims map to GCP identity attributes. `google.subject` is required. Additional custom attributes enable fine-grained IAM bindings.

Common mappings for V3 tokens:

```
google.subject=assertion.sub
attribute.organization_id=assertion.organization_id
attribute.environment_id=assertion.environment_id
attribute.project_id=assertion.project_id
attribute.creator_email=assertion.creator_email
attribute.email=assertion.email
```

### Attribute conditions

Attribute conditions restrict which tokens the provider accepts. Use [CEL expressions](https://cloud.google.com/iam/docs/conditions-attribute-reference) to filter on Ona claims.

**Allow only a specific Ona organization:**

```
assertion.organization_id == '<ONA_ORG_ID>'
```

**Allow only a specific project:**

```
assertion.organization_id == '<ONA_ORG_ID>' && assertion.project_id == '<ONA_PROJECT_ID>'
```

**Allow only environments created by a specific user:**

```
assertion.organization_id == '<ONA_ORG_ID>' && assertion.creator_email == 'dev@example.com'
```

<Warning>Always set an attribute condition. Without one, any valid Ona token from any organization can authenticate to your pool.</Warning>

## Step 3: Grant access to GCP resources

You can grant access using direct resource bindings or service account impersonation.

### Option A: Direct resource access

Grant the federated identity access directly on a GCP resource:

```bash theme={null}
# Allow all identities in the pool
gcloud storage buckets add-iam-policy-binding gs://<BUCKET_NAME> \
  --member="principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/*" \
  --role="roles/storage.objectViewer"
```

To restrict to a specific Ona project, use the `attribute.project_id` attribute:

```bash theme={null}
gcloud storage buckets add-iam-policy-binding gs://<BUCKET_NAME> \
  --member="principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/attribute.project_id/<ONA_PROJECT_ID>" \
  --role="roles/storage.objectViewer"
```

To restrict to a single identity (specific sub claim):

```bash theme={null}
gcloud storage buckets add-iam-policy-binding gs://<BUCKET_NAME> \
  --member="principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/subject/organization_id:<ONA_ORG_ID>:project_id:<ONA_PROJECT_ID>" \
  --role="roles/storage.objectViewer"
```

### Option B: Service account impersonation

If the GCP APIs you need do not support direct Workload Identity Federation, impersonate a service account instead.

1. Create a service account:

```bash theme={null}
gcloud iam service-accounts create ona-sa \
  --display-name="Ona Environment SA" \
  --project=<PROJECT_ID>
```

2. Grant the federated identity permission to impersonate the service account:

```bash theme={null}
gcloud iam service-accounts add-iam-policy-binding ona-sa@<PROJECT_ID>.iam.gserviceaccount.com \
  --member="principalSet://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/attribute.organization_id/<ONA_ORG_ID>" \
  --role="roles/iam.workloadIdentityUser"
```

3. Grant the service account access to the resources it needs:

```bash theme={null}
gcloud projects add-iam-policy-binding <PROJECT_ID> \
  --member="serviceAccount:ona-sa@<PROJECT_ID>.iam.gserviceaccount.com" \
  --role="roles/storage.objectViewer"
```

## Step 4: Authenticate from an environment

### Create a credential configuration file

Create a credential configuration file that tells the GCP SDK how to obtain tokens from Ona:

```bash theme={null}
gcloud iam workload-identity-pools create-cred-config \
  projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/providers/ona-provider \
  --output-file=gcp-credentials.json \
  --executable-command="ona idp token --audience https://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/providers/ona-provider" \
  --executable-timeout-millis=5000
```

For service account impersonation, add the `--service-account` flag:

```bash theme={null}
gcloud iam workload-identity-pools create-cred-config \
  projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/providers/ona-provider \
  --service-account=ona-sa@<PROJECT_ID>.iam.gserviceaccount.com \
  --output-file=gcp-credentials.json \
  --executable-command="ona idp token --audience https://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/ona-pool/providers/ona-provider" \
  --executable-timeout-millis=5000
```

### Authenticate

Set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable and enable executable-based credentials:

```bash theme={null}
export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/gcp-credentials.json
export GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES=1
```

Then use GCP tools normally:

```bash theme={null}
gcloud auth login --cred-file=gcp-credentials.json
gcloud storage ls gs://my-bucket
```

### Automate on environment startup

Add the credential setup to your [automations](/ona/configuration/tasks-and-services/overview):

```yaml theme={null}
# automations.yaml
tasks:
  gcp-login:
    name: GCP Login
    command: |
      export GOOGLE_APPLICATION_CREDENTIALS=/workspace/gcp-credentials.json
      export GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES=1
      gcloud auth login --cred-file=$GOOGLE_APPLICATION_CREDENTIALS
    triggeredBy:
      - postDevcontainerStart
```

<Note>Store the credential configuration file in your repository or generate it during environment startup. It does not contain secrets, only the configuration for how to obtain tokens.</Note>

## Using V2 tokens with GCP

V2 tokens also work with GCP Workload Identity Federation. The V2 `sub` claim uses a path-based format (e.g., `org:<orgID>/prj:<projectID>/env:<envID>`). Adjust your attribute mappings and conditions accordingly.

V2 tokens include fewer claims (`org`, `gsub`, and standard JWT fields), so attribute mappings are limited to `google.subject=assertion.sub` and conditions on `assertion.sub` or `assertion.org`. See the [OIDC overview V2 section](/ona/configuration/oidc#v2-tokens) for the full V2 sub format reference.

## Further reading

* [GCP: Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation)
* [GCP: Configure Workload Identity Federation with OIDC providers](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers)
* [GCP: Manage workload identity pools](https://cloud.google.com/iam/docs/manage-workload-identity-pools-providers)
* [Ona OIDC overview](/ona/configuration/oidc)

## Troubleshooting

<Accordion title="&#x22;The audience in the credential configuration does not match&#x22;">
  * The `--audience` in `ona idp token` must match the `--allowed-audiences` on the OIDC provider. Use the full provider resource name.
</Accordion>

<Accordion title="&#x22;The attribute condition was not met&#x22;">
  * Your token's claims do not satisfy the `--attribute-condition` CEL expression.
  * Decode your token: `ona idp token --audience <AUDIENCE> --decode`
  * Verify the `organization_id`, `project_id`, or other claims match the condition.
</Accordion>

<Accordion title="&#x22;Permission denied on resource&#x22;">
  * The federated identity or service account does not have the required IAM role on the target resource.
  * Check the `--member` format in your IAM binding. For `principalSet://`, the attribute value must match exactly.
</Accordion>

<Accordion title="&#x22;Executable returned a non-zero exit code&#x22;">
  * The `ona idp token` command failed. Verify the CLI is installed and authenticated in the environment.
  * Check that the audience value is correct.
</Accordion>
