Modes
You enable RBAC by setting the root key at startup:
cyborgdb.yaml
Key kinds
When RBAC is on, the service classifies everyX-API-Key request header:
If
CYBORGDB_SERVICE_ROOT_KEY is unset, authentication is disabled entirely — RBAC is strictly opt-in.
Provisioning users
A user is scoped to exactly one index, with a non-empty subset of{"read", "write"} permissions. Mint a user with the root key:
cdbk_… as api_key to their Client — they need no index key of their own (the token carries the user’s key material, and the service opens the index via that user’s wrapped DEK).
Listing and revoking users
cdbk_… token becomes useless. There is no propagation lag.
SDK-supplied indexes
Per-user keys work on both key-management paths — KMS-backed indexes (kms_name=…) and SDK-supplied indexes (index_key=…). The index KEK is needed only at mint time, to unwrap the root DEK and re-wrap it under the new user: for KMS-backed indexes the service resolves the KEK server-side, while for SDK-supplied indexes you pass it on the create_user call (index_key in the POST body). From then on the user authenticates with their cdbk_… token alone — the service opens the index via the user’s own wrapped DEK, so no index KEK is involved on their requests, on either path.
One difference remains on SDK-supplied indexes: auto-training after a user’s upsert is skipped, because the training job runs out-of-band with the index KEK and the service holds none for a provider: none index. The skip is per-caller, not per-index: a root upsert that supplies index_key still triggers auto-training on the same index. So to keep an SDK-supplied index trained under user writes, either train it explicitly with the root key (supplying index_key), upsert as root when practical, or migrate to KMS-backed (see Managing Encryption Keys → Migrating).
KMS-backed indexes stay the smoother fit for multi-tenancy: minting needs no key material in the request, and auto-training keeps working for user writes. But it is a recommendation, not a requirement.
End-to-end example
A typical operator workflow for onboarding a new tenant:1
Provision a KMS slot
Add a registry entry to your service YAML — see KMS & BYOK.Restart the service. Look for
cyborgdb.yaml
KMS registry loaded in the logs.2
Create the tenant's index (root)
3
Mint a user key for the tenant (root)
cdbk_… to the tenant out-of-band.4
Tenant uses the index
The tenant configures their SDK client with
api_key = "cdbk_…" and operates only on acme-documents. They cannot list, describe, or touch any other tenant’s index.5
Revoke when access ends
Operational notes
- Read vs write semantics.
readcoversquery,get,list_ids,describe.writecoversupsert,delete. Index lifecycle operations (create,train,delete_index) and user management are root-only — there’s no “delegated admin” permission. - KEK cache. Plaintext index KEKs live in an in-process cache for
INDEX_KEK_CACHE_TTL_SECONDS(default 60s). Revoking a user is immediate and cryptographic; revoking KMS-level access to the wrap key propagates within the cache TTL. - Restarting the service. User keys survive restart — the wrapped DEKs are persisted alongside the index envelope. The root key is read from env/YAML on every start.
See also
- Per-Index KMS & BYOK — required for per-user keys.
- Environment Variables —
CYBORGDB_SERVICE_ROOT_KEY,INDEX_KEK_CACHE_TTL_SECONDS. - REST API: Create User, List Users, Delete User.