# `checks.module-eval-hive-tls` — see ./lib.nix for the shared rationale (why # this suite exists, naming convention, "evaluates not executes"). # # The swarm-services leaf's renewal: a timer that really re-runs the # issuance, at a threshold read off the store role's lifetime. And the # store's root on a hive that asks it for no leaf. And the gateway leaf, # issued by the store through the hive's own role, with no hive CA and no # host-held swarm root. { pkgs, lib, self, nixosSystem, shared, }: let inherit (import ./lib.nix { inherit pkgs lib self nixosSystem ; }) hive hiveWithController runGroup ; # Every service on one host, so the store's granting unit renders the role # this leaf is issued through. inherit (shared) allLocal; # The same host with the role's lifetime moved, so a threshold that is a # number of its own shows up as one that did not move with it. shortTtl = hiveWithController { deploy.singleHostSwarm = true; deploy.bao.servicesPkiLeafTtlHours = 48; }; # Fronting none of the swarm's names, reading a store it does not run, # with the reader identity, the services-issuer pair and the hive's own # identity placed by hand. noService = hiveWithController { deploy.bao.clientCertFile = "/etc/pki/bao-client.pem"; deploy.bao.clientKeyFile = "/etc/pki/bao-client-key.pem"; deploy.bao.serverCaFile = "/etc/pki/bao-ca.pem"; deploy.bao.servicesIssuerClientCertFile = "/etc/pki/bao-services-issuer.pem"; deploy.bao.servicesIssuerClientKeyFile = "/etc/pki/bao-services-issuer-key.pem"; deploy.hive-controller.tls.baoHiveIdentityCertFile = "/etc/pki/bao-hive.pem"; deploy.hive-controller.tls.baoHiveIdentityKeyFile = "/etc/pki/bao-hive-key.pem"; }; noSvcFetch = noService.systemd.services.swarm-services-cert.script; # The same hive holding its own identity and no services-issuer pair: the # shape of every hive host without the store that fronts no swarm name. noServiceNoPair = hiveWithController { deploy.bao.clientCertFile = "/etc/pki/bao-client.pem"; deploy.bao.clientKeyFile = "/etc/pki/bao-client-key.pem"; deploy.bao.serverCaFile = "/etc/pki/bao-ca.pem"; deploy.hive-controller.tls.baoHiveIdentityCertFile = "/etc/pki/bao-hive.pem"; deploy.hive-controller.tls.baoHiveIdentityKeyFile = "/etc/pki/bao-hive-key.pem"; }; noPairFetch = noServiceNoPair.systemd.services.swarm-services-cert.script; # The same hive with no store identity at all. noIdentity = shared.bareWithController; noIdFetch = noIdentity.systemd.services.swarm-services-cert.script; # A gateway on a host with no hive and no store, fronting no swarm name, # with the services-issuer pair placed by hand; and the same host without it. gatewayNoHive = hive { gateway.enable = true; deploy.bao.serverCaFile = "/etc/pki/bao-ca.pem"; deploy.bao.servicesIssuerClientCertFile = "/etc/pki/bao-services-issuer.pem"; deploy.bao.servicesIssuerClientKeyFile = "/etc/pki/bao-services-issuer-key.pem"; }; gatewayNoHiveNoPair = hive { gateway.enable = true; }; # The store's host with the pair still named under its old path. renamedPair = hiveWithController { deploy.singleHostSwarm = true; deploy.hive-controller.tls.baoClientCertFile = "/etc/pki/old-issuer.pem"; deploy.hive-controller.tls.baoClientKeyFile = "/etc/pki/old-issuer-key.pem"; }; # The `want_svc=0` branch of a rendered script, up to the `fi` that closes it (the # only one followed by a blank line). noSvcBranch = script: builtins.head ( lib.splitString "\nfi\n\n" (lib.last (lib.splitString ''if [ "$want_svc" = 0 ]; then'' script)) ); # Everything after that branch: the path that logs in and issues the leaf. issuePath = script: lib.concatStringsSep "\nfi\n\n" ( lib.tail ( lib.splitString "\nfi\n\n" (lib.last (lib.splitString ''if [ "$want_svc" = 0 ]; then'' script)) ) ); units = allLocal.systemd.services; boot = units.swarm-services-cert; caUnit = units.hive-tls-ca; leafUnit = units.hive-tls-resign; timer = allLocal.systemd.timers.swarm-services-cert-renew; # What the timer starts, read off the timer rather than assumed from its # name: a timer's `Unit=` defaults to its own name, and pointing it at the # boot unit is exactly the regression the cases below exist for. triggeredName = lib.removeSuffix ".service" ( timer.timerConfig.Unit or "swarm-services-cert-renew.service" ); triggered = units.${triggeredName}; remainsAfterExit = u: u.serviceConfig.RemainAfterExit or false; # Whether `m` fails evaluation on `deploy.