swarm-bao: grant the queue responder the callout issuer and user keys' leaves
The `swarm-nats-auth` policy grants create and read, never update, on the seed and public half of the callout issuer and user keys, beside the xkey's two leaves: `ensure-callout-keys` creates them under that role, and the responder reads both seeds as it starts. The `swarm-secret-publisher` policy, which may write the rest of `swarm/services/`, is denied both seed paths exactly, as it is the xkey's. A planted issuer seed would be the authority to admit anyone to the queue. Both policies are written by the granter on every deploy; nothing about the granter's own policy changes.
This commit is contained in:
parent
8a4bb97377
commit
66ac034949
2 changed files with 60 additions and 17 deletions
|
|
@ -442,6 +442,24 @@ let
|
|||
"update"
|
||||
];
|
||||
}
|
||||
{
|
||||
# The same denial for the callout's two nkey seeds: a planted issuer
|
||||
# seed admits anyone to the queue, and a planted user seed is the one
|
||||
# identity callout does not check. Each is its own exact path, so the
|
||||
# OIDC leaf beside them is still the prefix's.
|
||||
name = "the publisher may not write the callout issuer or user seed";
|
||||
ok =
|
||||
let
|
||||
grants = grantsIn baoGrantHere.systemd.services.swarm-bao-secret-publisher-policy.script;
|
||||
in
|
||||
(grantFor grants "secret/data/swarm/services/swarm-nats/callout/issuer-seed").caps == [ "deny" ]
|
||||
&& (grantFor grants "secret/data/swarm/services/swarm-nats/callout/user-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
|
||||
|
|
@ -590,9 +608,9 @@ let
|
|||
# `+` is one path segment, so this reaches `swarm/agents/<agent>/queue`
|
||||
# and no other credential an agent holds; `swarm/agents/*` would reach
|
||||
# all of them. The responder's own OIDC client secret is the one
|
||||
# `services/` leaf beside it. Its only creates are the callout xkey's
|
||||
# two leaves, and nothing it holds may update or delete one.
|
||||
name = "the queue responder reads agent queue credentials and its OIDC secret, and may create only the callout xkey's two leaves";
|
||||
# `services/` leaf beside it. Its only creates are the two leaves of
|
||||
# each callout key, and nothing it holds may update or delete one.
|
||||
name = "the queue responder reads agent queue credentials and its OIDC secret, and may create only the callout keys' leaves";
|
||||
ok =
|
||||
let
|
||||
s = baoGrantHere.systemd.services.swarm-bao-nats-auth-policy.script;
|
||||
|
|
@ -604,7 +622,11 @@ let
|
|||
&& lib.length (lib.filter lib.isList (builtins.split "capabilities = \\[\"read\"]" s)) == 2
|
||||
&&
|
||||
lib.sort lib.lessThan creates == [
|
||||
"secret/data/swarm/public/swarm-nats/callout-issuer"
|
||||
"secret/data/swarm/public/swarm-nats/callout-user"
|
||||
"secret/data/swarm/public/swarm-nats/callout-xkey"
|
||||
"secret/data/swarm/services/swarm-nats/callout/issuer-seed"
|
||||
"secret/data/swarm/services/swarm-nats/callout/user-seed"
|
||||
"secret/data/swarm/services/swarm-nats/callout/xkey-seed"
|
||||
]
|
||||
&& lib.all (
|
||||
|
|
@ -616,7 +638,7 @@ let
|
|||
"read"
|
||||
]
|
||||
) grants
|
||||
&& lib.length (lib.filter lib.isList (builtins.split "path \"" s)) == 4
|
||||
&& lib.length (lib.filter lib.isList (builtins.split "path \"" s)) == 8
|
||||
&& !(lib.hasInfix "secret/data/swarm/agents/*" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/hives" s)
|
||||
&& !(lib.hasInfix "secret/data/swarm/services/*" s)
|
||||
|
|
|
|||
Loading…
Reference in a new issue