bao: enable cert auth and give the controller a role for its policy
The policy the granting unit already writes grants paths under `auth/cert/certs/*`, and nothing in the tree creates that mount. Every certificate login therefore fails against a path that is not there -- the controller's own, and the per-hive ones it is meant to issue against the same mount. Same unit, same bootstrap token: check whether cert auth is mounted, enable it if not, then write a role binding CN `swarm-controller` to the `swarm-controller` policy. Idempotency is a read rather than a tolerated error. `auth enable` fails on an existing mount, and recognising that would tie a rebuild to an error string no run of this store has ever produced, so the unit asks `bao auth list` and mounts only on absence. That read is why the token policy in setup.md gains `sys/auth`. Each grant came from `bao <cmd> -output-policy`, which prints what a command requires without running it -- the same way controllerPolicyText was derived. Enabling an auth method needs `sudo` on `sys/auth/cert`, which the documented token did not have. Gated on `clientCaFile`, not on the token alone: `swarm-bao-certs` installs `client-ca.pem` only under that condition, and a role's `certificate=` has to name a real CA. The policy write, which needs no CA, is unchanged in that case. Nothing can present a certificate for this role yet -- the only client leaf the tree mints carries CN = the hive's name -- and none of this has been run against a live store. Both are stated in setup.md.
This commit is contained in:
parent
df18d3d4d7
commit
8bd41fd84f
3 changed files with 107 additions and 5 deletions
|
|
@ -254,6 +254,15 @@ let
|
|||
baoGrantNoStore = hive {
|
||||
deploy.bao.bootstrapTokenFile = "/run/secrets/bao-bootstrap.token";
|
||||
};
|
||||
# The store and the token, with no CA to trust. `mkForce` because the PKI
|
||||
# glue supplies one by default here — this is the deployment that brings its
|
||||
# own certificates and has not named the authority yet, and it separates
|
||||
# "the grant unit runs" from "cert auth can be set up".
|
||||
baoGrantNoClientCa = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.bao.bootstrapTokenFile = "/run/secrets/bao-bootstrap.token";
|
||||
deploy.bao.clientCaFile = lib.mkForce null;
|
||||
};
|
||||
|
||||
baoNames = machine: machine.services.hyperhive.gateway.localNames;
|
||||
|
||||
|
|
@ -505,6 +514,37 @@ let
|
|||
in
|
||||
lib.hasInfix "sys/policies/acl/hive-*" s && !(lib.hasInfix "sys/policies/acl/*" s);
|
||||
}
|
||||
{
|
||||
# The policy above grants paths under a mount nothing else creates, so
|
||||
# the unit that writes the policy has to create it too — otherwise every
|
||||
# certificate login fails against a path that is not there.
|
||||
name = "the granting unit creates the cert auth mount and the controller's role";
|
||||
ok =
|
||||
let
|
||||
s = baoGrantHere.containers.swarm-bao.config.systemd.services.swarm-bao-controller-policy.script;
|
||||
in
|
||||
lib.hasInfix "bao auth enable cert" s
|
||||
&& lib.hasInfix "auth/cert/certs/swarm-controller" s
|
||||
&& lib.hasInfix "/var/lib/swarm-bao-tls/client-ca.pem" s;
|
||||
}
|
||||
{
|
||||
# The arm that makes the one above mean something. A role's trust anchor
|
||||
# is the CA, so with none named there is nothing to write — and the
|
||||
# policy write, which needs no CA, must survive that.
|
||||
#
|
||||
# ⚠️ Matched on the COMMANDS, not on `auth/cert/certs`: the policy text is
|
||||
# embedded in this same script and grants that very path, so the shorter
|
||||
# infix is present either way and the arm could never fail.
|
||||
name = "with no client CA the unit still writes the policy and skips the role";
|
||||
ok =
|
||||
let
|
||||
s =
|
||||
baoGrantNoClientCa.containers.swarm-bao.config.systemd.services.swarm-bao-controller-policy.script;
|
||||
in
|
||||
lib.hasInfix "bao policy write" s
|
||||
&& !(lib.hasInfix "bao auth enable cert" s)
|
||||
&& !(lib.hasInfix "client-ca.pem" s);
|
||||
}
|
||||
{
|
||||
# The arm that makes the one above mean something, and the property the
|
||||
# host-side half depends on: no store here, so no bind mount and no unit.
|
||||
|
|
|
|||
Loading…
Reference in a new issue