ops-warden/tests/test_safe_unit_runner.py
tegwick b593c87983
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
test: isolate ordinary unit runs from ambient credentials and provider I/O
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
2026-10-17 21:30:12 +02:00

92 lines
3.8 KiB
Python

"""Exercise installed parent and nested child controls, never real credentials."""
import json
import os
from pathlib import Path
import socket
import subprocess
import sys
import pytest
ROOT = Path(__file__).resolve().parents[1]
@pytest.fixture
def guarded(request):
guard = getattr(request.config, '_unit_guard', None)
if guard is None:
pytest.skip('requires make test / scripts/run_unit_tests.py')
return guard
def test_parent_environment_is_allowlisted_and_home_is_temporary(guarded):
# The external regression invocation sets synthetic BAO_TOKEN/VAULT_TOKEN/HOME.
assert 'BAO_TOKEN' not in os.environ
assert 'VAULT_TOKEN' not in os.environ
assert Path(os.environ['TMPDIR']) in Path.home().parents
assert 'PYTHONPATH' not in os.environ
@pytest.mark.parametrize('command', [
['bao', 'token', 'lookup'], ['ssh', 'railiance01'], ['curl', 'http://127.0.0.1:8000'],
[sys.executable, '-c', 'import os; print(os.environ)'],
])
def test_unexpected_process_refused_before_launch(guarded, command):
with pytest.raises(PermissionError, match='unit isolation'):
subprocess.run(command, check=True)
def test_parent_socket_denies_even_unregistered_loopback(guarded):
with pytest.raises(PermissionError, match='unit isolation'):
socket.socket().connect(('127.0.0.1', 8000))
@pytest.mark.parametrize('path', ['/home/synthetic-ambient-unit-fixture/.vault-token',
'/root/.kube/config', '/proc/self/environ',
'/tmp/warden-synthetic-ambient-home/.vault-token'])
def test_ambient_paths_refused_without_opening_them(guarded, path):
with pytest.raises(PermissionError, match='unit isolation'):
Path(path).read_bytes()
def test_symlink_cannot_escape_fixture_root(guarded, tmp_path):
link = tmp_path / 'ambient'
link.symlink_to('/home/synthetic-ambient-unit-fixture/.vault-token')
with pytest.raises(PermissionError, match='unit isolation'):
link.read_bytes()
def test_child_drops_even_synthetic_token_environment(guarded, monkeypatch):
monkeypatch.setenv('BAO_TOKEN', 'synthetic-only-never-a-real-token')
monkeypatch.setenv('VAULT_TOKEN', 'synthetic-only-never-a-real-token')
monkeypatch.setenv('HOME', '/home/synthetic-ambient-unit-fixture')
result = subprocess.run([sys.executable, str(ROOT / 'tests/unit_isolation_probe.py'), 'state'],
capture_output=True, text=True, check=True, env=dict(os.environ))
assert json.loads(result.stdout) == {'bao_token_present': False,
'vault_token_present': False, 'home_in_temporary': True}
@pytest.mark.parametrize('mode', ['socket', 'provider', 'home', 'nested'])
def test_guard_exists_in_each_allowed_python_child(guarded, mode):
result = subprocess.run([sys.executable, str(ROOT / 'tests/unit_isolation_probe.py'), mode],
capture_output=True, text=True, check=True)
assert result.stdout == 'denied\n'
def test_forged_provider_double_refused(guarded, tmp_path):
provider = tmp_path / 'bao'
provider.write_text('#!/bin/bash\necho not-the-reviewed-fixture\n')
provider.chmod(0o700)
with pytest.raises(PermissionError, match='double bytes differ'):
subprocess.run([str(provider), 'token', 'lookup'], check=True)
def test_os_open_truncation_respects_read_only_source_root(guarded, tmp_path, monkeypatch):
# Synthetic readable source outside the guard's writable subtree.
source = tmp_path / 'synthetic-source'
source.write_bytes(b'synthetic public source')
monkeypatch.setattr(guarded, 'temporary', tmp_path / 'writable')
with pytest.raises(PermissionError, match='unit isolation'):
descriptor = os.open(source, os.O_RDONLY | os.O_TRUNC)
os.close(descriptor)
assert source.read_bytes() == b'synthetic public source'