diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index 100a26c1..bede4e26 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -203,6 +203,29 @@ let } ''; + # The identity that copies authelia's minted OIDC client secrets into the + # store. Named outside `hive-*` for the same reason as the controller's: the + # controller may create policies under that prefix, and a policy it can + # rewrite is not a constraint on anything. + secretPublisherPolicyName = "swarm-secret-publisher"; + + # One grant, and every narrowing in it is load-bearing. + # + # `secret/data/` is KV v2's ACL prefix, inserted by the engine rather than + # written by the caller — same trap as the controller's grant above. + # + # `hives/` and not `swarm/*`: this principal has no business with an agent's + # or a service's credentials, and the hive prefix is the only one whose paths + # it produces. + # + # Write-only. It copies secrets in and never reads one back; a read + # capability would let a file-copier recover every hive's credentials. + secretPublisherPolicyText = '' + path "${credentialMountPath}/data/swarm/hives/*" { + capabilities = ["create", "update"] + } + ''; + # The KV v2 engine the controller writes agent credentials through. Named # once because the grant above and the `secrets enable` in the bootstrap unit # have to agree: a policy pointing at a mount nobody created is precisely the