diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index fff2de8c..16f067a7 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -154,10 +154,9 @@ let # policy by spelling it the same way, and is itself named after it. controllerPolicyName = "swarm-controller"; - # The subject the controller's certificate must carry. Cert auth matches on - # the CN, so this is an interface rather than a label: a leaf signed by the - # right CA but minted with any other subject cannot authenticate. - controllerCn = "swarm-controller"; + # An option rather than a literal because whatever mints the controller's + # leaf has to spell it identically, and that lives in another file. + controllerCn = baoDeploy.controllerCommonName; # Derived with `bao write -output-policy`, which short-circuits the request # and needs no server, rather than written from memory. @@ -478,6 +477,27 @@ in ''; }; + controllerCommonName = lib.mkOption { + type = lib.types.str; + default = "swarm-controller"; + example = "swarm-controller.svc"; + description = '' + Subject the store's `swarm-controller` cert-auth role accepts. An + interface, not a label: cert auth matches on the CN, so whatever mints + the controller's leaf has to spell it the same way. + + Lives here because it is a property of the **role**, which this module + writes — not a credential belonging to the controller. Nothing outside + the store needs it except whatever issues that leaf. + + ⚠️ The CA this role trusts also signs each hive's reader leaf, whose CN + is the hive's own name, so a hive named `swarm-controller` would satisfy + the role. Changing this to something outside the hive-name grammar + (`[a-z0-9-]`) rules that out — at the cost of a role rename in any store + that has already run the granting unit. + ''; + }; + serverCaFile = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; diff --git a/nix/host-modules/swarm-controller.nix b/nix/host-modules/swarm-controller.nix index 29d445ec..a88b483e 100644 --- a/nix/host-modules/swarm-controller.nix +++ b/nix/host-modules/swarm-controller.nix @@ -467,6 +467,37 @@ in ''; }; + baoClientCertFile = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "/var/lib/swarm-controller/bao-client.pem"; + description = '' + Certificate this daemon presents to the swarm's secret store. Its + subject has to match + {option}`services.hyperhive.deploy.bao.controllerCommonName`, which is + what the store's cert-auth role matches on. + + Distinct from {option}`services.hyperhive.deploy.bao.clientCertFile` on + purpose, and not an oversight: that one is **this host as a reader** and + carries the hive's name, while the controller's policy lets it create + roles for every hive. One certificate serving both would hand that power + to whatever else reads the store here. + + Defaulted by `glue-controller-bao-identity.nix` where this deployment + mints its own; elsewhere the leaf is issued out of band and named here. + ''; + }; + + baoClientKeyFile = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "/var/lib/swarm-controller/bao-client-key.pem"; + description = '' + Private key for {option}`services.hyperhive.deploy.swarm-controller.baoClientCertFile`. + Both or neither — a certificate with no key authenticates nothing. + ''; + }; + queue = { clientSecretFile = lib.mkOption { type = lib.types.str;