docs: move the socket-dir ownership rule to boundary.md
It was written into gateway.md, which only owns half the story: that doc describes the web.sock path, and before this branch it never mentioned agent.sock at all. Putting a rule shared by hive-c0re, the harness and nginx inside the gateway walkthrough means someone asking "why can't c0re dial agent.sock" has no reason to look there. boundary.md already covers who may touch what across the trust boundary -- including the sibling case of hive-priv's socket getting its mode from the unit rather than the process -- so the rule lives there now, with the three principals as a table. gateway.md keeps a two-line note about the one fact it needs (nginx traverses via o=--x) and links out.
This commit is contained in:
parent
c5cd8f2ac4
commit
289db00321
2 changed files with 39 additions and 17 deletions
|
|
@ -94,6 +94,40 @@ couldn't connect the way the socket unit's `SocketGroup` grant
|
|||
intends. Requiring socket activation everywhere means dev and prod
|
||||
take the exact same path and the group grant always holds.
|
||||
|
||||
### the per-agent socket dir
|
||||
|
||||
`/run/hive-agent/<name>/` is shared by **three principals that share no
|
||||
group**, which is why its mode is what it is:
|
||||
|
||||
| principal | reaches | needs |
|
||||
|---|---|---|
|
||||
| the agent's harness | binds + unlinks `agent.sock`, `web.sock` | owner, `rwx` |
|
||||
| `hive-c0re` | dials `agent.sock` (todo wakes) | traverse |
|
||||
| the gateway's nginx | dials `web.sock` | traverse |
|
||||
|
||||
The last two land in "other", so the dir is **`0751`, owned by the
|
||||
agent's container uid/gid** — `o=--x` is traverse without listing, and
|
||||
both sockets are `0666`, which is all a dialer needs.
|
||||
|
||||
**Ownership is declared, not repaired.** The tmpfiles.d entry written by
|
||||
`SyncAgentTmpfiles` names the uid/gid directly. Do not add a chown
|
||||
alongside it: `d` re-applies on every boot *and* every agent
|
||||
spawn/destroy, so ownership set afterwards is reverted the next time any
|
||||
agent changes — which is exactly how this dir spent a long time at
|
||||
`0777 root root` while a privileged chown appeared to be fixing it.
|
||||
|
||||
The mode is load-bearing, not cosmetic. Write permission on a
|
||||
*directory* is what confers the right to unlink its entries, whoever owns
|
||||
them, and the sticky bit is the only thing that would restrain that (it
|
||||
is not set here). A world-writable socket dir therefore lets anything
|
||||
able to reach the path delete an agent's socket and bind its own — and
|
||||
the gateway container has all of `/run/hive-agent` bind-mounted in.
|
||||
Dropping `o=w` removes that permission rather than qualifying it.
|
||||
|
||||
⚠️ Contrast `/shared`, which *is* sticky world-writable (`1777`): it has
|
||||
many legitimate writers, so sticky is the best available answer there.
|
||||
This dir has exactly one writer, so it needs no world write at all.
|
||||
|
||||
### host admin socket access (`hivectl`)
|
||||
|
||||
`hivectl` drives the whole hive — spawn / kill / destroy / rebuild /
|
||||
|
|
|
|||
|
|
@ -96,23 +96,11 @@ now set unconditionally for every agent. The mechanism:
|
|||
harness's `unlink + bind(2)` cycle on socket replace. Per-agent
|
||||
subdir keeps each agent's container blind to siblings' sockets.
|
||||
|
||||
**Ownership of that dir is declared, not repaired.** The tmpfiles.d
|
||||
entry written by `SyncAgentTmpfiles` names the agent's container
|
||||
uid/gid directly — `d /run/hive-agent/<name> 0751 <uid> <gid> -`.
|
||||
Three principals need the dir and no two share a group: the harness
|
||||
(owner, `rwx`, binds + unlinks its sockets), `hive-c0re` (dials
|
||||
`agent.sock`) and the gateway's nginx (dials `web.sock`, and has all
|
||||
of `/run/hive-agent` bind-mounted in). The latter two only need
|
||||
traverse, which is what `o=--x` grants; both sockets are `0666`.
|
||||
Do **not** reintroduce a chown here: tmpfiles re-applies this entry
|
||||
on every boot *and* every agent spawn/destroy, so any ownership set
|
||||
afterwards is reverted the next time any agent changes. The mode is
|
||||
also load-bearing — write permission on a *directory* is what confers
|
||||
the right to unlink its entries, whoever owns them, and the sticky bit
|
||||
is the only thing that would restrain that (it is not set here). So a
|
||||
world-writable socket dir would let anything able to reach the path
|
||||
replace an agent's socket with its own; `o=--x` removes that
|
||||
permission outright rather than qualifying it.
|
||||
The dir is `0751`, owned by the agent's container uid/gid, so
|
||||
nginx reaches `web.sock` through `o=--x` (traverse) and the socket's
|
||||
own `0666`. The gateway is one of three principals sharing that dir
|
||||
and does not own its ownership rules — see
|
||||
[`docs/boundary.md`](boundary.md#the-per-agent-socket-dir).
|
||||
3. **Marker gate**. After successful `bind_unix`, the harness drops
|
||||
`<dir>/hyperhive-socket-bound` next to the socket. c0re's
|
||||
`agent_sockets::write` filters its JSON map by marker presence —
|
||||
|
|
|
|||
Loading…
Reference in a new issue