diff --git a/nix/host-modules/swarm-bao.nix b/nix/host-modules/swarm-bao.nix index fba463cd..e97ff1d1 100644 --- a/nix/host-modules/swarm-bao.nix +++ b/nix/host-modules/swarm-bao.nix @@ -375,6 +375,11 @@ let # # The agent PKI grant is its only path on that mount: it can ask the one role # for a certificate, not write that role or reach the issuer. + + # The two `list` paths end in `/`: bao checks a LIST against the directory + # with a trailing slash, where `+` matches the empty last segment, so a + # slashless list path loses that request to the `+/matrix/+` and `+/forge/+` + # delete stanzas and the LIST is denied. controllerPolicyText = '' path "auth/cert/certs/hive-*" { capabilities = ["create", "update", "read", "delete"] @@ -400,11 +405,11 @@ let capabilities = ["delete"] } - path "${credentialMountPath}/metadata/swarm/agents/+/matrix" { + path "${credentialMountPath}/metadata/swarm/agents/+/matrix/" { capabilities = ["list"] } - path "${credentialMountPath}/metadata/swarm/agents/+/forge" { + path "${credentialMountPath}/metadata/swarm/agents/+/forge/" { capabilities = ["list"] } diff --git a/nix/module-eval/bao-grants.nix b/nix/module-eval/bao-grants.nix index 4156e26c..1ae17a60 100644 --- a/nix/module-eval/bao-grants.nix +++ b/nix/module-eval/bao-grants.nix @@ -1197,9 +1197,10 @@ let } { # `linked_accounts` names an agent's matrix accounts and forge labels by - # listing their two directories. A LIST matches the directory path - # itself, so each stanza reaches that one directory: not the agent's - # other keys, not `agents/` itself, not anything below. Pinned as whole + # listing their two directories. bao checks a LIST against the directory + # with a trailing slash, so each stanza names that slashed path and + # reaches that one directory: not the agent's other keys, not `agents/` + # itself, not anything below. Pinned as whole # stanzas, and as the only metadata stanzas under `agents/` beside the # queue revocation and the account deletes, so a widened path or an added # capability fails. @@ -1209,8 +1210,8 @@ let s = baoGrantHere.systemd.services.swarm-bao-controller-policy.script; stanzas = lib.length (lib.splitString "path \"secret/metadata/swarm/agents/" s) - 1; in - lib.hasInfix "path \"secret/metadata/swarm/agents/+/matrix\" {\n capabilities = [\"list\"]\n}" s - && lib.hasInfix "path \"secret/metadata/swarm/agents/+/forge\" {\n capabilities = [\"list\"]\n}" s + lib.hasInfix "path \"secret/metadata/swarm/agents/+/matrix/\" {\n capabilities = [\"list\"]\n}" s + && lib.hasInfix "path \"secret/metadata/swarm/agents/+/forge/\" {\n capabilities = [\"list\"]\n}" s && stanzas == 6; } {