bao: mint the controller's leaf, and point the controller at it
glue-bao-tls.nix signs a third leaf. It is minted whether or not a controller runs here, because the case it serves is the one where it does not: a controller elsewhere needs a leaf from this CA and cannot sign one, so issuing it here turns "obtain a certificate out of band" into "copy this file". glue-controller-bao-identity.nix holds the pairing and nothing else -- which paths this host's controller reads. Gated on the leaf existing rather than on deploy.bao.enable, so a controller on the store's host and one three networks away with an out-of-band leaf get the same wiring; gating on the store would have made the co-located case the only supported shape. The directory comes from deploy.bao.clientCertFile rather than repeating glue-bao-tls.nix's literal, so moving the PKI moves both. module-eval gains three cases and two fixtures, because nothing asserted the PKI script before: an earlier commit added a leaf to that rendered unit and left the derivation unchanged. The fixture's CN is deliberately a value no default could supply, so "the role and the leaf both carry it" says they read one option rather than that both happen to say swarm-controller. Gates: 62 module properties hold (59 before, plus these three), on a derivation hash that actually moved -- this suite is a cache hit when only fixtures change, so an unchanged hash would have meant the cases never ran. nix fmt clean, all three scripts/check-*.sh exit 0.
This commit is contained in:
parent
a5dc62cecd
commit
c18aee8f74
4 changed files with 112 additions and 2 deletions
|
|
@ -24,6 +24,7 @@
|
|||
./hive-tls.nix
|
||||
./otel.nix
|
||||
./glue-bao-tls.nix
|
||||
./glue-controller-bao-identity.nix
|
||||
./glue-matrix-bao-token.nix
|
||||
./swarm-authelia.nix
|
||||
./swarm-bao.nix
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
# ⚠️ Not the hive CA and not the swarm CA. The store will eventually
|
||||
# distribute both, and an authority you must already hold a certificate from
|
||||
# cannot be one the store hands out — reach the store to get the CA material,
|
||||
# need a cert from that CA to reach the store. This CA signs exactly two
|
||||
# things and distributes nothing, so it cannot enter that cycle.
|
||||
# need a cert from that CA to reach the store. This CA signs a fixed, short
|
||||
# list of leaves and distributes nothing, so it cannot enter that cycle.
|
||||
#
|
||||
# ⚠️ Files like this are the only place a `deploy.<foo>` value may derive from
|
||||
# a `deploy.<bar>.enable`. Everywhere else that is forbidden. The exception
|
||||
|
|
@ -126,6 +126,17 @@ in
|
|||
${lib.escapeShellArg cfg.domain} ${lib.escapeShellArg "DNS:${cfg.domain}"} serverAuth
|
||||
[ -s ${pkiDir}/client.pem ] || ${signLeaf} ${pkiDir} client \
|
||||
${lib.escapeShellArg clientCn} "" clientAuth
|
||||
|
||||
# Minted whether or not a controller runs here, because the case it
|
||||
# serves is the one where it does not: a controller elsewhere needs a
|
||||
# leaf from this CA and has no way to sign one. Issuing it here turns
|
||||
# "obtain a certificate out of band" into "copy this file".
|
||||
#
|
||||
# Its own CN rather than the reader's above: the controller's policy
|
||||
# lets it create roles for every hive, and the reader's leaf carries
|
||||
# this hive's name.
|
||||
[ -s ${pkiDir}/controller.pem ] || ${signLeaf} ${pkiDir} controller \
|
||||
${lib.escapeShellArg deployCfg.bao.controllerCommonName} "" clientAuth
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
|||
41
nix/host-modules/glue-controller-bao-identity.nix
Normal file
41
nix/host-modules/glue-controller-bao-identity.nix
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Glue: point the swarm controller at the bao leaf minted for it.
|
||||
#
|
||||
# ONE PAIRING PER FILE — controller ← bao, and nothing else. Deleting this
|
||||
# leaves a controller that takes operator-provided certificate paths, which is
|
||||
# what every deployment that does not mint its own already does.
|
||||
#
|
||||
# ⚠️ The minting is NOT here. ./glue-bao-tls.nix holds the CA and signs the
|
||||
# leaf, because the thing that owns a private key owns issuing from it; a
|
||||
# second signer would duplicate that file's `openssl` helper to no benefit.
|
||||
# What belongs here is the pairing: which paths this host's controller reads.
|
||||
#
|
||||
# ⚠️ Gated on the leaf existing, not on the store being enabled. A controller
|
||||
# on the store's own host is one deployment; a controller three networks away
|
||||
# holding a leaf issued out of band is another, and both want the same wiring.
|
||||
# `deploy.bao.enable` would have made the first one the only supported shape.
|
||||
#
|
||||
# Everything is `mkDefault`. An operator naming their own paths wins.
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
hyperhiveCfg = config.services.hyperhive;
|
||||
deployCfg = hyperhiveCfg.deploy;
|
||||
baoDeploy = deployCfg.bao;
|
||||
|
||||
# Where ./glue-bao-tls.nix puts the leaves. Derived from the reader's own
|
||||
# path rather than repeating that file's directory literal: an operator who
|
||||
# moves the PKI moves both, and the two cannot drift apart.
|
||||
haveMintedPki = baoDeploy.clientCertFile != null;
|
||||
pkiDir = if haveMintedPki then builtins.dirOf baoDeploy.clientCertFile else null;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (hyperhiveCfg.enable && deployCfg.swarm-controller.enable && haveMintedPki) {
|
||||
services.hyperhive.deploy.swarm-controller = {
|
||||
baoClientCertFile = lib.mkDefault "${pkiDir}/controller.pem";
|
||||
baoClientKeyFile = lib.mkDefault "${pkiDir}/controller-key.pem";
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue