events: an e2e test — an emitted event reaches the audit trail over the mesh's broker #2
@@ -578,11 +578,24 @@ test("a machine filters exactly what its modules declared, and nothing else", {
|
||||
`"resources":[]}' > /tmp/talker.json`);
|
||||
// The rule set goes where this machine's nftables unit reads from, and the unit is declared to
|
||||
// reflect it. No command anywhere.
|
||||
// The module ships the unit that loads its rules, rather than using the one the distribution's
|
||||
// nftables package provides. That unit is `Type=oneshot` with no `RemainAfterExit`, so it does
|
||||
// its work and goes inactive — and a host asked for a service that is "running" reports, quite
|
||||
// correctly, that it is stopped. There is no state in the vocabulary for "ran and exited having
|
||||
// done its job", so a module that wants one brings a unit that stays.
|
||||
//
|
||||
// Which is also the right shape: how a machine enforces rules is a fact about the machine, and
|
||||
// the mesh has no business depending on what a distribution happens to package.
|
||||
await must("anchor", `printf %s '{"module":"firewall","version":"1",` +
|
||||
`"capabilities":["firewall"],` +
|
||||
`"filtering":{"into":"/etc/nftables.conf"},` +
|
||||
`"filtering":{"into":"/etc/mesh/filter.nft"},` +
|
||||
`"resources":[{"id":"nftables","type":"package","package":"nftables"},` +
|
||||
`{"id":"filter","type":"service","unit":"nftables.service","state":"running",` +
|
||||
`{"id":"dir","type":"directory","path":"/etc/mesh","mode":"0755"},` +
|
||||
`{"id":"unit","type":"file","path":"/etc/systemd/system/mesh-filter.service",` +
|
||||
`"mode":"0644","content":"[Unit]\\nDescription=What the mesh computed for this machine\\n` +
|
||||
`[Service]\\nType=oneshot\\nRemainAfterExit=yes\\n` +
|
||||
`ExecStart=/usr/bin/nft -f /etc/mesh/filter.nft\\n[Install]\\nWantedBy=multi-user.target\\n"},` +
|
||||
`{"id":"filter","type":"service","unit":"mesh-filter.service","state":"running",` +
|
||||
`"boot":"enabled","restart-on":["filtering"]}]}' > /tmp/firewall.json`);
|
||||
for (const f of ["talker", "firewall"]) {
|
||||
await must("anchor", `docker cp /tmp/${f}.json mesh-control:/${f}.json`);
|
||||
@@ -593,7 +606,7 @@ test("a machine filters exactly what its modules declared, and nothing else", {
|
||||
await mesh("push laptop");
|
||||
await new Promise((r) => setTimeout(r, 20_000));
|
||||
|
||||
const written = await must("laptop", `cat /etc/nftables.conf`);
|
||||
const written = await must("laptop", `cat /etc/mesh/filter.nft`);
|
||||
// A rule names its source. Not decoration: it is the only thing that answers "why is this open".
|
||||
assert.match(written, /# talker . the thing this test is about/,
|
||||
`the rule does not name what caused it:\n${written}`);
|
||||
@@ -719,7 +732,15 @@ test("the builder is a module the mesh assigns, with a credential the mesh deliv
|
||||
`> /root/built/module.json`);
|
||||
await must("anchor", `cd /root/built && git init -q . && git add -A && ` +
|
||||
`git -c user.email=lab -c user.name=lab commit -qm built`);
|
||||
await mesh("build /root/built --wait 300s", 420_000);
|
||||
try {
|
||||
await mesh("build /root/built --wait 300s", 420_000);
|
||||
} catch (why) {
|
||||
// The builder's own account of itself. Without it the failure is "nothing consumed the
|
||||
// queue", which names no cause and is the same sentence whether the credential was refused,
|
||||
// the queue was never declared, or the process died three seconds in.
|
||||
const said = (await on("anchor", `docker logs mesh-builder 2>&1 | tail -40`)).out;
|
||||
throw new Error(`${(why as Error).message}\n\nwhat the builder said:\n${said}`);
|
||||
}
|
||||
|
||||
// Naming the module, and not merely containing its name: `builds` says "nothing has been built
|
||||
// yet" when there is nothing, and that sentence contains the word this was matching on.
|
||||
|
||||
Reference in New Issue
Block a user