155 lines
8.8 KiB
Python
155 lines
8.8 KiB
Python
import contextlib
|
|
import hashlib
|
|
import importlib.util
|
|
import io
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
import tarfile
|
|
import unittest
|
|
from unittest.mock import Mock, patch
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
spec = importlib.util.spec_from_file_location('group_fixture_driver', HERE / 'driver.py')
|
|
f = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(f)
|
|
|
|
|
|
class PlanTests(unittest.TestCase):
|
|
def test_default_and_explicit_plan_do_not_load_containment_or_generate_material(self):
|
|
for args in ([], ['--plan']):
|
|
with patch.object(sys, 'argv', ['fixture', *args]), patch.object(f, 'load_containment') as load, patch.object(f, 'execute') as execute, patch.object(f.secrets, 'token_hex') as generate, contextlib.redirect_stdout(io.StringIO()) as out:
|
|
self.assertEqual(0, f.main())
|
|
self.assertEqual('prepared_not_executed_not_approved', json.loads(out.getvalue())['status'])
|
|
load.assert_not_called(); execute.assert_not_called(); generate.assert_not_called()
|
|
|
|
def test_wrong_manifest_digest_refuses_before_loading_helper(self):
|
|
with patch.object(sys, 'argv', ['fixture', '--execute-reviewed-fixture', '--expected-manifest-sha256', '0' * 64]), patch.object(f, 'load_containment') as load:
|
|
with self.assertRaises(RuntimeError):
|
|
f.main()
|
|
load.assert_not_called()
|
|
|
|
def test_manifest_exact_source_closure_and_images(self):
|
|
manifest = f.reviewed_manifest(hashlib.sha256(f.MANIFEST.read_bytes()).hexdigest())
|
|
self.assertEqual('unix:///var/run/docker.sock', manifest['fixed_endpoint'])
|
|
self.assertEqual('never', manifest['pull_policy'])
|
|
self.assertEqual('network-none', manifest['network'])
|
|
self.assertEqual(0, manifest['limits']['host_ports'])
|
|
self.assertEqual(0, manifest['limits']['host_mounts'])
|
|
self.assertEqual(2, manifest['limits']['max_service_containers'])
|
|
self.assertIn('sha256:', manifest['postgres_image'])
|
|
self.assertIn('sha256:', manifest['python_image'])
|
|
|
|
def test_exact_fresh_names_no_host_network_ports_or_mounts(self):
|
|
manifest = json.loads(f.MANIFEST.read_text())
|
|
session = f.session_plan(manifest, 'f' * 32)
|
|
self.assertEqual(2, len(set(session['containers'])))
|
|
for name in session['containers']:
|
|
args = f.base_args(session, name, 'none')
|
|
self.assertIn('--pull=never', args)
|
|
self.assertIn('--read-only', args)
|
|
self.assertIn('--log-driver', args)
|
|
self.assertIn('net-kingdom.recovery-run=' + 'f' * 32, args)
|
|
self.assertFalse({'--publish', '-p', '--volume', '-v', '--privileged', '--network=host'} & set(args))
|
|
with self.assertRaises(RuntimeError):
|
|
f.session_plan(manifest, 'not-a-fresh-run')
|
|
|
|
def test_tar_private_only_generated_named_material(self):
|
|
raw = f.tar_bytes({'password': b'synthetic-only', 'lldap.toml': b'synthetic-config'})
|
|
with tarfile.open(fileobj=io.BytesIO(raw)) as archive:
|
|
self.assertTrue(all(member.uid == member.gid == 1000 and member.mode == 0o600 for member in archive))
|
|
for path in ('../outside', '/absolute', 'path/../../escape'):
|
|
with self.assertRaises(RuntimeError):
|
|
f.tar_bytes({path: b'synthetic'})
|
|
|
|
def test_failure_still_invokes_existing_exact_cleanup(self):
|
|
manifest = json.loads(f.MANIFEST.read_text())
|
|
adapter = Mock()
|
|
adapter.command.side_effect = RuntimeError('synthetic transport fault')
|
|
result = {'status': 'failed'}
|
|
with self.assertRaises(RuntimeError):
|
|
f.execute(manifest, adapter, result)
|
|
adapter.cleanup.assert_called_once()
|
|
session = adapter.cleanup.call_args[0][0]
|
|
self.assertEqual(session['containers'], result['session']['containers'])
|
|
self.assertTrue(result['daemon_request_uncertain'])
|
|
self.assertEqual('failed', result['status'])
|
|
|
|
def test_every_declared_source_input_exists_and_schema_does_not_admit_epoch(self):
|
|
source = HERE.parent / 'postimage/identity-provisioner'
|
|
for name in ('provisioner.py', 'group_provenance.py', 'group_provenance_postgres.py', 'migrations/group_journal_postgres_v1.sql'):
|
|
self.assertTrue((source / name).is_file())
|
|
self.assertTrue((HERE / 'test_service_groups.py').is_file())
|
|
schema = (source / 'migrations/group_journal_postgres_v1.sql').read_text()
|
|
self.assertNotIn('INSERT INTO', schema)
|
|
self.assertIn('DEFAULT true', schema)
|
|
self.assertIn('active boolean UNIQUE', schema)
|
|
|
|
def test_exact_producer_interpreter_has_no_path_or_venv_fallback(self):
|
|
manifest = json.loads(f.MANIFEST.read_text())
|
|
self.assertEqual('/usr/local/bin/python3', f.helper_python(manifest))
|
|
for value in ('python3', '/opt/venv/bin/python', '/usr/bin/python3', None):
|
|
with self.assertRaises(RuntimeError):
|
|
f.helper_python({**manifest, 'helper_interpreter': value})
|
|
compile(f.INTERPRETER_PROBE, 'public-interpreter-probe', 'exec')
|
|
source = (HERE / 'driver.py').read_text()
|
|
self.assertIn("'helper_interpreter_verified_before_candidate_import'", source)
|
|
self.assertNotIn("'--entrypoint', 'python3'", source)
|
|
|
|
def test_probe_syntax_and_no_network_expansion(self):
|
|
compile((HERE / 'probe.py').read_text(), str(HERE / 'probe.py'), 'exec')
|
|
compile(f.IMPORT, 'private-import', 'exec')
|
|
self.assertNotIn('subprocess', (HERE / 'probe.py').read_text())
|
|
self.assertIn("'host': '127.0.0.1'", (HERE / 'probe.py').read_text())
|
|
|
|
|
|
class DiagnosticTests(unittest.TestCase):
|
|
def test_fixed_error_class_sqlstate_and_no_exception_values(self):
|
|
class OperationalError(RuntimeError):
|
|
sqlstate = '28P01'
|
|
original = OperationalError('password=DO_NOT_DISCLOSE dsn=private')
|
|
wrapper = RuntimeError('another secret')
|
|
wrapper.__cause__ = original
|
|
value = f.diagnostics.error_metadata(wrapper, 'bootstrap_connect_wait')
|
|
self.assertEqual({'stage': 'bootstrap_connect_wait', 'exception_class': 'RuntimeError', 'sqlstate': '28P01'}, value)
|
|
self.assertNotIn('secret', json.dumps(value))
|
|
original.sqlstate = 'password=DO_NOT_DISCLOSE'
|
|
self.assertIsNone(f.diagnostics.error_metadata(original, 'bootstrap_connected')['sqlstate'])
|
|
|
|
def test_failed_helper_is_checkpointed_before_caller_refusal(self):
|
|
result, captured = {}, []
|
|
diagnostic = {'stage': 'bootstrap_migration', 'exception_class': 'SyntaxError', 'sqlstate': '42601'}
|
|
raw = '\n'.join(json.dumps(v) for v in [
|
|
{'event': 'stage', 'stage': 'bootstrap_connected'},
|
|
{'event': 'stage', 'stage': 'bootstrap_migration'},
|
|
{'status': 'failed', 'failure': 'synthetic_pg_oracle_failed', 'diagnostic': diagnostic}])
|
|
value = f.retain_helper_result(result, 'bootstrap', raw, lambda: captured.append(json.loads(json.dumps(result))))
|
|
with self.assertRaises(RuntimeError): f.require(value['status'] == 'passed')
|
|
self.assertEqual(diagnostic, captured[0]['helper_diagnostics']['bootstrap']['diagnostic'])
|
|
self.assertEqual(['bootstrap_connected', 'bootstrap_migration'], captured[0]['helper_diagnostics']['bootstrap']['stages'])
|
|
|
|
def test_untrusted_frames_cannot_add_values_or_unknown_stage(self):
|
|
bad = [[], {'event': 'stage', 'stage': 'dsn=private'},
|
|
{'event': 'stage', 'stage': 'probe_entry', 'password': 'private'},
|
|
{'status': 'failed', 'failure': 'synthetic_pg_oracle_failed', 'diagnostic': {'stage': 'bootstrap_ensure', 'exception_class': 'password', 'sqlstate': None}}]
|
|
for item in bad:
|
|
with self.assertRaises((RuntimeError, ValueError, TypeError)):
|
|
f.diagnostics.parse_frames(json.dumps(item))
|
|
for raw in ('x' * 32769, '\n'.join('{}' for _ in range(97))):
|
|
with self.assertRaises(RuntimeError): f.diagnostics.parse_frames(raw)
|
|
|
|
def test_bootstrap_oracles_have_ordered_public_markers(self):
|
|
source = (HERE / 'probe.py').read_text()
|
|
labels = ['bootstrap_connect_wait', 'bootstrap_connected', 'bootstrap_schema', 'bootstrap_migration',
|
|
'bootstrap_epoch_insert', 'bootstrap_role_create', 'bootstrap_runtime_grants',
|
|
'bootstrap_checkpoint_init', 'bootstrap_directory_init', 'bootstrap_ensure',
|
|
'bootstrap_ensure_readback', 'bootstrap_runtime_ddl_refusal', 'bootstrap_complete']
|
|
offsets = [source.index("stage('" + label + "')") for label in labels]
|
|
self.assertEqual(sorted(offsets), offsets)
|
|
driver = (HERE / 'driver.py').read_text()
|
|
self.assertLess(driver.index("mark('postgres_initdb')"), driver.index("mark('postgres_launch')"))
|
|
self.assertIn("result['postgres_initdb_complete']", driver)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|