The packet filter's tools are a bundle the node's runtime serves; its container goes (hq to-be 38 WP4)

nftables drops its container, NET_ADMIN, the container-runtime capability, the runtime base
images and the Dockerfile; its tools are declared as a TypeScript bundle the toolchain compiles
and node-tools loads on every node. The runtime runs as the operator's account, so the tool
runs the filter's commands through sudo without a prompt when it is not root (ADR 0175 §4);
the filter file is the path the manifest's filtering names, no container env carrying it.
This commit is contained in:
jochen
2026-10-03 12:46:35 +02:00
parent 853ace3828
commit 5d01258b67
5 changed files with 38 additions and 64 deletions
+22 -3
View File
@@ -2,7 +2,8 @@
// rule set from every module's `listens` and writes it to the filter file (ADR 0045); the module
// loads it through its own unit. This code reads the filter back as the machine enforces it, reloads
// the mesh's own table, and removes one thing the mesh did not write when the operator names it
// (ADR 0168, ADR 0170) — the seat's three verbs, over the machine's own tools.
// (ADR 0168, ADR 0170) — the seat's three verbs, over the machine's own tools, which it runs as root
// through sudo when the runtime loading it is not (ADR 0175).
import { execFile } from "node:child_process";
import { promisify } from "node:util";
@@ -12,9 +13,27 @@ const execFileP = promisify(execFile);
/** A command runner, so the acts can be tested without a packet filter. */
export type Runner = (cmd: string, args: string[]) => Promise<string>;
/** The command as it is run: as given when this process is root, else through sudo without a
* prompt. The runtime that loads this bundle runs as the node's operator account, which may
* escalate as the operator would (novox/hq ADR 0175 §4); the packet filter answers only to root,
* listing included. A command sudo refuses fails by name, saying what the account lacks. */
export function escalated(cmd: string, args: string[], uid: number | undefined = process.getuid?.()): [string, string[]] {
if (uid === 0) return [cmd, args];
return ["sudo", ["-n", cmd, ...args]];
}
export const execRunner: Runner = async (cmd, args) => {
const { stdout } = await execFileP(cmd, args, { maxBuffer: 16 * 1024 * 1024 });
return stdout;
const [program, argv] = escalated(cmd, args);
try {
const { stdout } = await execFileP(program, argv, { maxBuffer: 16 * 1024 * 1024 });
return stdout;
} catch (err) {
const stderr = String((err as { stderr?: string }).stderr ?? "").trim();
if (program === "sudo" && /a password is required|not allowed to execute|not in the sudoers/.test(stderr)) {
throw new Error(`${cmd} needs root and the runtime's account may not escalate without a prompt: ${stderr}`);
}
throw err;
}
};
/** The mesh's own tables, which `remove` never touches. */