docs/security: name all 34 PrivRequest variants, not 17
`security.md` introduces its hive-priv table as "Narrow interface — `PrivRequest` variants map 1:1 to specific known operations". The table named 17 of 34, so the claim it was making was only half-checkable by the reader it was written for. Two whole subsystems were absent rather than stragglers: btrfs subvolume + snapshot management (9 verbs) and per-agent external forge accounts (2), plus `SendAgentSnapshotToFd`, which passes a file descriptor across the boundary via SCM_RIGHTS — the kind of verb someone reads a security page to find. The table had already been resynced by hand once, in June, and drifted again within three months. mara's call was to keep it exhaustive rather than summarise by subsystem: the swarm-level operations are expected to go away, so the row count is at its peak now and shrinks from here. Rows for the 17 missing variants, each naming what the helper actually runs. Three of them carry the constraint that makes them safe rather than just the command, because that is what the surrounding section is for: `ControlInfraContainer`'s allowlist is the `InfraContainer` enum (serde rejects unknown names at the wire boundary, and `hive-c0re` has no variant); `WriteAgentExtraForgeAccount`'s `label` reaches a filename and is validated as a plain identifier first; `SendAgentSnapshotToFd` requires exactly one descriptor and refuses one arriving alongside any other operation. Prose is active voice throughout the new rows — "hive-priv validates `label`" rather than "`label` is validated" — since the question a reader brings to this table is which component enforces what. Verified with a variant-vs-page diff carrying its own controls (extractor count, page-readable, a present variant resolves, an invented one does not): 34 named, 0 absent. vale is unchanged from main's baseline for this file, 0 errors and 13 warnings on both sides. Closes #4222.
This commit is contained in:
parent
2f792a868c
commit
2ec5c9433f
1 changed files with 32 additions and 16 deletions
|
|
@ -237,7 +237,7 @@ for every operation that genuinely requires root.
|
||||||
known operations; there is no arbitrary command pass-through:
|
known operations; there is no arbitrary command pass-through:
|
||||||
|
|
||||||
| Operation | What it runs |
|
| Operation | What it runs |
|
||||||
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------- |
|
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `StartContainer` / `StopContainer` | `nixos-container start/stop <name>` |
|
| `StartContainer` / `StopContainer` | `nixos-container start/stop <name>` |
|
||||||
| `KillContainer` | `machinectl kill <machine> --signal=SIGKILL` (`nixos-container` has no kill verb) |
|
| `KillContainer` | `machinectl kill <machine> --signal=SIGKILL` (`nixos-container` has no kill verb) |
|
||||||
| `CreateContainer` / `UpdateContainer` | `nixos-container create/update <name> --flake <ref>` |
|
| `CreateContainer` / `UpdateContainer` | `nixos-container create/update <name> --flake <ref>` |
|
||||||
|
|
@ -252,6 +252,22 @@ known operations; there is no arbitrary command pass-through:
|
||||||
| `RunForgeAdmin` | `nixos-container run hive-forge -- runuser -u forgejo -- forgejo admin <args>` |
|
| `RunForgeAdmin` | `nixos-container run hive-forge -- runuser -u forgejo -- forgejo admin <args>` |
|
||||||
| `WriteAgentForgeToken` / `WriteAgentMatrixToken` | write `0600` credential file into agent state dir |
|
| `WriteAgentForgeToken` / `WriteAgentMatrixToken` | write `0600` credential file into agent state dir |
|
||||||
| `RestartMatrixDaemon` | `systemctl --machine=h-<name> restart hive-matrix-daemon.service` |
|
| `RestartMatrixDaemon` | `systemctl --machine=h-<name> restart hive-matrix-daemon.service` |
|
||||||
|
| `ControlInfraContainer` | `systemctl <action> container@<container>.service` — the `InfraContainer` enum is the allowlist, and serde rejects unknown names at the wire boundary (`hive-c0re` has no variant, so no request can name it) |
|
||||||
|
| `SyncAgentTmpfiles` | write `/etc/tmpfiles.d/hyperhive-agents.conf` for the agent set, then `systemd-tmpfiles --create` |
|
||||||
|
| `SetAgentPaused` | create / remove the `<state>/<name>/harness/paused` marker that parks an agent's turn loop |
|
||||||
|
| `WriteAgentGithubToken` | write `0600` `github-token` into agent state dir (same semantics as the forge/matrix token writes) |
|
||||||
|
| `WriteAgentExtraForgeAccount` / `DeleteAgentExtraForgeAccount` | write / remove `forge-<label>-token` + a `forge-<label>.json` base-URL sidecar, both `0600`. hive-priv validates `label` as a plain identifier before it reaches the filename — an unchecked one traverses out of the state dir |
|
||||||
|
| `RegisterCiRunner` | write `/run/hive-ci/runner-token` (host path, root-owned) then `systemctl --machine=hive-ci restart gitea-runner-hive.service`. Only the registration token crosses; the forge admin token never enters the container |
|
||||||
|
| `EnsureAgentSubvolume` | `btrfs subvolume create <state>/<name>` for a new agent — no-op when the path exists or the filesystem isn't btrfs |
|
||||||
|
| `UpgradeAgentSubvolume` | migrate an existing plain state dir into a subvolume: create, `cp -a --reflink=auto`, atomic swap. Operator opt-in, and the caller stops the agent first |
|
||||||
|
| `DeleteAgentSubvolume` | `btrfs subvolume delete <state>/<name>` — purge path only, never a plain destroy |
|
||||||
|
| `EnsureBtrfsQuota` | `btrfs quota enable <AGENT_STATE_ROOT>`. Operator opt-in — enabling forces a full rescan |
|
||||||
|
| `ReadSubvolumeUsage` | `btrfs qgroup show -f --raw <state>/<name>` |
|
||||||
|
| `SetSubvolumeQuota` | `btrfs qgroup limit <bytes\|none> <state>/<name>` |
|
||||||
|
| `SnapshotAgentSubvolume` | `btrfs subvolume snapshot -r <agent_root> <snapshot_path>` — the frozen point-in-time copy a migration streams from |
|
||||||
|
| `DeleteAgentSnapshot` | `btrfs subvolume delete <snapshot_path>` |
|
||||||
|
| `SendAgentSnapshotToFile` | `btrfs send [-p <parent>] <snapshot>` into a bare filename under `MIGRATE_STAGING_ROOT`; refuses to overwrite an existing export |
|
||||||
|
| `SendAgentSnapshotToFd` | `btrfs send [-p <parent>] <snapshot>` into a **file descriptor passed with the request** (`SCM_RIGHTS`). hive-c0re connects to the peer and hands over the connected socket, so hive-priv never learns an address or protocol. hive-priv requires exactly one descriptor here, and refuses one that arrives alongside any other operation |
|
||||||
|
|
||||||
**Container allowlist** — `hive-priv` validates every request against
|
**Container allowlist** — `hive-priv` validates every request against
|
||||||
an allowlist before any operation: the allowlist accepts only names
|
an allowlist before any operation: the allowlist accepts only names
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue