Watch
0
0
Fork
You've already forked hyperhive
0

hive-tls: stage bao pki root in every hive's trust bundle

A self-signed hive fronting no swarm service name never filled
`$svcroot` (/var/lib/hive-tls/swarm-services-root.pem): the only writer
was `swarm-services-cert`'s issuance, which exits early on
`want_svc=0`. So those hives' trust-bundle.pem lacked the store's `pki`
root, even though every other hive's swarm-service names chain to it.

On `want_svc=0`, `swarm-services-cert` now reads the root from the
store's unauthenticated `GET /v1/pki/ca/pem`, over the hive's existing
BAO_ADDR, `deploy.bao.serverCaFile` and reader identity
(`deploy.bao.clientCertFile`/`clientKeyFile`) at the TLS layer only; no
login. It writes `$svcroot` and restarts `hive-tls-ca` when the root
changed, as the issuing path already does. The daily
`swarm-services-cert-renew` timer runs the same script, so the copy
follows a root rotation.

The gateway no longer `Requires=` `swarm-services-cert` on such a host:
nginx reads nothing that unit writes there, and the fetch retries
against a sealed store.

`hivectl peer-config` prints the root as step 2 of the self-signed
instructions: the swarm's service names are issued under it, not the
swarm root.

No new option. Refs #4588.
This commit is contained in:
atlas 2026-09-30 21:23:18 +02:00 • committed by mara
commit 72f5e39278
5 changed files with 171 additions and 10 deletions

View file

@ -63,7 +63,9 @@ gateway can't serve a swarm service that runs behind another.
**The root's public certificate is a file, on every hive:**
`/var/lib/hive-tls/swarm-services-root.pem` (0644), written beside the
leaf it signed and folded into `trust-bundle.pem`. On the host running
leaf it signed and folded into `trust-bundle.pem`. A hive fronting no
swarm name asks for no leaf and reads the root alone, from the store's
`pki/ca/pem`. On the host running
the store it's also at
`/var/lib/swarm-bao-services-pki/services-root.pem`. That's the file to
hand a browser, and reading it needs no store login — which matters,
@ -124,6 +126,11 @@ host:
scp /var/lib/swarm-ca/root.pem <peer-host>:/var/lib/swarm-ca/root.pem
```
It then prints the secret store's `pki` root itself, read from
`/var/lib/hive-tls/swarm-services-root.pem`. The store issues the swarm's
service names under that root, not the swarm root, so a peer host trusting only
the swarm root can't verify them.
That's the point of the hierarchy: the operator installs the root
**once per swarm host**, not once per peer, so a hive joining later
needs no edit on the hives already running. A hive whose cert already chains to a public

View file

@ -45,7 +45,7 @@ neither is a renaming of the other.
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| swarm root CA cert | `swarm-ca.nix` first-boot unit, when the operator sets `autoConfigure` | `/var/lib/swarm-ca/root.pem` | operator copies the **cert** in; it's public |
| swarm root CA key | same unit | `/var/lib/swarm-ca/root-key.pem`, `0600` | stays on whichever host holds it — see the constraint below |
| swarm-services root CA (cert + key) | `swarm-bao.nix`'s granting unit, inside the store's `pki` mount | the **key** never leaves the mount; the **cert** lands at `/var/lib/swarm-bao-services-pki/services-root.pem` (0644) and at `/var/lib/hive-tls/swarm-services-root.pem` on every hive | nothing to copy — every hive receives the cert with the leaf it asks the store for |
| swarm-services root CA (cert + key) | `swarm-bao.nix`'s granting unit, inside the store's `pki` mount | the **key** never leaves the mount; the **cert** lands at `/var/lib/swarm-bao-services-pki/services-root.pem` (0644) and at `/var/lib/hive-tls/swarm-services-root.pem` on every hive | nothing to copy — every hive receives the cert with the leaf it asks the store for, or from `pki/ca/pem` where it fronts no swarm name |
| authelia session, JWT and storage-encryption keys | authelia's first-boot unit, in-container | `/var/lib/authelia-swarm/{session,jwt,storage-encryption}.key` | generated in place; nothing outside that container reads them |
| authelia OIDC HMAC key | same unit | `/var/lib/authelia-swarm/oidc-hmac.key` | same |
| authelia OIDC issuer key (RSA) | same unit | `/var/lib/authelia-swarm/oidc-issuer.key` | same — relying parties verify against the **public** half at `/jwks.json` |