Watch
0
0
Fork
You've already forked hyperhive
0

store the forge webhook secret and grafana's secret key in bao, seeded from the existing files

This commit is contained in:
atlas 2026-10-27 12:02:44 +01:00 • committed by mara
commit a4e48a7bca

View file

@ -483,6 +483,23 @@ let
"update"
];
}
{
# Grafana's datasource key sits under the publisher's `services/*` write
# too, and a planted value is the key Grafana would encrypt with from its
# next start on, orphaning what it stored under the old one. The OIDC
# leaf beside it is the control: still the prefix's.
name = "the publisher may not write Grafana's datasource key";
ok =
let
grants = grantsIn baoGrantHere.systemd.services.swarm-bao-secret-publisher-policy.script;
in
(grantFor grants "secret/data/swarm/services/swarm-grafana/secret-key").caps == [ "deny" ]
&&
(grantFor grants "secret/data/swarm/services/swarm-grafana/oidc/client").caps == [
"create"
"update"
];
}
{
# The review classifier's forge token sits under the publisher's
# `services/*` write too, and the controller posts the classifier's
@ -611,12 +628,12 @@ let
# both, and the two are separate principals precisely because a
# dashboard is not entitled to a collector's credential.
#
# The admin password and the metrics bearer are the leaves it may create,
# The admin password, the metrics bearer and the datasource key are the leaves it may create,
# and without `update`: a grant that could replace one would let a second
# run rotate a value Grafana or the metrics store already holds. The
# controller's Grafana token is the one leaf it may replace, which it
# does when Grafana refuses the stored token.
name = "the Grafana reader reads its own and its forwarder's client secrets, creates its admin password and metrics bearer, and writes the controller's Grafana token, and nothing else";
name = "the Grafana reader reads its own and its forwarder's client secrets, creates its admin password, metrics bearer and datasource key, and writes the controller's Grafana token, and nothing else";
ok =
let
s = baoGrantHere.systemd.services.swarm-bao-grafana-oidc-policy.script;
@ -644,6 +661,13 @@ let
"read"
];
}
{
path = "secret/data/swarm/services/swarm-grafana/secret-key";
caps = [
"create"
"read"
];
}
{
path = "secret/data/swarm/controller/swarm-controller/grafana/token";
caps = [
@ -2028,6 +2052,24 @@ let
"swarm-bao-grafana-oidc-policy"
];
}
{
# The webhook HMAC secret: the controller creates it, seeded from its
# old state-directory file, and reads it. `create` without `update`, so
# the first value stored is the one every start reads. Pinned as the
# whole stanza, so an added capability fails; the sibling token's
# stanza above is the presence control for the same matcher.
name = "the controller creates and reads its webhook secret, and no other granting unit names it";
ok =
let
s = baoGrantHere.systemd.services.swarm-bao-controller-policy.script;
naming = lib.filter (
u: lib.hasInfix "swarm-controller/forge/webhook-secret" baoGrantHere.systemd.services.${u}.script
) grantingUnitNames;
in
lib.hasInfix "path \"secret/data/swarm/controller/swarm-controller/forge/webhook-secret\" {\n capabilities = [\"create\", \"read\"]\n}" s
&& lib.hasInfix "path \"secret/data/swarm/controller/swarm-controller/forge/token\" {\n capabilities = [\"read\"]\n}" s
&& naming == [ "swarm-bao-controller-policy" ];
}
{
# The forge's OIDC client secret by name: the forge publisher reads it,
# and the secret publisher writes it under its `swarm/services/*` grant,