swarm: mint a per-agent queue credential beside the agent's store identity

Every agent on a hive authenticates to the swarm queue with the same
hive-scoped secret today, so at the auth callout one agent is
indistinguishable from its co-hived neighbours and no subject can be
scoped to one of them.

Mint a secret per agent instead, at swarm level, into
secret/swarm/agents/<agent>/queue -- inside the stanza every agent's ACL
document already grants, so no policy changes and no existing agent's
document is rewritten. It is written by the same node that already mints
the agent's certificate, and read back under the agent's own token
before that node reports success.

The secret is not derived from the agent's mTLS identity: the two
credentials answer different questions and coupling their lifetimes
would mean renewing either implied renewing the other. Nothing here
rotates a queue secret -- a re-run keeps the existing value and only
corrects the principal it names, because this function is re-run
deliberately against agents that are already connected. Revoking one
means deleting the path.

Nothing reads the new credential yet; this is the minting half.
This commit is contained in:
atlas 2026-09-21 18:26:54 +02:00 committed by mara
commit ffd5018b18
6 changed files with 359 additions and 19 deletions

View file

@ -81,6 +81,12 @@ chrono = { version = "0.4", default-features = false, features = [
clap = { version = "4", features = ["derive"] }
clap_complete = "4"
enumflags2 = { version = "0.7.12", features = ["serde"] }
# The OS CSPRNG, for the one thing in this tree that generates a secret rather
# than receiving one (`swarm-controller::agent_identity`). `getrandom` rather
# than `rand`: the whole need is "fill these bytes from the kernel", and `rand`
# would add `rand_core` + `rand_chacha` to do it through a userspace generator
# this has no use for.
getrandom = "0.3"
indicatif = "0.18"
hive-sh4re = { path = "hive-sh4re" }
hive-agent-sock = { path = "hive-agent-sock" }