bao: let the UI's admins login write the review classifier's API key
The docs tell the operator to write `secret/swarm/services/review-classifier/anthropic-api-key` by hand in the bao UI, but the UI's OIDC login for authelia's `admins` group lands on `swarm-operator-viewer`, which is list+read on `secret/metadata/*` and nothing under `secret/data/`. bao refuses the write, so an admin can't set the key and every classifier run fails with "no API key". The viewer policy gains `create` and `update` on that one leaf, no `read`: a UI session still never sees a secret value. The leaf is a named binding, shared with the classifier's reader policy. module-eval pins the viewer's two stanzas and that no `data/` grant carries `read`. docs/swarm/secrets.md and services.md describe the write. Closes #5148
This commit is contained in:
parent
a669cd96b6
commit
133d5578d2
4 changed files with 32 additions and 11 deletions
|
|
@ -1836,10 +1836,11 @@ let
|
|||
|
||||
# ── the UI's OIDC login ─────────────────────────────────────────────────
|
||||
{
|
||||
# What an `admins` login through the UI holds: the key tree and KV
|
||||
# metadata. Any `data/` path would hand a browser session every secret
|
||||
# in the store, and any `sys/` one more than the UI needs.
|
||||
name = "the operator viewer policy is list and read on KV metadata, and nothing under data/ or sys/";
|
||||
# What an `admins` login through the UI holds: the key tree, KV
|
||||
# metadata, and a write on the one leaf the operator fills by hand.
|
||||
# A `read` under `data/` would hand a browser session a secret's
|
||||
# value, and any `sys/` path more than the UI needs.
|
||||
name = "the operator viewer policy is list and read on KV metadata, a write on the classifier's API key, and no data/ read or sys/";
|
||||
ok =
|
||||
let
|
||||
viewer = grantsIn baoGrantHere.systemd.services.swarm-bao-operator-viewer-policy.script;
|
||||
|
|
@ -1852,10 +1853,18 @@ let
|
|||
"read"
|
||||
];
|
||||
}
|
||||
{
|
||||
path = "secret/data/swarm/services/review-classifier/anthropic-api-key";
|
||||
caps = [
|
||||
"create"
|
||||
"update"
|
||||
];
|
||||
}
|
||||
]
|
||||
&& grantFor viewer "secret/data/swarm/agents/x/queue" == null
|
||||
&& grantFor viewer "secret/metadata/swarm/agents/x/queue" != null
|
||||
&& !(lib.any (g: lib.hasPrefix "secret/data" g.path || lib.hasPrefix "sys/" g.path) viewer);
|
||||
&& !(lib.any (g: lib.hasPrefix "secret/data" g.path && lib.elem "read" g.caps) viewer)
|
||||
&& !(lib.any (g: lib.hasPrefix "sys/" g.path) viewer);
|
||||
}
|
||||
{
|
||||
# Route (a): enabling an auth method stays a bootstrap-token act. The
|
||||
|
|
|
|||
Loading…
Reference in a new issue