Files
archy/scripts/tests/test_backend_isolated_runner.py
archipelago 64f0bc36dc test: qualify Gashboard through fixed backend isolation target
Add ARCHY_TEST_PACKAGE=gashboard with hardcoded Node test entry, synthetic data settings, private network/PID namespace and wallet/container/app tmpfs masks. Reject arbitrary command arguments and conflicting fixture modes; keep existing Rust/C01/container paths intact. Retain only the Rust runner DAC traversal capability for the read-only worktree.

Six runner regressions pass, including existing modes; update the existing C01 test sudo mock for its exec-profile inventory call. Nine actual Gashboard API regressions pass in the new isolated systemd namespace with patched Zod/Express dependencies. Initial namespace file-access failure preserved before aligning traversal capability. No production app entry or installed service was run.
2026-11-09 17:04:12 -05:00

169 lines
8.8 KiB
Python

#!/usr/bin/env python3
import os
import hashlib
import json
import pathlib
import subprocess
import tempfile
import unittest
ROOT = pathlib.Path(__file__).resolve().parents[2]
RUNNER = ROOT / "scripts" / "test-backend-isolated.sh"
class BackendIsolationRunnerTests(unittest.TestCase):
def test_gashboard_has_fixed_entry_and_wallet_network_pid_isolation(self):
with tempfile.TemporaryDirectory() as temporary:
temp = pathlib.Path(temporary)
repo = temp / 'repo'
entry = repo / 'scripts/tests/gashboard-isolated-entry.mjs'
entry.parent.mkdir(parents=True)
entry.write_text('// fixture path only; never executed')
(repo / 'docker/gashboard/apps/api/node_modules/tsx').mkdir(parents=True)
fake_bin = temp / 'bin'
fake_bin.mkdir()
for name in ('node', 'cargo'):
executable = fake_bin / name
executable.write_text('#!/bin/sh\nexit 99\n')
executable.chmod(0o700)
sudo = fake_bin / 'sudo'
sudo.write_text(
'#!/usr/bin/python3\nimport json, os, sys\n'
'if sys.argv[1:] == ["-n", "true"]: raise SystemExit(0)\n'
'assert sys.argv[1:3] == ["-n", "systemd-run"]\n'
'with open(os.environ["FIXTURE_LOG"], "w") as f: json.dump(sys.argv[1:], f)\n')
sudo.chmod(0o700)
log = temp / 'systemd.json'
subprocess.run(['bash', str(RUNNER)], check=True, env={**os.environ,
'PATH': str(fake_bin) + ':' + os.environ['PATH'],
'ARCHY_TEST_REPO': str(repo), 'ARCHY_TEST_PACKAGE': 'gashboard',
'ARCHY_TEST_ISOLATOR': 'systemd', 'FIXTURE_LOG': str(log)})
args = json.loads(log.read_text())
self.assertEqual(args[-2:], [str(fake_bin / 'node'), str(entry)])
for arg in ('--property=PrivateNetwork=yes', '--property=PrivateDevices=yes',
'--property=ProtectSystem=strict', '--property=NoNewPrivileges=yes',
'--setenv=ARCHY_TEST_ISOLATED=1', '/usr/bin/unshare', '--pid',
'--mount-proc', '--kill-child', '--bounding-set=-all,+dac_override'):
self.assertIn(arg, args)
masks = next(arg for arg in args if arg.startswith('--property=TemporaryFileSystem='))
for directory in ('/run', '/var/lib/archipelago', '/var/lib/containers', '/root', '/tmp', '/data', '/app'):
self.assertIn(directory + ':rw', masks)
self.assertNotIn('cargo', ' '.join(args))
def test_gashboard_rejects_commands_and_other_fixture_modes(self):
env = {**os.environ, 'ARCHY_TEST_PACKAGE': 'gashboard', 'ARCHY_TEST_ISOLATOR': 'systemd'}
for arguments, extra, message in [
(['arbitrary-command'], {}, 'accepts no command arguments'),
([], {'ARCHY_TEST_ISOLATOR': 'podman'}, 'require the systemd fixture namespace'),
([], {'ARCHY_TEST_TERMINAL_FIXTURE': '1'}, 'cannot be combined'),
]:
with self.subTest(arguments=arguments, extra=extra):
result = subprocess.run(['bash', str(RUNNER), *arguments], env={**env, **extra}, capture_output=True, text=True)
self.assertEqual(result.returncode, 2)
self.assertIn(message, result.stderr)
def test_c01_startup_adds_masks_without_replacing_wallet_and_bus_isolation(self):
with tempfile.TemporaryDirectory() as temporary:
temp = pathlib.Path(temporary)
fake_bin = temp / 'bin'
fake_bin.mkdir()
executable = fake_bin / 'fixture-binary'
executable.write_text('#!/bin/sh\nexit 0\n')
executable.chmod(0o700)
cargo = fake_bin / 'cargo'
cargo.write_text(
'#!/usr/bin/python3\nimport json, os, sys\n'
'assert "--no-run" in sys.argv\n'
'print(json.dumps({"reason":"compiler-artifact","profile":{"test":True},'
'"executable":os.environ["FIXTURE_BINARY"]}))\n')
cargo.chmod(0o700)
sudo = fake_bin / 'sudo'
sudo.write_text(
'#!/usr/bin/python3\nimport json, os, sys\n'
'if sys.argv[1:] == ["-n", "true"]: raise SystemExit(0)\n'
'if sys.argv[1:] == ["-n", "aa-status", "--json"]:\n'
' print(json.dumps({"profiles":{os.environ["FIXTURE_PROFILE"]:"enforce"},"processes":{}})); raise SystemExit(0)\n'
'assert sys.argv[1:3] == ["-n", "systemd-run"]\n'
'with open(os.environ["FIXTURE_LOG"], "w") as f: json.dump(sys.argv[1:], f)\n')
sudo.chmod(0o700)
log = temp / 'systemd-arguments.json'
subprocess.run(['bash', str(RUNNER), 'fixture-only', '--ignored'], check=True,
env={**os.environ, 'PATH': f'{fake_bin}:' + os.environ['PATH'],
'ARCHY_TEST_ISOLATOR': 'systemd', 'ARCHY_TEST_C01_STARTUP': '1',
'ARCHY_TEST_C01_BINARY': str(executable), 'ARCHY_TEST_THREADS': '1',
'FIXTURE_BINARY': str(executable), 'FIXTURE_LOG': str(log),
'FIXTURE_PROFILE': 'archipelago-manager-exec-' + hashlib.sha256((ROOT / 'image-recipe/configs/archipelago-manager-exec.profile.in').read_bytes()).hexdigest(),
'RUST_MIN_STACK': '16777216'})
args = json.loads(log.read_text())
masks = [arg for arg in args if arg.startswith('--property=TemporaryFileSystem=')]
self.assertEqual(len(masks), 1)
for directory in ('/run', '/var/lib/archipelago', '/var/lib/containers', '/root', '/opt/archipelago', '/etc/archipelago'):
self.assertIn(directory + ':rw', masks[0].split('=', 2)[2].split())
for argument in ('--property=PrivateNetwork=yes', '--property=PrivateDevices=yes',
'--property=ProtectSystem=strict', '--property=NoNewPrivileges=yes',
'--setenv=ARCHY_TEST_ISOLATED=1', '--setenv=RUST_MIN_STACK=16777216',
'--setenv=ARCHY_TEST_C01_STARTUP=1', '--test-threads=1'):
self.assertIn(argument, args)
self.assertIn('--setenv=ARCHY_TEST_C01_BINARY=' + str(executable), args)
def test_c01_startup_refuses_an_unsupported_isolator_before_compiling(self):
result = subprocess.run(['bash', str(RUNNER)], capture_output=True, text=True,
env={**os.environ, 'ARCHY_TEST_ISOLATOR': 'podman', 'ARCHY_TEST_C01_STARTUP': '1'})
self.assertEqual(result.returncode, 2)
self.assertIn('requires the systemd fixture namespace', result.stderr)
def test_podman_mode_separates_build_and_networkless_execution(self):
with tempfile.TemporaryDirectory() as temporary:
temp = pathlib.Path(temporary)
fake_bin = temp / "bin"
fake_bin.mkdir()
log = temp / "podman.log"
podman = fake_bin / "podman"
podman.write_text(
"#!/usr/bin/env bash\n"
"printf '%s\\0' \"$@\" >> \"$PODMAN_TEST_LOG\"\n"
"printf '\\n' >> \"$PODMAN_TEST_LOG\"\n"
"if [[ \" $* \" == *' cargo test '* ]]; then\n"
" printf '%s\\n' '{\"reason\":\"compiler-artifact\",\"profile\":{\"test\":true},\"executable\":\"/workspace/core/target/debug/archy-test\"}'\n"
"fi\n"
)
podman.chmod(0o700)
cargo_home = temp / "cargo"
env = os.environ.copy()
env.update(
{
"PATH": f"{fake_bin}:{env['PATH']}",
"PODMAN_TEST_LOG": str(log),
"ARCHY_TEST_ISOLATOR": "podman",
"ARCHY_TEST_REPO": str(ROOT),
"ARCHY_TEST_IMAGE": "example.invalid/ci@sha256:test",
"ARCHY_TEST_CARGO_HOME": str(cargo_home),
}
)
subprocess.run([str(RUNNER)], env=env, check=True)
invocations = [
line.replace("\0", " ") for line in log.read_text().splitlines()
]
self.assertEqual(len(invocations), 2)
self.assertIn("--network=pasta", invocations[0])
self.assertIn(f"{ROOT}:/workspace:rw,Z", invocations[0])
self.assertIn("--network=none", invocations[1])
self.assertIn(f"{ROOT}:/workspace:ro,Z", invocations[1])
self.assertIn("ARCHY_TEST_ISOLATED=1", invocations[1])
def test_unknown_isolator_fails_closed(self):
result = subprocess.run(
[str(RUNNER)],
env={**os.environ, "ARCHY_TEST_ISOLATOR": "unknown"},
capture_output=True,
text=True,
)
self.assertEqual(result.returncode, 2)
self.assertIn("must be systemd or podman", result.stderr)
if __name__ == "__main__":
unittest.main()