fix(#3391): give the swarm controller hive-CA trust
The controller's forge client speaks TLS to `https://<forge domain>`, which the gateway serves with a leaf signed by the hive CA. That CA is generated at runtime, so nothing build-time can name it and it is not in the system store -- and `reqwest`/`rustls` resolves roots through `rustls-native-certs`, whose `SSL_CERT_FILE` *replaces* the store rather than adding to it. With no bundle wired, every forge call failed `invalid peer certificate: UnknownIssuer` and agent creation died at its first step. `lib/hive-ca-trust.nix` already solved this, but only for containers: it sources the CA through `/run/hive-ca/trust-bundle.pem`, a bind mount that does not exist on the host. `hostUnit` makes it read the host copy and wait on `hive-tls-ca.service` itself -- one flag driving both, because a host source without that ordering is a race. `enable` is the other half, and it is the sharp edge: a container caller imports this into the container's module set, so it disappears with the container. A host caller imports it at the host's top level, where `imports` is unconditional -- without the flag, a hive with the controller turned off would get a bundle oneshot and a `swarm-controller` service conjured by `genAttrs`, holding an `SSL_CERT_FILE` and no `ExecStart`.
This commit is contained in:
parent
8b83eca0c1
commit
d14963ad2b
2 changed files with 55 additions and 2 deletions
|
|
@ -35,6 +35,26 @@ let
|
|||
forgeCfg = config.services.hyperhive.swarm.forge;
|
||||
uiCfg = config.services.hyperhive.swarm.ui;
|
||||
|
||||
# The controller's forge client speaks TLS to `https://${forgeCfg.domain}`,
|
||||
# which the gateway serves with a leaf signed by the hive CA — a CA
|
||||
# generated at runtime, so nothing build-time can name it and it is not in
|
||||
# the system store. `reqwest`/`rustls` resolves roots through
|
||||
# `rustls-native-certs`, whose `SSL_CERT_FILE` *replaces* that store rather
|
||||
# than adding to it, so without the assembled bundle every forge call fails
|
||||
# `invalid peer certificate: UnknownIssuer` and agent creation dies at its
|
||||
# first step.
|
||||
#
|
||||
# `hostUnit`: this consumer is a host service, not a container, so it reads
|
||||
# the CA from the host path and the oneshot waits on `hive-tls-ca.service`
|
||||
# itself. `enable`: `imports` is unconditional at the host's top level, so
|
||||
# without it a hive with the controller off would get a bundle unit and a
|
||||
# phantom `swarm-controller` service holding an `SSL_CERT_FILE`.
|
||||
caTrust = import ./lib/hive-ca-trust.nix {
|
||||
inherit lib;
|
||||
tlsCfg = config.services.hyperhive.tls;
|
||||
gatewayCfg = config.services.hyperhive.gateway;
|
||||
};
|
||||
|
||||
# The controller's own OAuth2 client. It is NOT a hive: the per-hive
|
||||
# clients the roster issues belong to hives, and the responder's client
|
||||
# belongs to the responder. One identity per principal — the rule is that
|
||||
|
|
@ -139,6 +159,16 @@ let
|
|||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(caTrust.trustBundle {
|
||||
inherit pkgs;
|
||||
name = "swarm-controller";
|
||||
consumers = [ "swarm-controller" ];
|
||||
hostUnit = true;
|
||||
enable = cfg.enable;
|
||||
})
|
||||
];
|
||||
|
||||
options.services.hyperhive.swarm.controller = {
|
||||
queueClientId = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
|
|
|||
Loading…
Reference in a new issue