Vault Overview
kis Vault (vault.svc) is the platform’s trust plane. It is one service with three pillars:
- Secrets engine — tenant-scoped, encrypted-at-rest, audit-logged secret CRUD.
- Zero-trust mTLS PKI — issuance, rotation, and revocation of short-lived X.509 service identities from the internal certificate authority (authority
kisai), plus storage of externally-issued certificates. - Service-to-service JWTs — short-lived, Vault-signed JWTs replace long-lived API keys for outbound service calls.
The division of labor with IAM: IAM issues user-facing tokens; Vault custodies keys. IAM mints access tokens from key material it pulls from Vault; Vault owns the service identity registry (SPIFFE IDs) and the signing keys.
Components
Section titled “Components”| Component | What it is |
|---|---|
vault.svc | The server. Default port :7999, metrics on 127.0.0.1:9098. |
vault-agent | Per-node daemon. Attests local workloads (process credentials, binary path/hash), caches credentials, and serves them over the Unix socket /run/vault/vault.sock. |
| Vault client (SDK) | Every platform service embeds a vault client with two transports: remote (HTTPS direct to vault.svc) or agent (via the local socket). Selected by config: vault.client.transport. |
kis vault | CLI: developer commands ride the local agent; operator commands use an mTLS operator certificate. |
Workload identity follows the SPIFFE model: every service and node gets a spiffe://kis.ai/... identity encoded in its certificate. Node certificates live 24 hours and auto-renew at half-life; service certificates default to 90 days.
Custody model
Section titled “Custody model”Two orthogonal choices decide where the sensitive material actually lives — both are pure configuration:
- Storage backend — where secret values are stored. Supported:
hcpvault(HashiCorp Vault KV-v2, the default in production),openbao(wire-compatible),azurekvandawssm(preview), andfsvault(plaintext YAML on disk — development only; the server refuses to run it withenv: prod). - Signer — what holds the CA/JWT signing keys. Supported:
inproc(key on disk, default),pkcs11(HSM),awskms,azurekv-keys,gcpkms. The private key never leaves the signer — Vault only ever asks it to sign.
There is no Shamir-style unseal of Vault itself. The root of trust is the CA material (on disk for inproc, inside the HSM/KMS for custody signers) plus the storage backend’s own unseal.
Envelope encryption
Section titled “Envelope encryption”On top of the backend’s native at-rest encryption, Vault can add a per-tenant envelope: secrets are AES-GCM-256 encrypted with a tenant-specific key before they ever reach the backend, with the secret’s identity bound in as associated data — ciphertext cannot be copied between records or tenants. It is off by default (vault.envelope.enabled); existing plaintext secrets keep working on read, and only new writes are wrapped.
Multi-tenancy and the caller-scope guard
Section titled “Multi-tenancy and the caller-scope guard”Vault is tenant-scoped along the platform’s CPET hierarchy (customer / product / environment / tenant). Secrets exist at three scopes, encoded as name prefixes when a workload asks for them:
| Prefix | Scope |
|---|---|
vault:NAME | Tenant scope — the caller’s full CPET |
vaultcluster:NAME | Cluster scope (datacenter + cluster) |
vaultkey:NAME | Global scope |
For tenant-scoped operations, the authoritative scope is always the propagated caller identity (the tenancy context on the request), never whatever CPET a request body claims. This closes the confused-deputy hole: a service cannot read another tenant’s secret by naming that tenant in its payload. Enforcement is deny-by-default (vault.enforce_caller_cpet: true) and fails closed.
Vault is also tenant-deepest by design: there are no per-user secrets. Per-user material is application-layer envelope encryption using a tenant key that is itself held in Vault.
Using Vault from a service
Section titled “Using Vault from a service”Platform services do not call the HTTP API directly — the chassis wires a vault client in at boot:
- Configuration values can reference secrets transparently: any config value of the form
vault:db-passwordis resolved through the vault client at read time, with the caller’s CPET applied.vaultcluster:andvaultkey:work the same way at their scopes. - The client API covers secrets (get/save/check/delete), service certificates (generate/retrieve), JWT material, and the mTLS→JWT exchange (
AuthenticateAndGetJWT). - Caching: minted service JWTs are cached ~58 minutes and retrieved certificates ~6 hours. Secret reads are not cached — treat every secret read as a network call, and expect no automatic retry or fallback.
- Moving a service from direct HTTPS to the node agent is a one-line, per-service, reversible config flip:
vault.client.transport: remote→agent.
Where things run
Section titled “Where things run”| Path / port | Purpose |
|---|---|
:7999 | vault.svc API listener (mTLS) |
127.0.0.1:9098 | Server metrics (OpenTelemetry/Prometheus) |
/run/vault/vault.sock | Agent workload socket |
127.0.0.1:9099 | Agent metrics |
/etc/vault/vault.yaml | Server bootstrap config |
/etc/vault/agent.yaml | Agent config |
/var/lib/vault | Agent state directory |
Continue with:
- Configuration — bootstrap file, backends, signers, access rules, agent config
- HTTP API — the full endpoint surface
- Operations — bootstrap from zero, node enrollment, rotation, audit, failure modes