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 CEPT hierarchy (customer / environment / product / 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 CEPT |
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 CEPT 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_cept: 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 CEPT 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 (
AuthenticateAndGetToken). - 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
- Usage & Integration: reading/writing secrets, issuing certs, JWTs, wiring Vault into an app
- HTTP API: the full endpoint surface
- Operations: bootstrap, node enrollment, rotation, audit, failure modes, and deployment (single-node, HA, vault-agent)
- End-to-End Testing: verify secrets, PKI, JWTs, and agent enrollment