From 2c865f90f08b6d2a77ee40a2313ee99a5a5a6f39 Mon Sep 17 00:00:00 2001 From: automation-bot Date: Sat, 5 Sep 2026 09:46:39 +0300 Subject: [PATCH] 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. --- docs/secret-distribution.md | 14 +++++++------- docs/secrets-and-pki.md | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/secret-distribution.md b/docs/secret-distribution.md index 9e34e2c..c70434d 100644 --- a/docs/secret-distribution.md +++ b/docs/secret-distribution.md @@ -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. | -| **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)) | -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: ssh-ed25519-cert-v01@openssh.com user certificate -Signing CA: RSA SHA256:vcGM3I3hc5AYm9ji1lXYBx1yhVuxR3Gj/3CFdRRkjOo (using rsa-sha2-512) -Valid: from 2026-09-05T08:55:53 to 2026-09-05T14:56:23 +Signing CA: RSA SHA256:[fleet's CA fingerprint] (using rsa-sha2-512) +Valid: from [issued] to [issued + 6h] Principals: - ansible + [automation identity] Extensions: 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 diff --git a/docs/secrets-and-pki.md b/docs/secrets-and-pki.md index d88e050..925a749 100644 --- a/docs/secrets-and-pki.md +++ b/docs/secrets-and-pki.md @@ -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. - **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 -allowed_users ansible -default_user ansible +allowed_users [automation identity] +default_user [automation identity] ttl 6h (21600s) max_ttl 12h (43200s) algorithm_signer rsa-sha2-512