Watch
0
0
Fork
You've already forked hyperhive
0

hive TLS: re-issue a services leaf that does not chain to the store's root, delete the hive CA's leftovers

- swarm-services-cert (and its daily renewal) treats a services leaf that
  `openssl verify` rejects against swarm-services-root.pem as invalid and
  asks the store for a new one, as hive-tls-resign already does for the
  gateway leaf. The trust bundle is that root alone, so a leaf under any
  other issuer verifies for no consumer. With the store unreachable the
  unit fails, and where the gateway waits for the leaf, the import fails
  with it.
- Every host also deletes the old hive CA's ca.srl and .swarm-ca-adopted
  in deploy.hive-controller.tls.stateDir, with the same tmpfiles `r`
  rules as ca.pem/ca-previous.pem/ca-key.pem. Nothing reads either.
- docs/swarm/ca.md: the services leaf's re-issue conditions, the two
  extra deleted files, and that the deletion is irreversible: rolling back
  to a generation with swarm-ca.service mints a new, unrelated root that
  nothing issues under.

module-eval hive-tls: a case for the services-leaf check in the boot
issuance and the renewal (red with the line removed), and the deletion
case covers the two extra files.

Refs #4588
This commit is contained in:
atlas 2026-10-05 20:24:12 +02:00 • committed by mara
commit 15f7d4d0cf
4 changed files with 50 additions and 11 deletions

View file

@ -98,9 +98,9 @@ The secret store's `pki` mount issues them a leaf of their own, through its
this host's services-issuer certificate, calls
`pki/issue/swarm-services`, and writes the result to
`/var/lib/hive-tls/swarm-services.pem` — the path the gateway already
copies from. Every hive does this with its own identity, so holding the
swarm root's private key stopped being what decides whether a hive can
serve its swarm's names.
copies from. Every hive does this with its own identity, so the store's
role, not a key on the hive, decides whether a hive can serve its swarm's
names.
`services.hyperhive.swarm.serviceDomains`, every swarm service name and the
same list on every host, populates the role's
@ -137,8 +137,9 @@ and every browser taught to trust it.
**A daily timer renews the leaf.** The store's role issues it for 720
hours. `swarm-services-cert-renew.timer` runs the same script as
`swarm-services-cert.service` once a day, and that script asks the store
for a new leaf once the current one is past half that window or is
missing a configured name. A rotation re-imports the leaf into the
for a new leaf once the current one is past half that window, is
missing a configured name, or doesn't chain to the store's root
(`swarm-services-root.pem`). A rotation re-imports the leaf into the
gateway and reloads nginx. A store that can't answer — still sealed, or
out of reach — fails the unit, which leaves the current leaf in place,
and the next day's run tries again: about fifteen tries before the leaf
@ -156,9 +157,15 @@ others.
No host holds a CA or its key, except the store's mTLS CA
(`glue-bao-tls.nix`), which signs only the store's server certificate and the
certificates that log in to it. At boot and on every deploy, every host
deletes `/var/lib/swarm-ca` and the `ca.pem`, `ca-previous.pem` and
`ca-key.pem` in `<deploy.hive-controller.tls.stateDir>`. The swarm distributes
only certificates.
deletes `/var/lib/swarm-ca` and the `ca.pem`, `ca-previous.pem`,
`ca-key.pem`, `ca.srl` and `.swarm-ca-adopted` in
`<deploy.hive-controller.tls.stateDir>`. The swarm distributes only
certificates.
⚠️ **The deletion is irreversible.** Rolling back to a generation that still
has `swarm-ca.service` finds no root under `/var/lib/swarm-ca` and mints a
new one, unrelated to the deleted root. That's harmless: nothing issues
under it.
A host whose `deploy.bao.clientCaFile`, `deploy.bao.serverCaFile` or
`deploy.swarm-controller.hiveClientCaFile` names one of those paths fails