the-custodian/docs/changes/CUST-WP-0080/verify_keycape_bootstrap.py
codex bb3e2db07e
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Reject generated-only commits / generated-commit-guard (push) Successful in 8s
security: record KeyCape custody caller reconciliation and native config proof
2026-10-13 19:49:24 +02:00

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()