Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt

Use this file to discover all available pages before exploring further.

Tenant Master Key

Every KnoxCall tenant has its own master key — a 32-byte symmetric key that wraps every other piece of encrypted material the tenant owns. Secrets, database admin passwords, SSH keys, CA private keys, transit-key versions: all of it is wrapped (KCT1 envelope format) by the tenant master key. This is the load-bearing isolation primitive in KnoxCall. A bug in the control plane, a stolen backup, or a malicious insider hitting the wrong row in the database can’t leak data across tenants — every tenant’s data is wrapped with its key, and you can’t unwrap one tenant’s blob with another tenant’s key. The Vault parallel: this is your unseal key, except per-tenant rather than per-cluster, and unwrapped on demand from a configurable backing store rather than at startup.

How it’s stored

The master key isn’t stored in plaintext anywhere. It’s stored wrapped in the tenant_master_keys table, and the wrapping method is configurable per tenant. There are three:
Wrap methodWhat wraps the master keyWhere the wrapping key livesSovereignty
globalMASTER_KEY_B64 (the deployment’s env var)KnoxCall’s process envDefault — same as today, plus per-tenant isolation
operator_kmsA KMS key in KnoxCall’s cloud accountAWS / GCP / Azure (KnoxCall-operated)Strong (KMS audit, hardware-backed)
customer_kmsA KMS key in your cloud accountAWS / GCP / Azure (yours)Strongest — BYOK
See the BYOK & KMS guide for how to set up operator_kms or customer_kms. Without explicit configuration, every tenant uses global — same crypto today, plus per-tenant isolation.

How it’s used

Every per-tenant crypto operation goes through TenantMasterKeyManager. The flow:
  1. Caller wants to encrypt or decrypt something for tenant T.
  2. Manager checks its in-memory cache for T’s unwrapped master key.
  3. Cache hit → use the cached key.
  4. Cache miss → load the wrapped row, dispatch to the correct provider (global / AWS / future GCP / future Azure) to unwrap, cache for an hour.
  5. Concurrent misses for the same tenant deduplicate — N parallel requests after a cache flush trigger one unwrap, not N.
The cache TTL is 1 hour by default for global and operator_kms wrap methods; customer-tunable in [60, 3600] seconds for those methods. Exception: customer_kms (BYOK) tenants have a fixed 5-minute TTL — this is not customer-tunable, and is intentional to bound plaintext exposure if the customer revokes KMS access. Two practical implications:
  • First call after a cache miss is slow (KMS round-trip). Subsequent calls are local.
  • You can revoke KnoxCall’s KMS access mid-flight, and the next cache flush makes the tenant immediately unable to unwrap anything. The tenant goes “sealed.”

Sealed state

If unwrapping fails (KMS access denied, KMS unreachable, key disabled), the manager records tenant_kms_config.sealed_since. For customer_kms (BYOK) tenants, the 5-minute cache TTL means the tenant becomes sealed within 5 minutes of losing KMS access. While sealed:
  • New encrypts / decrypts for that tenant fail with a clear error.
  • The cache still serves any unexpired entries — the tenant doesn’t go dark instantly, only after the cache TTL.
  • The admin UI’s Key Management section shows the sealed state and the last KMS error.
The sealed state clears automatically on the next successful unwrap.

Versioning

Master keys are versioned per tenant. Each rotation creates a new row at the next version, marks the previous one retired, and sets the new one active.
  • Active — current version. New wraps use this. One per tenant.
  • Retired — older but still usable for unwrap of legacy ciphertext.
  • Revoked — explicitly destroyed. Cryptographic erasure: data wrapped by this version is permanently unreadable.

Cryptographic erasure (the kill switch)

Revoking a tenant master key version is destructive. It’s the right-to-be-forgotten primitive, and it cascades:
Revoke tenant master key v1

Every CA private key wrapped by v1 → unreadable
Every secret blob wrapped by v1   → unreadable
Every transit-key version wrapped by v1 → unreadable
Every database admin password wrapped by v1 → unreadable
The data rows stay in the database for audit, but the wrapped blobs can never be unwrapped again. Re-issuing a tenant master key won’t bring them back — fundamentally different bytes. The admin UI guards revocation with a confirm-by-typing-tenant-name dialog. The audit-log entry records who, when, and why.

What never leaves KnoxCall

These never appear in any API response:
  • The unwrapped master key bytes.
  • The wrapped blob (visible in DB rows; not exposed to API).
  • The KMS provider’s response payload.
The Key Management endpoints return metadata only — version, wrap method, KMS key reference (the ARN, not the key), sealed state, timestamps. There is no GET /admin/key-management/keys/{version}/material and there never will be.

Audit-trail markers

Audit actionWhat it means
tenant_master_key.createNew master key minted (rotation or initial provision)
tenant_master_key.kms_config_updateKMS config changed (e.g. switched from global to customer_kms_aws)
tenant_master_key.revokeCryptographic erasure of a version
tenant_master_key.cache_clearOperator forced an unwrap on next access (e.g. to verify KMS still works)
byok.kms.onboardCustomer KMS provider onboarded (BYOK)
byok.kms.rotateTenant master key rotated under BYOK config
byok.kms.unsealTenant unsealed after KMS access restored (seal itself is not logged — only sealed_since is set on the config row)

What’s shipped today

  • ✅ Per-tenant master keys for all three wrap methods (rows, manager, cache, sealed-state).
  • global wrap (the deployment-wide MASTER_KEY_B64).
  • ✅ AWS KMS provider (operator_kms_aws, customer_kms_aws).
  • ✅ GCP Cloud KMS provider (operator_kms_gcp, customer_kms_gcp) — Workload Identity Federation.
  • ✅ Azure Key Vault provider (operator_kms_azure, customer_kms_azure) — Federated Credentials.
  • ✅ Cryptographic erasure with audit trail.
  • ✅ Tenant KMS dashboard — manage BYOK config at Settings → Security → Tenant KMS.
  • ⏳ Bulk rewrap migration: when you rotate a master key, existing data stays wrapped under the retired version. A migration tool to rewrap everything to the new active version is on the roadmap (the manual escape valve is to do it via rewrap / per-resource update).

See also