Lightbridge Authz is a two‑API service for managing API keys with OAuth2‑secured CRUD and an Authorino/OPA validation interface. Both servers use TLS, share the same database, and share the same migrations.
- authz-api (frontend CRUD, OAuth2)
- TLS on
:3000inside the container, exposed as:13000via compose. - Public routes:
GET /andGET /health - Protected routes under
/api/v1(OAuth2 bearer token).
- TLS on
- authz-opa (Authorino, basic auth)
- TLS on
:3001inside the container, exposed as:13001via compose. POST /v1/opa/validate(basic auth).
- TLS on
- authz-migrate
- Runs SQL migrations before the API services start.
- postgresql, keycloak, adminer, authz-tls
just upVerify health:
curl -k https://localhost:13000/health
curl -k https://localhost:13001/health-k is required because the certs are self‑signed.
Default container config is mounted from .docker/authz/container.yaml:
- API TLS:
/tls/api.crt+/tls/api.key - OPA TLS:
/tls/opa.crt+/tls/opa.key - OPA basic auth:
authorino / change-me - OAuth2 JWKS:
http://keycloak:9100/realms/dev/protocol/openid-connect/certs
- Install the
charts/lightbridgeumbrella chart—the sharedglobal.configblock is rendered into a single config map (global.configMapName, defaults tolightbridge-authz-config) that bothlightbridge-apiandlightbridge-opamount at/etc/lightbridge/config.yaml. Use YAML anchors (seecharts/lightbridge/values.yaml) to keep the baselogging,database,oauth2, andserversections in sync while overriding the API/OPA ports or service-specific knobs. - The same umbrella chart also owns the TLS secret (
global.tlsSecretName, defaults tolightbridge-authz-tls) via a pre-install/pre-upgradeglobal-tlsjob. The job skips generation if the secret already exists, so reruns are safe; disable it (e.g., when cert-manager manages certs) with--set global.tls.job.enabled=false. - Every dependency still renders its own hooks locally, but the umbrella chart disables the per-service TLS job/configmap so the shared resources are reused. Each
lightbridge-authzrelease now also has a pre-install/pre-upgrademigratejob that writes the templated config to/tmp/lightbridge-config/config.yamland runslightbridge-authz migrate --config-path ..., keeping the schema ready before the servers start. - Override TLS paths, service types, image tags, etc., via the per-release
lightbridge-apiandlightbridge-opavalue blocks; for example, bumplightbridge-api.service.typetoLoadBalanceror tweaklightbridge-opa.image.tagwhile relying on the sharedglobal.config. - Validate the charts before deployment with
helm lint charts/lightbridge-authzandhelm lint charts/lightbridge. You can preview the combined output (config map, TLS secret job, migrations job, and services) withhelm template charts/lightbridge. After installing, runhelm test <release>to exercise thelightbridge-authztest pod that hits the rendered service port.
CRUD API (OAuth2, /api/v1)
- Accounts:
POST/GET /accounts,GET/PATCH/DELETE /accounts/{account_id} - Projects:
POST/GET /accounts/{account_id}/projects,GET/PATCH/DELETE /projects/{project_id} - API keys:
POST/GET /projects/{project_id}/api-keys,GET/PATCH/DELETE /api-keys/{key_id} - Lifecycle:
POST /api-keys/{key_id}/revoke,POST /api-keys/{key_id}/rotate - OpenAPI docs:
https://localhost:13000/api/v1/docs
OPA API (Basic Auth)
POST /v1/opa/validatePOST /v1/authorino/validate(supports dynamic metadata passthrough/enrichment)- OpenAPI docs:
https://localhost:13001/v1/opa/docs
Use this endpoint from Authorino’s OPA external authz policy to validate API keys; send the presented API key and optional client IP.
Example:
curl -k -u authorino:change-me \
https://localhost:13001/v1/opa/validate \
-H 'Content-Type: application/json' \
-d '{"api_key":"<plain_api_key>","ip":"203.0.113.10"}'Authorino-oriented example with metadata:
curl -k -u authorino:change-me \
https://localhost:13001/v1/authorino/validate \
-H 'Content-Type: application/json' \
-d '{"api_key":"<plain_api_key>","ip":"203.0.113.10","metadata":{"tenant":"acme"}}'Detailed usage + integration test guide:
docs/authorino-usage.md
Keycloak is preloaded with:
- Realm:
dev - User:
test@admin/test(email-as-username) - Client:
test-client(public)
- Open Keycloak admin:
http://localhost:9100
Admin user:admin/password - Realm
dev→ Clients →test-client - Enable Direct Access Grants and save.
If you see {"error":"invalid_request","error_description":"HTTPS required"}, set the realm SSL requirement to none (realm dev → Realm Settings → SSL Required), or run:
docker compose exec keycloak /opt/keycloak/bin/kcadm.sh update realms/dev -s sslRequired=noneThen fetch a token:
curl -s -X POST 'http://localhost:9100/realms/dev/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d 'client_id=test-client' \
-d 'username=test@admin' \
-d 'password=test'Use the access_token:
curl -k https://localhost:13000/api/v1/accounts \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"billing_identity":"acme","owners_admins":["test@admin"]}'If you prefer not to enable direct access grants, configure a redirect URI in Keycloak and follow the standard authorization code flow to obtain an access token.
just build
just up
just up-no-build
just logs-api
just logs-opa
just migrate