HashiCorp Vault

This integration guide is for configuring Vault to trust workload identity that has already been published through oidc.pub. Vault uses the JWT auth method to validate the external issuer's discovery document and JWKS, then exchanges a verified workload JWT for a Vault token.

If the issuer is still private, start with the relevant setup guide first, such as Vault, GitLab CI, or Kubernetes.

Vault: JWT/OIDC auth method

1. Enable the JWT auth method

Mount Vault's JWT auth method if you do not already have one. Each auth mount can trust one verification configuration, so if you want to trust multiple oidc.pub issuers, mount separate JWT backends at different paths.

vault auth enable jwt

2. Configure Vault to trust the oidc.pub issuer

Point the JWT auth method at the public discovery endpoint hosted on oidc.pub. Replace k8s-prod.oidc.pub with the issuer you want Vault to trust.

vault write auth/jwt/config \
  oidc_discovery_url="https://k8s-prod.oidc.pub" \
  bound_issuer="https://k8s-prod.oidc.pub" \
  oidc_client_id="" \
  oidc_client_secret=""

For direct JWT validation, Vault does not need an OIDC client ID or client secret. It only needs the discovery document and issuer binding.

3. Create a role for the trusted workload

Create a JWT role that matches the workload's expected aud and sub claims, then map successful logins to Vault policies.

vault write auth/jwt/role/k8s-workload \
  role_type="jwt" \
  user_claim="sub" \
  bound_audiences="vault" \
  bound_subject="system:serviceaccount:default:my-app" \
  policies="app-read" \
  ttl="1h"

Starting with Vault 1.17, if the incoming JWT contains an audience, the role's bound_audiences must exactly match at least one of the token's aud values.

4. Log in with the workload JWT

Pass the published workload JWT to Vault. If the token signature, issuer, audience, and subject all match, Vault returns a Vault token with the policies attached to the role.

vault write auth/jwt/login \
  role="k8s-workload" \
  jwt="$OIDC_TOKEN"

Provider-specific claim examples

The exact aud and sub values depend on the workload issuer. Match the role to the actual claims in the token you expect Vault to accept.

Kubernetes

Kubernetes projected service account tokens typically use a subject of the form system:serviceaccount:<namespace>:<name>. Set the audience in the projected token to the value Vault should trust, such as vault.

# Role example
vault write auth/jwt/role/k8s-workload \
  role_type="jwt" \
  user_claim="sub" \
  bound_audiences="vault" \
  bound_subject="system:serviceaccount:default:my-app" \
  policies="app-read"

GitLab CI

GitLab job tokens usually encode pipeline context in the subject. Restrict Vault to the exact branch, tag, or environment pattern you want to trust.

# Role example
vault write auth/jwt/role/gitlab-main \
  role_type="jwt" \
  user_claim="sub" \
  bound_audiences="https://gitlab.oidc.pub" \
  bound_subject="project_path:mygroup/myproject:ref_type:branch:ref:main" \
  policies="ci-read"

HashiCorp Vault

If another Vault cluster issues the workload identity, configure that source Vault role to mint an audience this Vault expects, then match the trusted entity identifier in bound_subject.

# Role example
vault write auth/jwt/role/external-vault \
  role_type="jwt" \
  user_claim="sub" \
  bound_audiences="vault" \
  bound_subject="vault-entity-id" \
  policies="vault-federation"

Related guides

Use the setup guides to publish the private issuer first, then return here to configure Vault as the relying system.

Relevant setup guides: Vault, GitLab CI, and Kubernetes.