mesh/merge-gate checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/repo-check checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/delivery-group group feat/owned-paths checking: 0 of 2 member(s) ready
mesh/delivery superseded: a newer head of the same pull request
Every directory and archive resource carries `unknown`: move-out for a home folder whose program writes nothing there (the node-engine, delivered in mesh-host #117, moves the rest to ~/.local/state/mesh-moved/<module>/ with a list), module for ~/.ssh and ~/.claude, program elsewhere; `knows` keeps what a program or the operator relies on (powerlevel10k's compiled files, i3's scripts and the asus/g14 drop-ins, dunst's slack rule, betterbird's records, node-env's forge credential, issue 1033). Two shared folders are no longer declared. Each module's README says it. checks/owned holds every manifest to it; checks/sshdir stays while main's merge check runs it (issue 1035). Tests that pin a manifest follow the new key only. Reviewed in three rounds.
70 lines
4.6 KiB
Markdown
70 lines
4.6 KiB
Markdown
# mesh-reads
|
|
|
|
A node's files and accounts, read through the mesh (novox/hq ADR 0310, extending ADR 0268 §5; hq to-be 41
|
|
WP8; issue 418). It holds the node seat `node-reads` on every node, the control-node included, so reading a
|
|
file, searching one, listing a directory, the owner and mode of each component of a path and looking up an
|
|
account or a group never go through the login shell's `execute`, and an approval is asked for an act, never
|
|
for a read.
|
|
|
|
## Who it reads as
|
|
|
|
The account `mesh-reads`, which this module makes on every node (`runs-as`, ADR 0259 §8): no login shell, a
|
|
home of its own under `/var/lib`, and no group beside its own. The tool runner serves it in a runtime of its
|
|
own, on its own bus credential, never the machine's runtime, which runs as the operator's account. So the
|
|
node's file modes bound what it sees: a file only the operator, root or a module's own account may read is
|
|
refused by its mode, and the answer says so. It refuses every read when it finds itself running as root.
|
|
|
|
## What it refuses by name
|
|
|
|
Before any read, whatever the file modes would allow (ADR 0310 §5):
|
|
|
|
- **The places the mesh keeps a secret on this node**, which the controller composes from the manifests
|
|
and gives it as `MESH_SECRET_PLACES`: the directory of every module's own secret (its bus credential
|
|
among them), every credential file and grant directory, the vault's directories, and where the
|
|
operator-sealed secrets are kept. Without that list the module does not start.
|
|
- **The known credential files of a machine's programs** (`refuse.go`): an account's `.ssh`, `.gnupg`,
|
|
`.aws`, `.kube`; the agent's `.credentials.json`, `.netrc`, `.pgpass`, `.git-credentials`; private key
|
|
names (`id_ed25519`, `*.key`, `ssh_host_*_key`); `/etc/shadow`; `/etc/ssl/private`, `/etc/wireguard`
|
|
and the network manager's connections.
|
|
|
|
- **Histories and profiles**: shell and program histories (`.zsh_history`, `.bash_history`, `.psql_history`,
|
|
`.viminfo` …), browser and mail profiles (`.mozilla`, `.config/google-chrome`, `.config/chromium` …), a
|
|
process's `environ`, `mem`, `fd`, `map_files`, `root` and `cwd` under `/proc`, and `/etc/rancher` and
|
|
`/etc/kubernetes/admin.conf`.
|
|
|
|
**What was opened is judged, not the name.** The type is checked before the open, so a device or a fifo is
|
|
never opened; the file is opened non-blocking (in a search without following a link), checked again on its
|
|
descriptor, and the path the kernel gives for that descriptor is judged by name like any path asked. A link
|
|
flipped between the check and the open therefore reaches nothing a name refuses, and a deleted file is refused.
|
|
**Limit:** a hard link to a secret file under another name is not seen by the name rule; the file's own mode,
|
|
and the kernel's protected hard links, are what bound it. `stat` and `readlink` say a secret place's owner
|
|
and mode, and mark it, because those are not its content; `list`, `read` and `search` refuse it.
|
|
|
|
## The content rule
|
|
|
|
Every answer passes the content rule's secret class, from `mesh-sdk`'s `outward` package (ADR 0310 §4): a
|
|
line of a file or a matching line shaped like a secret is withheld and its number said, as is a link target
|
|
or an account's words. Every line of a `BEGIN … END` block — a private key's or a certificate's — is withheld whole, because one
|
|
base64 line of a key can pass the rule alone. A path and an entry's name are not judged: they are what the caller named or what the
|
|
file system calls a thing, and the rule would take a temporary directory's or a container layer's name for a
|
|
token.
|
|
|
|
## Its verbs and their bounds
|
|
|
|
| verb | replaces | bounds |
|
|
|---|---|---|
|
|
| `stat` | `stat`, `ls -ld`, `namei -l`, `findmnt -T` | 200 paths, 64 components each; links followed only with `follow` |
|
|
| `readlink` | `readlink`, `readlink -f`, `realpath` | one path |
|
|
| `list` | `ls`, `ls -la` | 2000 entries, cut and said |
|
|
| `read` | `cat`, `head`, `tail`, `less` | 64 KiB, or up to 256 KiB when asked; cut at a line and said; text only |
|
|
| `search` | `grep`, `grep -r`, `grep -F` | a fixed string; 100 matches (500 asked), 4 deep (8 asked), 5000 files, 4 MiB a file, 20 seconds (checked inside a file too); the named path's file system only, the others named; the bound met is said |
|
|
| `account` | `getent passwd`, `getent group`, `id`, `groups` | 2000 accounts and groups; never a password field |
|
|
|
|
No answer is larger than 1 MiB. Nothing here writes a file.
|
|
|
|
## Files it does not know
|
|
|
|
Each directory or archive this module declares says how it treats a file it did not write (ADR 0422, ADR 0416).
|
|
|
|
- `${dir:state}`: everything in it is the program's; the mesh moves nothing out (ADR 0422 §2).
|