Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/nix/host-modules/host-ca-removed.nix
atlas 15f7d4d0cf 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
2026-10-05 21:17:10 +02:00

74 lines
3 KiB
Nix

# Removal shim for the CAs a host held outside the secret store: the
# swarm root under `/var/lib/swarm-ca` (and its `services.hyperhive.swarm.ca.*`
# options), and a hive CA's `ca.pem`, `ca-previous.pem`, `ca-key.pem`,
# `ca.srl` and `.swarm-ca-adopted` in `deploy.hive-controller.tls.stateDir`.
#
# The secret store's `pki` root is the only trust anchor: it issues every
# hive's gateway leaf and the swarm's service names, and its key never leaves
# the store. Nothing generates, reads or bundles either CA, so a definition of
# a removed option fails evaluation with a message, a CA-file option naming
# one of the deleted paths fails it too, and every host deletes the files.
#
# Self-contained and deletable, like ./swarm-peers-removed.nix: one file to
# remove when the deprecation window closes.
{ lib, config, ... }:
let
deployCfg = config.services.hyperhive.deploy;
swarmCaDir = "/var/lib/swarm-ca";
hiveCaFiles = map (f: "${deployCfg.hive-controller.tls.stateDir}/${f}") [
"ca.pem"
"ca-previous.pem"
"ca-key.pem"
];
deleted = p: p == swarmCaDir || lib.hasPrefix "${swarmCaDir}/" p || lib.elem p hiveCaFiles;
# The hive CA's serial file and its adoption marker: neither is a CA, so
# no CA-file option can name them, and nothing reads them.
hiveCaLeftovers = map (f: "${deployCfg.hive-controller.tls.stateDir}/${f}") [
"ca.srl"
".swarm-ca-adopted"
];
# Every option that names a CA the store's mTLS checks against. One
# pointing at a deleted file fails the unit that reads it at start.
caFileOptions = {
"services.hyperhive.deploy.bao.clientCaFile" = deployCfg.bao.clientCaFile;
"services.hyperhive.deploy.bao.serverCaFile" = deployCfg.bao.serverCaFile;
"services.hyperhive.deploy.swarm-controller.hiveClientCaFile" =
deployCfg.swarm-controller.hiveClientCaFile;
};
removed =
name:
lib.mkRemovedOptionModule [ "services" "hyperhive" "swarm" "ca" name ] ''
The host-held swarm root CA is gone: the secret store's pki root is the
only trust anchor, and nothing generates or reads a root under
${swarmCaDir}. Remove this definition. See docs/swarm/ca.md.
'';
in
{
imports = map removed [
"autoConfigure"
"stateDir"
"validityDays"
];
assertions = lib.mapAttrsToList (option: path: {
assertion = path == null || !(deleted path);
message = ''
${option} is ${toString path}, a file every host deletes along with
the host-held CA it belonged to. Point it at the store's mTLS CA:
/var/lib/swarm-bao-pki/ca.pem on the host that runs the store, the copy
placed by hand on any other host. See docs/swarm/ca.md.
'';
}) caFileOptions;
# Both CAs' private keys are secrets outside the store, and the
# certificates beside them are anchors nothing issues under. The swarm
# root at the option's old default path only: a relocated `stateDir` is
# the operator's to delete.
systemd.tmpfiles.rules = [
"R ${swarmCaDir}"
]
++ map (f: "r ${f}") (hiveCaFiles ++ hiveCaLeftovers);
}