Watch
0
0
Fork
You've already forked hyperhive
0

add one shared templated agent policy and name each agent's bao entity after it

This commit is contained in:
atlas 2026-10-25 20:39:59 +01:00 • committed by mara
commit 4cdf807afc
9 changed files with 777 additions and 13 deletions

View file

@ -380,6 +380,16 @@ 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 identity grants name each agent's login entity after the agent
# (`agent_entity.rs`). `sys/auth/cert` carries `sudo` because a plain `read`
# of an auth mount is refused, and it is that one mount: it yields the
# accessor an entity alias names the mount by. Every identity stanza lists the
# request keys it takes, so the grants cannot set an entity's `policies`, which
# would attach any policy to a login. The entity and alias names are not
# scoped further, by accessor or by entity: an agent's name is not known at
# deploy time, so the guard in `agent_entity.rs` (rename only a name the store
# generated, never move an alias) is what prevents an identity swap.
# 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/+`
@ -401,6 +411,41 @@ let
capabilities = ["list"]
}
path "sys/auth/cert" {
capabilities = ["read", "sudo"]
}
path "identity/lookup/entity" {
capabilities = ["update"]
allowed_parameters = {
"alias_name" = []
"alias_mount_accessor" = []
}
}
path "identity/entity/name/+" {
capabilities = ["create", "read", "update"]
allowed_parameters = {
"name" = []
}
}
path "identity/entity/id/+" {
capabilities = ["update"]
allowed_parameters = {
"name" = []
}
}
path "identity/entity-alias" {
capabilities = ["create", "update"]
allowed_parameters = {
"name" = []
"mount_accessor" = []
"canonical_id" = []
}
}
path "${credentialMountPath}/data/swarm/agents/*" {
capabilities = ["create", "read", "update"]
}

View file

@ -1558,6 +1558,39 @@ let
in
lib.hasInfix "path \"secret/data/swarm/agents/*\" {\n capabilities = [\"create\", \"read\", \"update\"]" s;
}
{
# `agent_entity.rs` names each agent's login entity after the agent. The
# accessor read is `read` + `sudo` on the one mount, the lookup and both
# writes list the request keys they take (so `policies`, which would
# attach any policy to a login, is refused), and nothing else under
# `identity/` or `sys/auth` is reachable. Pinned as whole stanzas and as
# the exact list of identity and sys/auth paths, so a wider glob or an
# added path fails.
name = "the controller's identity grants are the five stanzas agent_entity.rs needs and nothing else";
ok =
let
s = baoGrantHere.systemd.services.swarm-bao-controller-policy.script;
pathsUnder =
prefix: lib.filter (l: lib.hasPrefix "path \"${prefix}" l) (map lib.trim (lib.splitString "\n" s));
in
lib.hasInfix "path \"sys/auth/cert\" {\n capabilities = [\"read\", \"sudo\"]\n}" s
&& lib.hasInfix "path \"identity/lookup/entity\" {\n capabilities = [\"update\"]\n allowed_parameters = {\n \"alias_name\" = []\n \"alias_mount_accessor\" = []\n }\n}" s
&& lib.hasInfix "path \"identity/entity/name/+\" {\n capabilities = [\"create\", \"read\", \"update\"]\n allowed_parameters = {\n \"name\" = []\n }\n}" s
&& lib.hasInfix "path \"identity/entity/id/+\" {\n capabilities = [\"update\"]\n allowed_parameters = {\n \"name\" = []\n }\n}" s
&& lib.hasInfix "path \"identity/entity-alias\" {\n capabilities = [\"create\", \"update\"]\n allowed_parameters = {\n \"name\" = []\n \"mount_accessor\" = []\n \"canonical_id\" = []\n }\n}" s
&&
pathsUnder "identity/" == [
"path \"identity/lookup/entity\" {"
"path \"identity/entity/name/+\" {"
"path \"identity/entity/id/+\" {"
"path \"identity/entity-alias\" {"
]
&& pathsUnder "sys/auth" == [ "path \"sys/auth/cert\" {" ]
# The control: the same walk finds the policy-namespace stanza that is
# there, so an empty result above means nothing else exists rather than
# that the walk reads nothing.
&& pathsUnder "sys/policies/acl/" == [ "path \"sys/policies/acl/hive-*\" {" ];
}
{
# `matrix_account::hive_sender` writes every hive's sender token and
# `forge::hive_token` every hive's forge token, and nothing else under