docs: document the Vault SSH certificate authority in secrets-and-pki

The SSH CA mount (ssh-client-signer/) existed live in Vault but was
missing from this doc's capability list entirely. Adds it as a fourth
"What It Does" bullet with real role config and a live screenshot of
the secrets engines list, and refreshes the stale ACL policies
screenshot (was showing 15 policies, live is 18).
This commit is contained in:
automation-bot committed 2026-09-05 09:19:54 +03:00
1 parent 9fd60f3f3b
commit 91a7ec1e9e
3 files changed
+19 -1

No files matched your search

+19 -1
View File
@@ -6,7 +6,7 @@
| | |
|---|---|
| **Software** | HashiCorp Vault, self-hosted, native systemd service (not containerized) |
| **Role** | Certificate authority (2 PKI mounts) + secret store (KV v2) |
| **Role** | Certificate authority (2 PKI mounts + 1 SSH CA mount) + secret store (KV v2) |
| **Distribution** | Vault Agent on every consuming host, AppRole auth, renders to local disk |
| **Replaces** | A prior plaintext-`.env`-in-git secrets model |
@@ -19,6 +19,24 @@ A managed secrets service (a cloud provider's KMS/Secrets Manager) was a real al
- **Certificate authority** — two PKI mounts: one for public-facing wildcard certs (consumed by the edge in [`docs/firewall-and-network.md`](firewall-and-network.md)), one for internal mTLS certs (consumed by the browser-facing reverse-proxy zone). Both issue short-lived certificates, not long-lived ones — a deliberate choice that shrinks the window a leaked cert is useful for.
- **Secret store** — a KV v2 mount holds every migrated application's real secret values, one namespace per host, enforced by policy (below).
- **Distribution** — Vault Agent runs on every fleet host, authenticates via AppRole, and renders both certificates and secrets to local disk. No application or service ever talks to Vault directly — this single rule is what makes the rest of the model tractable to reason about.
- **SSH certificate authority** — a dedicated mount issues short-lived SSH certificates for the fleet's automation identity, instead of that identity holding a single static key with standing, permanent access to every host. A signed certificate is valid for 6 hours (12-hour hard cap), scoped to exactly one principal, and every host trusts the CA's public key directly rather than storing that identity's key at all — the same short-lived-credential philosophy as the PKI mounts above, applied to SSH instead of TLS. A leaked certificate is worthless in hours; a leaked static key used to be useful forever. The one thing that can't use this model at all is Kestra's own SSH-based automation flows — its SSH plugin is a plain client with no certificate support, full stop — see [`docs/orchestration.md`](orchestration.md) for what it uses instead, and why that's a completely separate, unrelated credential rather than a workaround bolted onto this one.
This is the real role definition, not a paraphrase:
```
$ vault read ssh-client-signer/roles/sign-ansible
key_type ca
allowed_users ansible
default_user ansible
ttl 6h (21600s)
max_ttl 12h (43200s)
algorithm_signer rsa-sha2-512
default_extensions permit-pty, permit-port-forwarding
```
And this is the real mount list, not an assumption of what's enabled — the SSH CA sitting right alongside the two PKI mounts, not a separate system bolted on beside Vault:
![Vault's live Secrets engines list: cubbyhole/, kv/, pki/ (public wildcard), pki_int/ (internal mTLS), and ssh-client-signer/ — the SSH certificate authority is a real mount, not a description of an aspiration](../assets/vault-secrets-engines.png)
## Why It's Built This Way