hive CA: delete ca.pem, ca-previous.pem and ca-key.pem, the bundle is the store's root
The gateway leaf comes from the store's pki mount, so a hive CA's certificates anchor nothing and its key is a secret outside the store. - hive-tls-ca writes trust-bundle.pem from swarm-services-root.pem alone; the ca.pem and ca-previous.pem slots are gone. - Every host deletes ca.pem, ca-previous.pem and ca-key.pem in deploy.hive-controller.tls.stateDir with tmpfiles `r` rules that follow the option. The removal shim, now host-ca-removed.nix, holds these beside the /var/lib/swarm-ca rule and the swarm.ca.* removals. - deploy.bao.clientCaFile, deploy.bao.serverCaFile and deploy.swarm-controller.hiveClientCaFile naming /var/lib/swarm-ca or one of the deleted hive CA files fail evaluation, naming the store's mTLS CA (/var/lib/swarm-bao-pki/ca.pem on the store's host) as the replacement. module-eval hive-tls covers the single-anchor bundle, the deletion (incl. a relocated stateDir) and the assertion on all three options. Refs #4588
This commit is contained in:
parent
93f1a76ea7
commit
4e5a642928
10 changed files with 170 additions and 122 deletions
|
|
@ -155,7 +155,7 @@ let
|
|||
&& lib.hasInfix ''"$BAO_ADDR/v1/pki/ca/pem"'' noSvcFetch
|
||||
&& lib.hasInfix ''mv -f "$svcroot.new" "$svcroot"'' noSvcFetch
|
||||
&& lib.hasInfix ''svcroot="$d/swarm-services-root.pem"'' noService.systemd.services.hive-tls-ca.script
|
||||
&& lib.hasInfix ''if [ -s "$svcroot" ]; then anchors+=("$svcroot"); fi'' noService.systemd.services.hive-tls-ca.script;
|
||||
&& lib.hasInfix ''cat "$svcroot" > "$bundle"'' noService.systemd.services.hive-tls-ca.script;
|
||||
}
|
||||
{
|
||||
# The hive's own identity, not its reader identity: the reader's policy
|
||||
|
|
@ -258,18 +258,12 @@ let
|
|||
&& mentions noService "swarm-services-root.pem";
|
||||
}
|
||||
{
|
||||
# Three slots and no fourth: a root slot beside them is an anchor
|
||||
# nothing issues under.
|
||||
name = "the trust bundle anchors on the store's root and a hive CA's public certificates only";
|
||||
# One anchor: any other slot is a root nothing issues under.
|
||||
name = "the trust bundle is the store's root alone";
|
||||
ok =
|
||||
let
|
||||
slots = lib.filter (l: lib.hasPrefix "if [ -s " l && lib.hasInfix "anchors+=(" l) (
|
||||
lib.splitString "\n" caUnit.script
|
||||
);
|
||||
in
|
||||
lib.length slots == 3
|
||||
&& lib.hasInfix ''if [ -s "$svcroot" ]; then anchors+=("$svcroot"); fi'' caUnit.script
|
||||
&& !(lib.hasInfix ''anchors+=("$root")'' caUnit.script);
|
||||
lib.hasInfix ''cat "$svcroot" > "$bundle"'' caUnit.script
|
||||
&& !(lib.hasInfix "anchors+=(" caUnit.script)
|
||||
&& !(lib.hasInfix "ca.pem" caUnit.script);
|
||||
}
|
||||
{
|
||||
# The control is the all-local host, which defines none of them.
|
||||
|
|
@ -322,17 +316,74 @@ let
|
|||
&& !(lib.hasInfix refusal (imp noService));
|
||||
}
|
||||
{
|
||||
# Nothing reads or removes a `ca-key.pem`, so a rollback finds the
|
||||
# key and does not mint a new anchor. The control is the bundle
|
||||
# reading `ca.pem` in the same script.
|
||||
name = "a hive CA key is neither read nor removed, and its public certificate stays in the trust bundle";
|
||||
# The control is the same scan finding the store root's file, and a
|
||||
# relocated state dir, whose rules follow it.
|
||||
name = "no hive TLS unit reads a hive CA's files, and every host deletes them";
|
||||
ok =
|
||||
!(lib.hasInfix "ca-key.pem" caUnit.script)
|
||||
&& !(lib.hasInfix "ca-key.pem" leafUnit.script)
|
||||
&& lib.hasInfix ''ca="$d/ca.pem"'' caUnit.script
|
||||
&& lib.hasInfix ''if [ -s "$ca" ]; then anchors+=("$ca"); fi'' caUnit.script
|
||||
&& lib.hasInfix ''if [ -s "$prev" ]; then anchors+=("$prev"); fi'' caUnit.script
|
||||
&& lib.hasInfix ''cat "''${anchors[@]}" > "$bundle"'' caUnit.script;
|
||||
let
|
||||
texts =
|
||||
m:
|
||||
map (u: m.systemd.services.${u}.script) [
|
||||
"hive-tls-ca"
|
||||
"hive-tls-resign"
|
||||
"hive-gateway-self-signed-cert"
|
||||
];
|
||||
reads = m: needle: lib.any (lib.hasInfix needle) (texts m);
|
||||
deletes =
|
||||
m: dir:
|
||||
lib.all (f: lib.elem "r ${dir}/${f}" m.systemd.tmpfiles.rules) [
|
||||
"ca.pem"
|
||||
"ca-previous.pem"
|
||||
"ca-key.pem"
|
||||
];
|
||||
relocated = hiveWithController { deploy.hive-controller.tls.stateDir = "/srv/hive-tls"; };
|
||||
in
|
||||
!(lib.any (reads allLocal) [
|
||||
"/ca.pem"
|
||||
"ca-previous.pem"
|
||||
"ca-key.pem"
|
||||
])
|
||||
&& reads allLocal "swarm-services-root.pem"
|
||||
&& deletes allLocal "/var/lib/hive-tls"
|
||||
&& deletes noService "/var/lib/hive-tls"
|
||||
&& deletes relocated "/srv/hive-tls"
|
||||
&& !(deletes relocated "/var/lib/hive-tls");
|
||||
}
|
||||
{
|
||||
# The store host pointing its client CA at the old root: the store's and
|
||||
# the controller's options both fire, the second through the glue's
|
||||
# `mkDefault`. The control is the same host on its defaults.
|
||||
name = "a CA-file option naming a deleted CA file fails evaluation, naming the store's mTLS CA";
|
||||
ok =
|
||||
let
|
||||
refused =
|
||||
m: option:
|
||||
lib.any (
|
||||
a:
|
||||
!a.assertion
|
||||
&& lib.hasInfix "services.hyperhive.deploy.${option} is" a.message
|
||||
&& lib.hasInfix "/var/lib/swarm-bao-pki/ca.pem" a.message
|
||||
) m.assertions;
|
||||
oldRoot = hiveWithController {
|
||||
deploy.singleHostSwarm = true;
|
||||
deploy.bao.clientCaFile = "/var/lib/swarm-ca/root.pem";
|
||||
};
|
||||
hiveCa = hive {
|
||||
deploy.bao.serverCaFile = "/var/lib/hive-tls/ca.pem";
|
||||
deploy.swarm-controller.hiveClientCaFile = "/var/lib/hive-tls/ca-previous.pem";
|
||||
};
|
||||
options = [
|
||||
"bao.clientCaFile"
|
||||
"bao.serverCaFile"
|
||||
"swarm-controller.hiveClientCaFile"
|
||||
];
|
||||
in
|
||||
refused oldRoot "bao.clientCaFile"
|
||||
&& refused oldRoot "swarm-controller.hiveClientCaFile"
|
||||
&& refused hiveCa "bao.serverCaFile"
|
||||
&& refused hiveCa "swarm-controller.hiveClientCaFile"
|
||||
&& !(lib.any (refused allLocal) options)
|
||||
&& allLocal.services.hyperhive.deploy.bao.clientCaFile == "/var/lib/swarm-bao-pki/ca.pem";
|
||||
}
|
||||
{
|
||||
# The store host's hive presents the leaf ./glue-bao-tls.nix mints for
|
||||
|
|
|
|||
Loading…
Reference in a new issue