#!/usr/bin/env python3 """Verify the synthetic bootstrap output with KeyCape's current native loader. Only local source, synthetic credentials and disposable files are used. Requires pytest, PyYAML, OpenSSL and Go with dependencies already cached. No kubectl from PATH is executed: the fixture installs its recording stub in a private PATH. """ import argparse import base64 import hashlib import importlib.util import json import os from pathlib import Path import shutil import subprocess import tempfile def digest(path): return hashlib.sha256(path.read_bytes()).hexdigest() def main(): parser = argparse.ArgumentParser() parser.add_argument('--net-kingdom', type=Path, required=True) parser.add_argument('--key-cape', type=Path, required=True) args = parser.parse_args() fixture = args.net_kingdom / 'tests/test_keycape_bootstrap.py' spec = importlib.util.spec_from_file_location('bootstrap_fixture', fixture) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) with tempfile.TemporaryDirectory(prefix='keycape-bootstrap-native-') as directory: root = Path(directory) case_root = root / 'fixture'; case_root.mkdir() case = module.setup.__wrapped__(case_root) result = module.invoke(case) if result.returncode: raise RuntimeError('synthetic bootstrap failed') writes = [c for c in module.calls(case) if c['args'][0] == 'create'] if len(writes) != 1: raise RuntimeError('unexpected synthetic operation count') manifest = json.loads(writes[0]['stdin']) checkout = root / 'consumer'; checkout.mkdir() shutil.copytree(args.key_cape / 'src', checkout / 'src', ignore=shutil.ignore_patterns('.git', '__pycache__', '.pytest_cache')) # Existing native config tests read only these public example fixtures. (checkout / 'config').mkdir() for name in ('dev-config.yaml', 'service-clients.example.yaml'): shutil.copyfile(args.key_cape / 'config' / name, checkout / 'config' / name) (checkout / 'src/bootstrap-fixture.json').write_bytes(base64.b64decode(manifest['data']['config.yaml'])) native_test = Path(__file__).with_name('keycape_bootstrap_native_test.go') shutil.copyfile(native_test, checkout / 'src/internal/config/custody_bootstrap_test.go') tested = subprocess.run(['go', 'test', '-count=1', './internal/config', './internal/adapters/privacyidea'], cwd=checkout / 'src', capture_output=True, timeout=120, env={**os.environ, 'GOPROXY': 'off', 'GOTOOLCHAIN': 'auto'}) if tested.returncode: raise RuntimeError('native loader/adapter verification failed') sources = ['src/internal/config/config.go', 'src/internal/adapters/privacyidea/config.go', 'src/internal/adapters/privacyidea/adapter.go', 'src/internal/adapters/privacyidea/credential_file_test.go'] print(json.dumps({'result': 'passed', 'bootstrap_fixture_sha256': digest(fixture), 'native_test_sha256': digest(native_test), 'consumer_sources': [{'path': p, 'sha256': digest(args.key_cape / p)} for p in sources], 'scope': 'Generated synthetic YAML parsed by native loader; local config and adapter suites. No live cluster or provider.'}, indent=2)) if __name__ == '__main__': main()