Documentation menu

Getting started

Run the bridge locally with a file-based keyset, then deploy it next to Vault and Kong.

Install

brew tap bcollard/jwks-bridge
brew install --cask jwks-bridge

Or use the container image ghcr.io/bcollard/jwks-bridge, or a binary from the latest release.

Run locally

Generate a key, write it as a keyset document, and serve it with the file source. The private listener runs in plain HTTP here; that mode is for local development only.

mkdir -p keys
jwks-bridge keygen --alg RS256 --kid k1 --status active --doc > keys/default.json
printf 'local-password' > keys/password

jwks-bridge serve \
  --source file --file-dir ./keys --keysets default=default.json \
  --private-insecure-plaintext \
  --basic-user kong --basic-password-file ./keys/password
curl -s localhost:8080/.well-known/jwks.json      # public JWKS
curl -s -u kong:local-password localhost:8443/keyset  # keyset for Kong
curl -s localhost:9090/metrics | grep jwksbridge_  # Prometheus metrics

The repository ships the same setup as examples/local/run.sh.

Store the key in Vault

The bridge reads the keys field of a KV v2 secret. Write a first active key:

jwks-bridge keygen --alg RS256 --status active | jq -c '[.]' \
  | vault kv put secret/jwks-bridge/default keys=-

Vault setup covers the policy and the Kubernetes auth role.

Deploy on Kubernetes

kubectl create namespace jwks
kubectl -n jwks create secret tls jwks-bridge-tls --cert=tls.crt --key=tls.key
kubectl -n jwks create secret generic jwks-bridge-basic-auth \
  --from-literal=username=kong --from-literal=password="$(openssl rand -hex 24)"

helm install jwks-bridge oci://ghcr.io/bcollard/charts/jwks-bridge -n jwks \
  --set vault.address=https://vault.example.internal:8200 \
  --set private.tls.secretName=jwks-bridge-tls \
  --set private.basicAuth.secretName=jwks-bridge-basic-auth

The TLS certificate must be trusted by the Kong data planes. See Kubernetes and Helm.

Configure Kong

Point access_token_keyset at the private listener and route /.well-known/jwks.json to the public listener. jwt-signer in hybrid mode has the full decK file.