docs(secrets): interactive console runbook + 0.3.0 version bump
This commit is contained in:
@@ -16,6 +16,45 @@ plaintext back on demand — from application code, from configuration, or from
|
||||
|
||||
A `secret` CLI (`set` / `get` / `list` / `rm` / `rotate` / `rewrap-all`) ships in the repo (not packed).
|
||||
|
||||
### Interactive console
|
||||
|
||||
Run `secret` with **no arguments** in a real terminal and it opens an interactive console
|
||||
instead of printing usage — a menu-driven session for an operator sitting at a deployment,
|
||||
rather than a scripted one-shot verb. The launch condition is exact: no verb **and** neither
|
||||
stdin nor stdout is redirected. Any redirection (a pipe, `| cat`, CI, a script) falls straight
|
||||
through to the headless usage/exit-2 behavior above, so nothing scripted ever hangs on a
|
||||
prompt.
|
||||
|
||||
The first screen picks a **store target** — recent targets (persisted to
|
||||
`~/.zb-secrets/recent-targets.json`, names + paths only, never key material), an app's
|
||||
`appsettings.json` (the console composes base + `appsettings.<env>.json` + environment
|
||||
variables and binds `Secrets` exactly like the app itself, so every operation hits precisely
|
||||
the store the app reads), or manual entry (a raw SQLite path + a master-key environment
|
||||
variable name). If the configured KEK cannot be resolved in the operator's shell, the session
|
||||
still opens — **degraded**, metadata-only — and any flow that needs the key prompts for one
|
||||
(masked paste or a key file) to upgrade it in place.
|
||||
|
||||
Once a target is open, the menu offers:
|
||||
|
||||
- **List secrets** — metadata table (name, content type, KEK id, revision, updated); no KEK needed.
|
||||
- **Set / rotate a secret** — masked value prompt, seals a fresh row under the session KEK.
|
||||
- **Get (reveal) a secret** — confirm-gated; prints the plaintext once, never cached or logged.
|
||||
- **Delete a secret** — confirm-gated tombstone; no KEK needed.
|
||||
- **Reference audit & seed** — scans the target's composed configuration for `${secret:NAME}`
|
||||
tokens, classifies each Ok / Missing / Tombstoned / Undecryptable / InvalidName, and walks the
|
||||
gaps through a seed prompt. This is *the* deployment-setup flow.
|
||||
- **KEK doctor (lockout recovery)** — per-row diagnosis (Ok / WrongKek / Corrupt, with the
|
||||
foreign KEK id) plus a guided remedy: rewrap every row from an old KEK, or re-set individual
|
||||
rows when the old KEK is unrecoverable.
|
||||
- **Export bundle (ciphertext-only)** / **Import bundle** — move rows between stores. Bundles
|
||||
carry name + metadata + wrapped DEK + ciphertext, never plaintext; importing across KEKs
|
||||
verifies the pasted source key against the bundle's KEK id before re-wrapping, conflicts
|
||||
resolve last-writer-wins (with an optional per-row prompt), and the format is versioned.
|
||||
|
||||
There is no login — the console runs locally with direct file/DB access, the same trust model
|
||||
as any other admin CLI. See the operator runbook for the full walkthrough:
|
||||
[`docs/operations/interactive-console.md`](docs/operations/interactive-console.md).
|
||||
|
||||
## How it protects secrets
|
||||
|
||||
Each value is encrypted with a fresh **data key (DEK)** using AES-256-GCM; the DEK is then
|
||||
@@ -149,4 +188,6 @@ node can always reach a shared database, because you pay real distributed-system
|
||||
stays invisible to last-writer-wins. Run `rewrap-all` against **each** independent store.
|
||||
|
||||
See [`docs/operations/clustered-secrets.md`](docs/operations/clustered-secrets.md) for operator
|
||||
setup, and [`docs/operations/kek-rotation.md`](docs/operations/kek-rotation.md) for rotation.
|
||||
setup, [`docs/operations/kek-rotation.md`](docs/operations/kek-rotation.md) for rotation, and
|
||||
[`docs/operations/interactive-console.md`](docs/operations/interactive-console.md) for the
|
||||
`secret` interactive console (deployment seeding, lockout recovery, bundles).
|
||||
|
||||
Reference in New Issue
Block a user