module-eval: the seal, the store's identity, and the reader pairing
The seal choice gates the TPM machinery, in both directions. The store's three certificate paths are a function of the glue: present when the store is deployed, and an operator's own path beats the mkDefault. The absence arm this replaces asserted the store defaults NO path -- true while nothing supplied one, false the moment something did. The reader unit is a function of the PAIRING: present with store and homeserver together, absent with the store alone. That pair is what makes it glue rather than a feature of either side, and it is the case that fails if a later change wires the reader to one of them.
This commit is contained in:
parent
0e5eb1e8d6
commit
aa784a746d
1 changed files with 71 additions and 0 deletions
|
|
@ -71,6 +71,26 @@ let
|
|||
bare = hive { };
|
||||
withCi = hive { deploy.forgejo.ci.enable = true; };
|
||||
|
||||
baoPkcs11 = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.bao.seal = "pkcs11";
|
||||
};
|
||||
baoShamir = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.bao.seal = "shamir";
|
||||
};
|
||||
baoExplicitCerts = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.bao.serverCertFile = "/etc/pki/bao.pem";
|
||||
deploy.bao.serverKeyFile = "/etc/pki/bao-key.pem";
|
||||
};
|
||||
# The store and a service that reads from it, versus the store alone. The
|
||||
# pair is what makes the reader's absence arm mean anything.
|
||||
baoWithMatrix = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.matrix.enable = true;
|
||||
};
|
||||
|
||||
# A priority collision is a property of the *option*, not
|
||||
# of the merged value's interior — nix throws the moment the value is
|
||||
# demanded at all, so `seq`-ing each `serviceConfig` value to WHNF is
|
||||
|
|
@ -134,6 +154,57 @@ let
|
|||
name = "the CI container's unit definitions merge without a priority collision";
|
||||
ok = forceCiServiceConfigs;
|
||||
}
|
||||
{
|
||||
# The store's seal is spread over five gates — the stanza, the
|
||||
# provisioning unit, a bind mount, a device and an EnvironmentFile.
|
||||
# Rendering only some of them is the dangerous state: a store that
|
||||
# says hardware-backed and seals with a software key, which no
|
||||
# assertion can catch because every value is individually valid.
|
||||
name = "a shamir store renders no TPM provisioning unit";
|
||||
ok = !(baoShamir.systemd.services ? swarm-bao-token);
|
||||
}
|
||||
{
|
||||
# Presence control for the case above. Without it, a typo in the
|
||||
# option name would satisfy the absence arm forever.
|
||||
name = "a pkcs11 store renders the TPM provisioning unit";
|
||||
ok = baoPkcs11.systemd.services ? swarm-bao-token;
|
||||
}
|
||||
{
|
||||
# The store's mTLS identity is a separate trust domain from both CAs in
|
||||
# this tree, because it must not come from an authority the store will
|
||||
# itself distribute. What supplies it is the glue, which mints a CA of
|
||||
# the store's own — so an enabled store has all three paths, and if this
|
||||
# ever reads null again the store stops coming up on its own.
|
||||
name = "a deployed store is given its own certificate, key and client CA";
|
||||
ok =
|
||||
let
|
||||
b = baoPkcs11.services.hyperhive.deploy.bao;
|
||||
in
|
||||
b.serverCertFile != null && b.serverKeyFile != null && b.clientCaFile != null;
|
||||
}
|
||||
{
|
||||
# Everything the glue sets is `mkDefault`, and this is the case that
|
||||
# says so: a deployment whose certificates come from somewhere the glue
|
||||
# has never heard of must win. Also the presence control for the case
|
||||
# above — a renamed option would read `null` on both and satisfy
|
||||
# neither, but only this one names a value.
|
||||
name = "an operator's own certificate path beats the glue's default";
|
||||
ok = baoExplicitCerts.services.hyperhive.deploy.bao.serverCertFile == "/etc/pki/bao.pem";
|
||||
}
|
||||
{
|
||||
# The store's first reader. Its unit belongs to the pairing, not to
|
||||
# either service: matrix must not learn the store exists, and the store
|
||||
# must not know who reads it.
|
||||
name = "a store deployed beside the homeserver fetches its registration token";
|
||||
ok = baoWithMatrix.systemd.services ? swarm-bao-matrix-token;
|
||||
}
|
||||
{
|
||||
# Absence arm. A store with nothing to serve renders no reader, so the
|
||||
# unit is a function of the PAIRING rather than of the store — which is
|
||||
# the property that makes it glue instead of a feature of either side.
|
||||
name = "a store with no homeserver beside it renders no token reader";
|
||||
ok = !(baoPkcs11.systemd.services ? swarm-bao-matrix-token);
|
||||
}
|
||||
];
|
||||
|
||||
bad = builtins.filter (c: !c.ok) cases;
|
||||
|
|
|
|||
Loading…
Reference in a new issue