69 lines
3.4 KiB
Python
69 lines
3.4 KiB
Python
#!/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()
|