50 lines
2.9 KiB
Python
50 lines
2.9 KiB
Python
|
|
import contextlib
|
||
|
|
import hashlib
|
||
|
|
import importlib.util
|
||
|
|
import io
|
||
|
|
import json
|
||
|
|
from pathlib import Path
|
||
|
|
import sys
|
||
|
|
import tempfile
|
||
|
|
import unittest
|
||
|
|
from unittest.mock import patch
|
||
|
|
|
||
|
|
ROOT=Path(__file__).resolve().parents[1]
|
||
|
|
spec=importlib.util.spec_from_file_location('fixture_runner',ROOT/'tests/run_isolated_keycape_native_fixture.py')
|
||
|
|
f=importlib.util.module_from_spec(spec);spec.loader.exec_module(f)
|
||
|
|
|
||
|
|
class FixturePreparationTests(unittest.TestCase):
|
||
|
|
def test_default_plan_neither_runs_docker_nor_generates_materials(self):
|
||
|
|
output=io.StringIO()
|
||
|
|
with patch.object(sys,'argv',['fixture','--plan']),patch.object(f.s,'run') as run,patch.object(f,'materials') as materials,patch.object(f.s.local,'preflight') as preflight,contextlib.redirect_stdout(output):
|
||
|
|
self.assertEqual(f.main(),0)
|
||
|
|
run.assert_not_called();materials.assert_not_called();preflight.assert_not_called()
|
||
|
|
manifest=json.loads(output.getvalue())
|
||
|
|
self.assertEqual(manifest['status'],'prepared_not_executed_not_approved')
|
||
|
|
self.assertEqual(manifest['fixed_endpoint'],'unix:///var/run/docker.sock')
|
||
|
|
def test_wrong_reviewed_manifest_hash_stops_before_preflight_or_generation(self):
|
||
|
|
with patch.object(sys,'argv',['fixture','--execute-reviewed-fixture','--expected-manifest-sha256','0'*64]),patch.object(f.s,'run') as run,patch.object(f,'materials') as materials,patch.object(f.s.local,'preflight') as preflight:
|
||
|
|
with self.assertRaises(RuntimeError):f.main()
|
||
|
|
run.assert_not_called();materials.assert_not_called();preflight.assert_not_called()
|
||
|
|
def test_untyped_or_malformed_public_digest_refused(self):
|
||
|
|
for invalid in ('0'*64, 'sha256:'+'A'*64, 'sha256:'+'0'*63, None):
|
||
|
|
with self.subTest(invalid_type=type(invalid).__name__), tempfile.TemporaryDirectory() as temporary:
|
||
|
|
manifest=json.loads(f.MANIFEST.read_text())
|
||
|
|
first=next(iter(manifest['source_sha256']))
|
||
|
|
manifest['source_sha256'][first]=invalid
|
||
|
|
path=Path(temporary)/'manifest.json'
|
||
|
|
path.write_text(json.dumps(manifest))
|
||
|
|
with patch.object(f,'MANIFEST',path), patch.object(f.s,'run') as run:
|
||
|
|
with self.assertRaises(RuntimeError):
|
||
|
|
f.reviewed_manifest(hashlib.sha256(path.read_bytes()).hexdigest())
|
||
|
|
run.assert_not_called()
|
||
|
|
|
||
|
|
def test_manifest_binds_current_candidate_and_existing_fixture_factory(self):
|
||
|
|
digest=hashlib.sha256(f.MANIFEST.read_bytes()).hexdigest()
|
||
|
|
manifest=f.reviewed_manifest(digest)
|
||
|
|
self.assertIn('tests/test_identity_bundle.py',manifest['source_sha256'])
|
||
|
|
self.assertIn('tools/bootstrap-recovery/isolated-keycape-session.py',manifest['source_sha256'])
|
||
|
|
self.assertIn('sso-mfa/k8s/privacyidea/key-custody-remote.py',manifest['source_sha256'])
|
||
|
|
|
||
|
|
if __name__=='__main__':unittest.main()
|