diff --git a/docs/swarm/ca.md b/docs/swarm/ca.md index d98cfb3e..5b5f6416 100644 --- a/docs/swarm/ca.md +++ b/docs/swarm/ca.md @@ -129,8 +129,9 @@ every gateway host: `services-issuer-key.pem` from the store's host and set both options. A host whose gateway serves the self-signed leaf without both options set -fails evaluation, naming them. One that names files it can't read fails -`swarm-services-cert.service`, naming the paths. The old spellings, +still evaluates and deploys, and `swarm-services-cert.service` fails, naming +them. One that names files it can't read fails the same unit, naming the +paths. The old spellings, `deploy.hive-controller.tls.baoClientCertFile` and `baoClientKeyFile`, are renames of these two: a config that still sets them evaluates with a warning naming both paths. diff --git a/nix/host-modules/hive-tls.nix b/nix/host-modules/hive-tls.nix index 465d9190..b8d92d2d 100644 --- a/nix/host-modules/hive-tls.nix +++ b/nix/host-modules/hive-tls.nix @@ -333,30 +333,6 @@ in }; config = lib.mkIf active { - assertions = [ - { - assertion = haveServicesIssuer; - message = '' - services.hyperhive.gateway serves the self-signed leaf on this host, - which needs the swarm-services issuer's store identity: set both - - services.hyperhive.deploy.bao.servicesIssuerClientCertFile - services.hyperhive.deploy.bao.servicesIssuerClientKeyFile - - swarm-services-cert.service presents it to ask the swarm secret - store for the swarm-services leaf and to fetch the store's pki root. - - Both default to the pair glue-bao-tls.nix mints when - services.hyperhive.deploy.bao.enable is true (the host that runs - the store). Otherwise copy services-issuer.pem and - services-issuer-key.pem from the store host's /var/lib/swarm-bao-pki/ - and name them in those two options, or give the gateway a - certificate of its own (services.hyperhive.gateway.tls.certDir or - services.hyperhive.gateway.tls.acme.enable). - ''; - } - ]; - # The state dir and the trust bundle. Never waits on the store: the # store's container is ordered after this unit, which writes the # bundle it bind-mounts, so the leaf is `hive-tls-resign`'s. diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index b849d982..c84b220a 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -1967,8 +1967,9 @@ in `pki/issue/swarm-services` and nothing else, and it is the same on every gateway host, whether or not a hive runs there. - Required on every host whose gateway serves the self-signed leaf; - unset fails evaluation. + Required on every host whose gateway serves the self-signed leaf. + Unset, the host evaluates and `swarm-services-cert` fails, naming + both options. ./glue-bao-tls.nix points it at the leaf it mints on the store's host. On a gateway host without the store, it is a file the operator copies diff --git a/nix/module-eval/forge-placement.nix b/nix/module-eval/forge-placement.nix index ce13d01d..ed86dea2 100644 --- a/nix/module-eval/forge-placement.nix +++ b/nix/module-eval/forge-placement.nix @@ -73,8 +73,6 @@ let deploy.forgejo.ci.jobTimeout = "2h"; deploy.bao.ciRunnerClientCertFile = "/etc/pki/bao-ci-runner.pem"; deploy.bao.ciRunnerClientKeyFile = "/etc/pki/bao-ci-runner-key.pem"; - deploy.bao.servicesIssuerClientCertFile = "/etc/pki/bao-services-issuer.pem"; - deploy.bao.servicesIssuerClientKeyFile = "/etc/pki/bao-services-issuer-key.pem"; }; # The old name alone, with no store identity placed and none defaulted. ciUnderForgeNoIdentity = hive { @@ -90,8 +88,6 @@ let swarm.forge.ci.package = pkgs.hello; deploy.bao.ciRunnerClientCertFile = "/etc/pki/bao-ci-runner.pem"; deploy.bao.ciRunnerClientKeyFile = "/etc/pki/bao-ci-runner-key.pem"; - deploy.bao.servicesIssuerClientCertFile = "/etc/pki/bao-services-issuer.pem"; - deploy.bao.servicesIssuerClientKeyFile = "/etc/pki/bao-services-issuer-key.pem"; }; runsForge = m: m.services.hyperhive.deploy.forgejo.enable && m.containers ? hive-forge; diff --git a/nix/module-eval/hive-tls.nix b/nix/module-eval/hive-tls.nix index 672f5537..22576502 100644 --- a/nix/module-eval/hive-tls.nix +++ b/nix/module-eval/hive-tls.nix @@ -288,9 +288,11 @@ let && refsHive [ noService.systemd.services.hive-tls-resign ]; } { - # The control is the same host with the pair placed, and the store's - # host, where the glue supplies it. - name = "a self-signed gateway with no services-issuer pair fails evaluation, naming both options"; + # A host with no store and no pair placed is a supported shape: it + # evaluates, and its unit goes red. The control is the same host with + # the pair placed, whose branch fetches, and the store's host, where + # the glue supplies the pair. + name = "a self-signed gateway with no services-issuer pair evaluates, and its unit fails naming both options"; ok = let refused = @@ -298,15 +300,29 @@ let lib.any ( a: !a.assertion - && lib.hasInfix "services.hyperhive.deploy.bao.servicesIssuerClientCertFile" a.message - && lib.hasInfix "services.hyperhive.deploy.bao.servicesIssuerClientKeyFile" a.message + && ( + lib.hasInfix "servicesIssuerClientCertFile" a.message + || lib.hasInfix "servicesIssuerClientKeyFile" a.message + ) ) m.assertions; + redUnit = + m: + let + branch = noSvcBranch m.systemd.services.swarm-services-cert.script; + in + lib.hasInfix "services.hyperhive.deploy.bao.servicesIssuerClientCertFile (unset)" branch + && lib.hasInfix "services.hyperhive.deploy.bao.servicesIssuerClientKeyFile (unset)" branch + && lib.hasSuffix "exit 1" (lib.removeSuffix "\n" branch) + && !(lib.hasInfix "/v1/pki/ca/pem" branch); in - refused gatewayNoHiveNoPair - && refused noIdentity - && !(refused gatewayNoHive) - && !(refused noService) - && !(refused allLocal) + !(refused gatewayNoHiveNoPair) + && !(refused noIdentity) + && redUnit gatewayNoHiveNoPair + && redUnit noIdentity + && !(redUnit gatewayNoHive) + && lib.hasInfix "/v1/pki/ca/pem" ( + noSvcBranch gatewayNoHive.systemd.services.swarm-services-cert.script + ) && allLocal.services.hyperhive.deploy.bao.servicesIssuerClientCertFile == "/var/lib/swarm-bao-pki/services-issuer.pem"; diff --git a/nix/module-eval/nats-tls.nix b/nix/module-eval/nats-tls.nix index 051a8155..257843a7 100644 --- a/nix/module-eval/nats-tls.nix +++ b/nix/module-eval/nats-tls.nix @@ -67,16 +67,14 @@ let # address set by hand: what every hive but one in a multi-host swarm looks # like. The controller is on too, since it may run away from the queue. # - # The forge's secret, the controller's store identity and the gateway's - # services-issuer pair are what a hive away from authelia and the store - # already has to be handed, and none is an address; without them this hive - # would fail assertions that have nothing to do with the queue. + # The forge's secret and the controller's store identity are what a hive + # away from authelia and the store already has to be handed, and none is an + # address; without them this hive would fail assertions that have nothing to + # do with the queue. remoteSecrets = { deploy.forgejo.sso.clientSecretFile = "/var/lib/forgejo-oidc/by-hand.secret"; deploy.swarm-controller.baoClientCertFile = "/var/lib/swarm-controller/bao-client.pem"; deploy.swarm-controller.baoClientKeyFile = "/var/lib/swarm-controller/bao-client-key.pem"; - deploy.bao.servicesIssuerClientCertFile = "/etc/pki/bao-services-issuer.pem"; - deploy.bao.servicesIssuerClientKeyFile = "/etc/pki/bao-services-issuer-key.pem"; }; remote = hiveWithController ( lib.recursiveUpdate remoteSecrets { deploy.swarm-controller.enable = true; } diff --git a/nix/module-eval/swarm-otel-identity.nix b/nix/module-eval/swarm-otel-identity.nix index 78ae95cb..99dcd677 100644 --- a/nix/module-eval/swarm-otel-identity.nix +++ b/nix/module-eval/swarm-otel-identity.nix @@ -27,12 +27,9 @@ let # hive's telemetry with nothing to push authenticated with, which is the # already-supported degrade `haveCollectorSecret` names above the module's # `let`. What this fixture is for is checking the reading unit itself does - # not render, rather than rendering with an env var nothing filled in. Its - # gateway has a certificate of its own: a self-signed one needs the - # services-issuer identity. + # not render, rather than rendering with an env var nothing filled in. otelNoIdentity = hive { deploy.swarm-otel.enable = true; - gateway.tls.certDir = "/var/lib/acme/t.local"; swarm.authelia.url = "https://auth.example.invalid"; deploy.forgejo.sso.clientSecretFile = "/var/lib/forgejo-oidc/by-hand.secret"; };