From 8d9e4bdb77b6b3754c15a1f1c1f1746beaea2fed Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 22 Sep 2026 19:00:39 +0200 Subject: [PATCH] Adoption bed: the container probe asks the guard's promise, admitting the container interface through the found firewall for itself alone --- test/integration/adoption.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/integration/adoption.test.ts b/test/integration/adoption.test.ts index ac489ee..99f5e34 100644 --- a/test/integration/adoption.test.ts +++ b/test/integration/adoption.test.ts @@ -404,7 +404,7 @@ const TITLE: Record = { A3: "given another registry port, the adopted foundation comes up — and stays on that port as modules", B1: "nothing that serves changed: the service answers, its file and container are untouched, the firewall gained only the mesh's marked rules", B2: "the store is unreachable from outside, before and after the found firewall reloads; the bus answers a machine not yet enrolled", - B4: "the store is reachable from a container on the node itself", + B4: "the guard lets the machine's own containers reach the store (with the found firewall admitting them)", C1: "a second machine enrols through the found firewall and joins the private network", B3: "the store is reachable over the private network", C2: "after the found firewall reloads, the openings are there and the mesh still works", @@ -606,7 +606,15 @@ before(async () => { // reaches a published port through the runtime's proxy, on the incoming path, not the forwarded. await step("B4", ["A3"], async () => { const said: string[] = []; + // What this asks is the guard's promise: it never refuses the machine's own containers. The + // found firewall stays in force (ADR 0100) and denies inbound by default, and a container on + // the store's own network reaches its published port through the runtime's proxy — inbound, + // not forwarded — so the operator's firewall has to admit the container interface for any + // container to get there, on an adopted node as on a converged one. The probe admits it for + // itself alone, and takes the rule away again. + await must(CONTROL, `ufw allow in on docker0 to any port ${STORE_PORT} proto tcp comment bed-probe-only`); const fromContainer = await on(CONTROL, `docker run --rm ${ALPINE} nc -zv -w 3 ${ANCHOR} ${STORE_PORT} 2>&1`, 180_000); + await must(CONTROL, `ufw delete allow in on docker0 to any port ${STORE_PORT} proto tcp comment bed-probe-only`); if (!fromContainer.ok) { // Evidence, so the cause can be read from this run rather than guessed at the next one. const evidence = await on(CONTROL, [