mesh-files: the holder of node-files, reads and writes with trash, owned paths and an act log, so file work on a node needs no shell (issue 900, ADR 0394)
mesh/delivery-group group feat/900-node-files checking: composed check out of date: novox/mesh-controller@210f7cf5e64b was judged against trunk 611e2275cf7c, t…
mesh/merge-gate out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
mesh/delivery-group group feat/900-node-files checking: composed check out of date: novox/mesh-controller@210f7cf5e64b was judged against trunk 611e2275cf7c, t…
mesh/merge-gate out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk 3db85a0dde83, the trunk is now 8b53a3663244; judged again on a recheck or when it is merged
mesh/delivery superseded: a newer head of the same pull request
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# mesh-files
|
||||
|
||||
The holder of the node seat `node-files` (novox/hq ADR 0394, issue 900; to-be 41 WP9). It reads and manages
|
||||
the files and accounts of the node it runs on, through the mesh, so nothing about a node's files goes through
|
||||
a shell.
|
||||
|
||||
It replaces `mesh-reads` (ADR 0310), which stays beside it until `mesh-files` is assigned on every node (ADR 0394 §9).
|
||||
|
||||
## Verbs
|
||||
|
||||
The seat's verbs, with the descriptions the controller defines (`internal/catalogue/files.go`).
|
||||
|
||||
- **Reads:** `stat`, `readlink`, `list`, `read`, `search`, `account`. As in mesh-reads: bounded answers, a place a
|
||||
secret is kept refused by name before any read, a line shaped like a secret withheld.
|
||||
- **Writes:** `write` (a text file whole, with an optional mode), `copy`, `move`, `delete` (recursive on
|
||||
request), `mkdir` (parents on request), `chmod` (octal or `u+x,go-w`, recursive on request), `chown` (owner,
|
||||
optional group, recursive on request).
|
||||
- **Trash:** `trash` lists it, `restore` puts an item back.
|
||||
|
||||
Every write verb takes `reason` (required, for the audit trail) and `override` (a reason; needed only for a
|
||||
path a module owns).
|
||||
|
||||
## Rights
|
||||
|
||||
It runs as the tool runner's account, the node's operator account, and declares no account of its own. An act
|
||||
is tried with that account's rights first. Where that fails with a permission error, the act is repeated
|
||||
through `sudo -n` with a fixed binary (cat, cp, mv, stat, chmod, chown, mkdir, rm under `/usr/bin`) and an
|
||||
argument list built from fixed words and one path, never a shell (`sudo.go`). Tests use a fake runner.
|
||||
Not yet through sudo: `stat`, `list`, `readlink` and `search` (they answer what the account reaches and say what it
|
||||
may not); `read` and every write do.
|
||||
|
||||
## Owners and modes
|
||||
|
||||
- `copy` and `move` keep owner and mode (`cp -a`); a copy refuses a target that exists.
|
||||
- A new file or folder takes its folder's owner and group.
|
||||
- An overwrite keeps the overwritten file's owner and mode.
|
||||
|
||||
## Trash
|
||||
|
||||
`delete`, and the overwrite of `write`, first move the old item to `<state>/trash/<id>/item` with a
|
||||
`meta.json` (original path, owner, group, mode, caller, reason, time). `restore` puts it back and refuses when
|
||||
the path is taken now. Entries older than 7 days are emptied on every write call and every `trash` list.
|
||||
|
||||
## Owned paths
|
||||
|
||||
The controller gives the holder `MESH_OWNED_PATHS`, a JSON object from an absolute path to `module (tool)`. A
|
||||
write, move or delete of such a path, anything under it, or (for delete, move and recursive chmod and chown) a
|
||||
folder that holds it, is refused naming the module and tool, unless `override` gives a reason. The override is
|
||||
recorded in the act log and told to the operator, in words without a path, through `operator-channel.tell`.
|
||||
Without the word, the module starts and owns nothing.
|
||||
|
||||
## The act log
|
||||
|
||||
Each write act that was done is one JSON line in `<state>/acts.log`: time, caller, verb, paths, reason, and for
|
||||
an override the override and the owned paths it went through. The caller is the bus user the runtime proved
|
||||
(`stdio.CallerOf`), or `unproven`; it is never read from the arguments. A refused act is not logged.
|
||||
|
||||
## What it refuses
|
||||
|
||||
- A place a secret is kept (`MESH_SECRET_PLACES`, and the known credential files in `refuse.go`) is refused by
|
||||
name for `read`, `list` and `search`. Copying or moving such a place is allowed: nothing is printed.
|
||||
- A copy or move to or from `<node>:/path` is refused: copying between nodes comes in step 2 (issue 903).
|
||||
- A write without a reason; a path that is not absolute; a mode that is not a mode.
|
||||
Reference in New Issue
Block a user