fix: redact live identity/CA specifics from today's SSH-CA command output

Two command-block "evidence" snippets added earlier today pasted real,
live-captured values verbatim: the exact cert file path, the fleet's
actual CA fingerprint, today's real issuance timestamp, and the live
Vault role/principal name. All of it identified real infrastructure
in a way the rest of this repo's established redaction convention
(see docs/firewall-and-network.md's [admin workstation]-style
placeholders) already exists specifically to avoid. Redacted to
bracket placeholders; the structural/format evidence (cert type,
extensions, TTLs) stays genuine.
This commit is contained in:
automation-bot committed 2026-09-05 09:46:39 +03:00
1 parent ff3ca1d8f1
commit 2c865f90f0
2 files changed
+11 -11

No files matched your search

+7 -7
View File
@@ -27,23 +27,23 @@ The obvious simpler design is one universal "secret goes in, secret comes out" p
| | | | | |
|---|---| |---|---|
| **Law** | The automation identity never holds a static, standing-access SSH key. Only a Vault-signed certificate, valid for hours, ever grants it access to a fleet host. | | **Law** | The automation identity never holds a static, standing-access SSH key. Only a Vault-signed certificate, valid for hours, ever grants it access to a fleet host. |
| **Flow** | Its own systemd timer (2h interval) → reuses Vault Agent's already-authenticated token → `vault write ssh-client-signer/sign/sign-ansible` → certificate installed next to the identity's own key on the one host that needs it → every fleet host's sshd trusts the CA directly, no per-host secret involved | | **Flow** | Its own systemd timer (2h interval) → reuses Vault Agent's already-authenticated token → `vault write ssh-client-signer/sign/[role name]` → certificate installed next to the identity's own key on the one host that needs it → every fleet host's sshd trusts the CA directly, no per-host secret involved |
| **Failure behavior** | A single missed refresh is harmless — the timer fires every 2 hours against a 6-hour certificate, so there's hours of margin. A sustained outage spanning several missed cycles eventually locks the automation identity out of certificate-based SSH entirely, with no static key to fall back to — an accepted tradeoff, not an oversight (see [`docs/secrets-and-pki.md`](secrets-and-pki.md)) | | **Failure behavior** | A single missed refresh is harmless — the timer fires every 2 hours against a 6-hour certificate, so there's hours of margin. A sustained outage spanning several missed cycles eventually locks the automation identity out of certificate-based SSH entirely, with no static key to fall back to — an accepted tradeoff, not an oversight (see [`docs/secrets-and-pki.md`](secrets-and-pki.md)) |
This is the real signed certificate, not a description of one — installed and ready to use, principal and validity window both visible: This is the real shape of a signed certificate from this flow, not a description of one — host path, CA fingerprint, and validity window redacted since they identify live infrastructure, everything else genuine:
``` ```
$ ssh-keygen -Lf /home/ansible/.ssh/auto-cert.pub $ ssh-keygen -Lf [cert path]
Type: [email protected] user certificate Type: [email protected] user certificate
Signing CA: RSA SHA256:vcGM3I3hc5AYm9ji1lXYBx1yhVuxR3Gj/3CFdRRkjOo (using rsa-sha2-512) Signing CA: RSA SHA256:[fleet's CA fingerprint] (using rsa-sha2-512)
Valid: from 2026-09-05T08:55:53 to 2026-09-05T14:56:23 Valid: from [issued] to [issued + 6h]
Principals: Principals:
ansible [automation identity]
Extensions: Extensions:
permit-port-forwarding permit-port-forwarding
``` ```
**Invariants:** exactly one identity (`ansible`) is ever signed for. Vault's role config enforces this independently of the script that calls it — a compromised or buggy script still can't get a certificate for any other principal. Every host trusts the CA's public key directly; none of them store the automation identity's actual key material at all. **Invariants:** exactly one identity is ever signed for. Vault's role config enforces this independently of the script that calls it — a compromised or buggy script still can't get a certificate for any other principal. Every host trusts the CA's public key directly; none of them store the automation identity's actual key material at all.
## 3️⃣ Application Secret Flow ## 3️⃣ Application Secret Flow
+4 -4
View File
@@ -21,13 +21,13 @@ A managed secrets service (a cloud provider's KMS/Secrets Manager) was a real al
- **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. - **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. - **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: This is the real role definition, not a paraphrase — role and principal names redacted since they identify a live credential, everything else genuine:
``` ```
$ vault read ssh-client-signer/roles/sign-ansible $ vault read ssh-client-signer/roles/[role name]
key_type ca key_type ca
allowed_users ansible allowed_users [automation identity]
default_user ansible default_user [automation identity]
ttl 6h (21600s) ttl 6h (21600s)
max_ttl 12h (43200s) max_ttl 12h (43200s)
algorithm_signer rsa-sha2-512 algorithm_signer rsa-sha2-512