docs: update auth flows for the root-token retirement (card 59)

The standing root token this doc described is retired. Replaced the
2-flow table with the real 3-flow model now in place: routine AppRole
auth, a narrowly-scoped provisioner AppRole for occasional bootstrap
work, and a break-glass generate-root path for the rare cases the
provisioner deliberately can't cover. Alerting row corrected to note
the audit-log check fires on any root-policy token generically, not
a specific standing one.
This commit is contained in:
automation-bot committed 2026-09-05 12:44:31 +03:00
1 parent bd0897a7c7
commit 19269e4d0f
1 file changed
+4 -3
+4 -3
View File
@@ -67,12 +67,13 @@ None of these ever call the Vault API themselves — every one of them goes thro
![Secret lifecycle: Vault Agent authenticates via AppRole, gets a token, renders the secret to a local file, the application reads that file and never talks to Vault directly — rotation happens asynchronously, updated once in Vault and picked up on the agent's next render](../assets/secrets-and-pki-lifecycle.svg) ![Secret lifecycle: Vault Agent authenticates via AppRole, gets a token, renders the secret to a local file, the application reads that file and never talks to Vault directly — rotation happens asynchronously, updated once in Vault and picked up on the agent's next render](../assets/secrets-and-pki-lifecycle.svg)
**Two authentication flows, not one:** **Three authentication flows, not one:**
| Flow | When | Path | | Flow | When | Path |
|---|---|---| |---|---|---|
| AppRole auth | Every host, ongoing | Vault Agent → role_id + secret_id → Vault → short-lived token, cached, auto-renewed | | AppRole auth | Every host, ongoing | Vault Agent → role_id + secret_id → Vault → short-lived token, cached, auto-renewed |
| Bootstrap auth | Rare, human-initiated | Operator uses a root token to mint new AppRole credentials or update policies — never part of any workload's runtime path | | Provisioner auth | Occasional, playbook-triggered | A narrowly-scoped AppRole mints new host AppRole credentials and reads two specific KV paths — cannot create policies or AppRole roles itself |
| Break-glass auth | Rare, human-initiated, no standing token | Operator + a quorum of unseal-key shares → a freshly-minted root token, used once, revoked immediately — the only path that can create policies or onboard a genuinely new host |
> [!IMPORTANT] > [!IMPORTANT]
> **The one deliberately-asymmetric trust decision**: every other backend connection inside the internal zone described in [`docs/dns-naming.md`](dns-naming.md) skips certificate verification on the reverse-proxy hop (still encrypted, just doesn't check identity) — a pragmatic tradeoff for low-stakes internal traffic between containers that already share a trusted network. The connection to Vault is the single exception: the proxy verifies Vault's certificate for real, against a dedicated internal CA cert. Given that Vault is the root of trust for every other secret in the fleet, treating it identically to a media-server backend would have been the actual mistake — the asymmetry here is the correct call, not an inconsistency. This is the real config contrast, not a description of it — every other backend uses this: > **The one deliberately-asymmetric trust decision**: every other backend connection inside the internal zone described in [`docs/dns-naming.md`](dns-naming.md) skips certificate verification on the reverse-proxy hop (still encrypted, just doesn't check identity) — a pragmatic tradeoff for low-stakes internal traffic between containers that already share a trusted network. The connection to Vault is the single exception: the proxy verifies Vault's certificate for real, against a dedicated internal CA cert. Given that Vault is the root of trust for every other secret in the fleet, treating it identically to a media-server backend would have been the actual mistake — the asymmetry here is the correct call, not an inconsistency. This is the real config contrast, not a description of it — every other backend uses this:
@@ -105,7 +106,7 @@ None of these ever call the Vault API themselves — every one of them goes thro
| Transport | Every Vault Agent ↔ Vault connection is TLS, certificate-verified | | Transport | Every Vault Agent ↔ Vault connection is TLS, certificate-verified |
| Secrets at rest | KV v2, encrypted by Vault's storage layer; rendered files are `0600`, root-owned, gitignored | | Secrets at rest | KV v2, encrypted by Vault's storage layer; rendered files are `0600`, root-owned, gitignored |
| Audit trail | Every request/response logged to a file audit device; secret values HMAC-hashed, not plaintext — what's visible is metadata: which token, which path, when. Rotated weekly, 8 generations kept. | | Audit trail | Every request/response logged to a file audit device; secret values HMAC-hashed, not plaintext — what's visible is metadata: which token, which path, when. Rotated weekly, 8 generations kept. |
| Alerting | Root-token use or permission-denied bursts trigger an alert through [`docs/notifications.md`](notifications.md)'s pipeline | | Alerting | Any root-policy token being used, or permission-denied bursts, trigger an alert through [`docs/notifications.md`](notifications.md)'s pipeline — the check matches generically on the token's policy, so it fires identically whether that's a routine mistake or a genuine break-glass event |
| Cert renewal reliability | Technitium's DNS-over-TLS/DoH cert bundle auto-rebuilds whenever Vault Agent re-renders its certs, guarded to skip unless under 7 days from expiry. This closed a real prior gap: the rebuild never used to happen automatically, and an expired cert was silently served for 19 days before anyone caught it. | | Cert renewal reliability | Technitium's DNS-over-TLS/DoH cert bundle auto-rebuilds whenever Vault Agent re-renders its certs, guarded to skip unless under 7 days from expiry. This closed a real prior gap: the rebuild never used to happen automatically, and an expired cert was silently served for 19 days before anyone caught it. |
This is the real hook script, not a description of it — the full guard logic, the actual PKCS12 rebuild, and the service restart it triggers (password redacted, everything else genuine): This is the real hook script, not a description of it — the full guard logic, the actual PKCS12 rebuild, and the service restart it triggers (password redacted, everything else genuine):