feat(nix): issue a swarm-services leaf, and renew it with the hive one
The swarm's service names cannot go on the hive leaf: the hive CA is name-constrained to the hive domain and those names are siblings of it. So there is a second leaf, signed by the services sub-CA. signLeafScript is parameterised rather than duplicated -- same ceremony, different issuer and names -- so the two cannot drift in how they are built. The name list itself is derived once, as a read-only swarm.serviceDomains, and read by both the sub-CA that name-constrains those names and the leaf that carries them as SANs: two modules each assembling the list is how they stop agreeing. The renewal unit is the point of this commit as much as the leaf. hive-tls-resign now knows about both, because a leaf that first-boot issuance creates and weekly renewal ignores looks perfect for its entire validity and then expires with no warning -- the failure is invisible until it is total. The freshness test became a function over a leaf rather than a check of one, so adding a third leaf is a line rather than a rewrite. The services leaf is skipped where the sub-CA is absent: it exists only where the swarm CA is autoconfigured, and on a hive whose certs come from its operator the correct state is no leaf, not a stale one. Also drops a comment that documented signLeafScript's old signature from above an unrelated binding.
This commit is contained in:
parent
240ae79ad6
commit
5a83c40dca
3 changed files with 114 additions and 45 deletions
|
|
@ -153,9 +153,37 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
options.services.hyperhive.swarm.serviceDomains = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
readOnly = true;
|
||||
internal = true;
|
||||
description = ''
|
||||
Read-only: the public hostnames of the swarm's own services, in a
|
||||
stable sorted order. Second derived set alongside `peerHives`, and
|
||||
here for the same reason — the CA that name-constrains these and
|
||||
the leaf that carries them as SANs must agree exactly, and two
|
||||
modules each assembling the list is how they stop agreeing.
|
||||
|
||||
Sorted and deduplicated deliberately: consumers compare this list
|
||||
against what they issued last time to decide whether to re-issue,
|
||||
so an unstable order would churn a certificate that other things
|
||||
are meant to pin.
|
||||
'';
|
||||
};
|
||||
|
||||
config = {
|
||||
services.hyperhive.swarm.peerHives = lib.filterAttrs (name: _: name != cfg.hiveName) swarmCfg.hives;
|
||||
|
||||
services.hyperhive.swarm.serviceDomains = lib.sort (a: b: a < b) (
|
||||
lib.unique (
|
||||
lib.filter (d: d != null && d != "") [
|
||||
swarmCfg.forge.domain
|
||||
swarmCfg.matrix.gatewayHost
|
||||
swarmCfg.authelia.domain
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
assertions = [
|
||||
{
|
||||
# Guarded on `hiveName != null` so the required-hiveName
|
||||
|
|
|
|||
Loading…
Reference in a new issue