| Filename | Latest commit message | Latest commit date |
|---|---|---|
`swarm agent create` failed with "no user store at swarm-authelia-bridge-users.json but users.yml already holds users" on any hive that had users. The guard was correct; what was wrong is that two files both claimed to be canonical for one physical file. The bridge kept a private users.json and rendered users.yml from it, while swarmctl kept its own pair against the same users.yml. A writer whose own JSON was absent could not tell "nothing here yet" from "someone else's users", so it refused to write at all. users.yml becomes the store: read before write, through serde_norway rather than a hand-rolled emitter. Unknown top-level and per-user keys round-trip through `extra`, or whichever process writes second would silently delete what the first added. Validation stays on the write path -- a bare to_string(&store) serialises perfectly and drops the "no control character ever reaches this file" guarantee silently. The seed constant goes with the guard: nothing writes a seed now, an absent file is an empty store, and left as a pub constant it read as if the seed dance were still load-bearing. |
||
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
swarm-authelia-bridge
The only thing allowed to write swarm-authelia's users database.
Why this exists
swarm-controller's CreateIdentity job needs to add an agent as an
authelia subject, but swarm-controller runs unprivileged and does not own
users.yml — a different uid does (authelia-swarm, the user
services.authelia.instances.swarm runs as). Root/CAP_CHOWN/a shared
group were all examined and rejected during this crate's design thread —
see swarmctl/README.md's identical analysis of this same file, written
before this crate existed.
The fix: run this process as User = "authelia-swarm"; instead —
inside the swarm-authelia container, alongside authelia itself — so it
simply owns the file it writes. No elevated privilege anywhere.
Shape
- One endpoint,
POST /requests, body =swarm-authelia-bridge-sock'sBridgeRequestverbatim — one variant today (EnsureAgentIdentity, idempotently ensure an agent exists as an authelia subject). - Bearer-authenticated via authelia's own OIDC token introspection (RFC
7662), against
swarm-controller's existing machine-client identity (already minted for the queue connection) — no new credential. - No restart of authelia after a write — relies on
authentication_backend.file.watch, confirmed working against the pinned 4.39.20 build during this design work. - Network-facing rather than unix-socket-only:
swarm-authelia's container shares the host netns, so the same listener serves both a co-locatedswarm-controller(loopback) and a split-host one (bind wider + firewall) with no separate transport.
Known limitation
swarmctl still writes an independent users.json/users.yml for human
accounts, assuming co-location with swarm-controller's host. Two
canonical stores for the same physical file is a real seam, not solved
here — routing swarmctl through this bridge too is a plausible follow-up,
out of scope for the agent-identity slice this crate shipped with.