Skip to main content
Requires Enterprise plan. Contact sales for access.
Ona environments can authenticate to HashiCorp Vault using the JWT auth method. The Ona CLI generates a JWT token that Vault validates against Ona’s OIDC discovery endpoint, then issues a Vault token with the policies you configure. No static Vault tokens or AppRole credentials are needed.

Prerequisites

Step 1: Enable the JWT auth method

Enable the JWT auth method in Vault and configure it to trust Ona’s OIDC endpoint:
vault auth enable jwt

vault write auth/jwt/config \
  oidc_discovery_url="https://app.gitpod.io" \
  default_role="ona-environment"
This tells Vault to fetch Ona’s signing keys from https://app.gitpod.io/.well-known/jwks.json and validate tokens against them.

Step 2: Create a Vault role

Create a role that defines which Ona tokens are accepted and what Vault policies they receive.

Organization-scoped role

Allow any environment in a specific Ona organization:
vault write auth/jwt/role/ona-environment \
  role_type="jwt" \
  bound_audiences="vault.hashicorp.com" \
  bound_claims='{"organization_id": "<ONA_ORG_ID>"}' \
  user_claim="sub" \
  token_policies="ona-read" \
  token_ttl="1h" \
  token_max_ttl="4h"

Project-scoped role

Restrict to environments from a specific project:
vault write auth/jwt/role/ona-project \
  role_type="jwt" \
  bound_audiences="vault.hashicorp.com" \
  bound_claims='{"organization_id": "<ONA_ORG_ID>", "project_id": "<ONA_PROJECT_ID>"}' \
  user_claim="sub" \
  token_policies="ona-read" \
  token_ttl="1h" \
  token_max_ttl="4h"

User-scoped role

Restrict to a specific user by email:
vault write auth/jwt/role/ona-dev \
  role_type="jwt" \
  bound_audiences="vault.hashicorp.com" \
  bound_claims='{"organization_id": "<ONA_ORG_ID>", "email": "dev@example.com"}' \
  user_claim="email" \
  token_policies="dev-secrets" \
  token_ttl="1h" \
  token_max_ttl="4h"

Role parameters

ParameterDescription
bound_audiencesMust match the --audience used in ona idp token. Default: vault.hashicorp.com
bound_claimsJSON object of claim-value pairs. All must match for authentication to succeed. Uses V3 flat claims.
user_claimThe token claim to use as the Vault identity alias. Common choices: sub, email, user_id
token_policiesVault policies to attach to the issued token
token_ttlInitial TTL of the Vault token
token_max_ttlMaximum TTL the token can be renewed to

Available V3 claims for bound_claims

You can bind on any V3 flat claim. Common choices:
  • organization_id - restrict to an Ona organization
  • project_id - restrict to a specific project
  • environment_id - restrict to a specific environment
  • user_id - restrict to a specific user
  • email - restrict by user email
  • creator_email - restrict by who created the environment
  • runner_id - restrict to environments on a specific runner
  • service_account_id - restrict to a specific service account

Step 3: Create a Vault policy

Create a policy that grants the access your environments need:
vault policy write ona-read - <<EOF
path "secret/data/my-app/*" {
  capabilities = ["read"]
}

path "secret/data/shared/*" {
  capabilities = ["read", "list"]
}
EOF

Step 4: Authenticate from an environment

Using the CLI shortcut

The Ona CLI has built-in Vault login support:
ona idp login vault --role ona-environment
This runs vault write auth/jwt/login under the hood and calls vault login with the resulting token. Options:
  • --role - the Vault role to authenticate against (defaults to IDP_VAULT_ROLE env var)
  • --audience - the token audience (default: vault.hashicorp.com)

Manual flow

If you need more control, use the Vault CLI directly:
TOKEN=$(ona idp token --audience vault.hashicorp.com)
vault write -format=json auth/jwt/login role=ona-environment jwt="$TOKEN"
Or as a one-liner that also logs in:
vault login -method=jwt role=ona-environment jwt="$(ona idp token --audience vault.hashicorp.com)"

Automate on environment startup

Add the login to your automations:
# automations.yaml
tasks:
  vault-login:
    name: Vault Login
    command: |
      ona idp login vault --role ona-environment
    triggeredBy:
      - postDevcontainerStart
After authentication, read secrets normally:
vault kv get secret/my-app/database

Using the Vault SDK

For programmatic access in your application:
import (
    vault "github.com/hashicorp/vault/api"
    "os/exec"
)

func vaultClient() (*vault.Client, error) {
    client, err := vault.NewClient(vault.DefaultConfig())
    if err != nil {
        return nil, err
    }

    // Get Ona OIDC token
    out, err := exec.Command("ona", "idp", "token",
        "--audience", "vault.hashicorp.com").Output()
    if err != nil {
        return nil, err
    }

    // Authenticate with Vault
    secret, err := client.Logical().Write("auth/jwt/login", map[string]interface{}{
        "role": "ona-environment",
        "jwt":  string(out),
    })
    if err != nil {
        return nil, err
    }

    client.SetToken(secret.Auth.ClientToken)
    return client, nil
}

Using V2 tokens with Vault

V2 tokens also work with Vault’s JWT auth method. V2 tokens include org and gsub claims instead of the flat V3 claims. Use bound_claims on org for organization-scoped access:
vault write auth/jwt/role/ona-v2 \
  role_type="jwt" \
  bound_audiences="vault.hashicorp.com" \
  bound_claims='{"org": "<ONA_ORG_ID>"}' \
  user_claim="sub" \
  token_policies="ona-read" \
  token_ttl="1h"
V2 tokens do not include email, project_id, or other flat claims, so fine-grained access control is limited to matching the sub claim. See the OIDC overview V2 section for the full V2 token reference.

Troubleshooting

“error validating token: invalid audience claim”
  • The bound_audiences in the Vault role must match the --audience used in ona idp token.
  • Default audience for Vault: vault.hashicorp.com.
“error validating token: claim ‘organization_id’ does not match”
  • The bound_claims values must exactly match the claims in your Ona token.
  • Decode your token: ona idp token --audience vault.hashicorp.com --decode
  • Verify the claim values match what you configured in the Vault role.
“error fetching keys from OIDC provider”
  • Vault cannot reach https://app.gitpod.io/.well-known/openid-configuration.
  • Verify network connectivity from your Vault server to app.gitpod.io.
“permission denied” when reading secrets
  • The Vault token was issued, but the attached policies do not grant access to the requested path.
  • Check the token_policies on the Vault role and the policy definitions.

Further reading