swarm: courier an agent's store identity into its container, and log in with it
`swarm-controller` mints an agent's mTLS leaf at creation and publishes it at `swarm/agents/<agent>/bao-mtls`. Nothing read it back. This adds the hop that carries it the rest of the way, and the in-container consumer that proves the hop works. Host side, `lifecycle::agent_identity` reads the row under *this hive's* own certificate — the hive is a principal the store already knows — and stages the leaf and its key `0600` under a new `agent-identity/<name>` state dir, deliberately outside every bind-mounted tree. Both files go in as systemd credentials rather than binds, the same answer and the same mode reason as the queue secret beside it: the staged key is unreadable to the unprivileged agent user, and the container manager reads a `--load-credential` source as root before re-exposing it under the consuming unit's own `User=`. The agent is never asked to authenticate in order to obtain the thing it authenticates with. Container side, `hive-agent-bao-identity.service` logs in with that certificate and reads the agent's own path back, failing the unit when either step does not succeed. It fails loudly where the hive-side readers degrade quietly, because a refused certificate means an agent that believes it reaches the store and never does — a cause only the login itself can name. The address is the whole switch, no separate `enable`, matching how `queue.nix` and `logs.nix` already gate themselves. A hive with a store forwards `HIVE_AGENT_BAO_ADDR` and every agent on it gets the check; a hive without one forwards nothing and no agent does. That is what keeps the delivery from landing in a container with nothing to read it. The hive can now reach an agent's identity, so hive privilege covers agent privilege. Accepted, not mitigated: the alternative is an agent fetching its own credential with a credential it does not yet have. Refs #4137
This commit is contained in:
parent
8aafe4eaee
commit
837e658d4a
10 changed files with 716 additions and 7 deletions
|
|
@ -51,7 +51,7 @@ strategy for every credential, including the mTLS leaf.
|
|||
| store path | minter | reader — pulls at runtime, holds in memory | renewal |
|
||||
| -------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | -------------- |
|
||||
| `swarm/agents/<agent>/matrix/<account>` | `swarm-controller` | the agent container itself, under the certificate its hive passed in | must be stated |
|
||||
| `swarm/agents/<agent>/bao-mtls` | `swarm-controller`, at agent creation | the agent's **hive**, under the hive's own certificate, which hands it into the container | must be stated |
|
||||
| `swarm/agents/<agent>/bao-mtls` | `swarm-controller`, at agent creation | `hive-c0re`, under the hive's own certificate, when it writes the agent's container config | must be stated |
|
||||
| `swarm/hives/<hive>/matrix/appservice-token` | one minter, on the authelia host | the hive process that presents the token to its homeserver, under the hive's own certificate | must be stated |
|
||||
| `swarm/hives/<hive>/queue/agent` | authelia | the agent container presenting the OIDC client to the swarm queue, under its own certificate | must be stated |
|
||||
| `swarm/services/<clientId>/oidc/client` | authelia | the service process that presents the client secret, under the certificate of the host it runs on | must be stated |
|
||||
|
|
@ -67,6 +67,27 @@ carries it, and no hive ever needs the capability to mint an identity.
|
|||
`swarm-controller` proves the leaf it publishes before the creation job
|
||||
reports success, by logging in with it and reading the row back.
|
||||
|
||||
**Who reads that row, and what happens to it.** `hive-c0re` reads it every
|
||||
time it writes an agent's container configuration
|
||||
(`lifecycle::agent_identity`), stages the certificate and its key `0600`
|
||||
outside every bind-mounted tree, and passes both to the container as systemd
|
||||
credentials — the same mechanism, and for the same mode reason, as the
|
||||
per-hive queue secret. A bind mount would hand the agent's unprivileged user
|
||||
a file it lacks the rights to open; the container manager reads a credential
|
||||
as root and re-exposes it under the consuming unit's own user.
|
||||
|
||||
Inside the container, `hive-agent-bao-identity.service` logs in with that
|
||||
certificate and reads this row back before reporting success, so an agent
|
||||
locked out of its own identity says so at boot rather than at whichever pull
|
||||
needed the store first. The unit exists whenever
|
||||
`services.hyperhive.agent.bao.addr` has a value, which the hive's meta flake
|
||||
sets from its own store address — the same all-or-nothing gate the per-hive
|
||||
queue credential beside it uses, and the reason the delivery above never lands
|
||||
in a container with nothing to read it. It fails loudly where the hive-side
|
||||
readers degrade quietly, which is deliberate: a missing queue secret means a
|
||||
swarm whose publisher has yet to run, while a refused certificate means an
|
||||
agent that believes it reaches the store and never does.
|
||||
|
||||
## Progressive enhancement
|
||||
|
||||
New functionality has to match this shape immediately — no PR introducing a
|
||||
|
|
|
|||
Loading…
Reference in a new issue