#!/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()