Watch
0
0
Fork
You've already forked hyperhive
0

swarm-bao: deny the secret publisher the callout xkey's seed

`swarm-secret-publisher` holds create and update on
`secret/data/swarm/services/*`, which covers the callout xkey's seed at
`swarm/services/swarm-nats/callout/xkey-seed`. It never writes that
path, but a write there would replace the key the queue's server seals
every callout request to. An exact-path `deny` outranks the prefix.

A create-only grant would not do: KV v2 honours create versus update, so
it would stop an overwrite, but it would still let the publisher plant a
seed of its choosing whenever the path is empty, on a first boot or
after a key replacement. The publisher needs no access to the path at
all.
This commit is contained in:
atlas 2026-10-05 22:13:58 +02:00 • committed by mara
commit 531d44d34b
2 changed files with 26 additions and 1 deletions

View file

@ -425,6 +425,23 @@ let
&& !(lib.hasInfix "secret/data/swarm/*" s)
&& !(lib.hasInfix "sys/policies/acl" s);
}
{
# The publisher's `services/*` write covers the callout xkey's seed, and
# only the exact-path denial, which outranks the prefix, keeps it from
# replacing the key. The control is an OIDC leaf beside it, which the
# prefix still grants.
name = "the publisher may not write the callout xkey's seed";
ok =
let
grants = grantsIn baoGrantHere.systemd.services.swarm-bao-secret-publisher-policy.script;
in
(grantFor grants "secret/data/swarm/services/swarm-nats/callout/xkey-seed").caps == [ "deny" ]
&&
(grantFor grants "secret/data/swarm/services/swarm-nats/oidc/client").caps == [
"create"
"update"
];
}
{
# The ordering is load-bearing and invisible at runtime: the controller's
# unit creates the KV and cert-auth mounts this one writes into, so