"""Run with an isolated interpreter containing only the installed wheel and deps.""" import importlib.metadata import json import os from pathlib import Path import subprocess import sys import tempfile import threading import time from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec import railiance_clock from railiance_clock.admission import admit from railiance_clock.authority import Authority, Server from railiance_clock.client import Clock, FileTrust from railiance_clock.core import ClockError def main(): installed = Path(railiance_clock.__file__).resolve() assert installed.is_relative_to(Path(sys.prefix).resolve()), installed schemas = installed.parent / 'schemas' for name in ('time-request', 'time-sample', 'protected-header'): assert json.loads((schemas / (name + '-v0.1.schema.json')).read_text())['type'] == 'object' cli = Path(sys.executable).parent / 'railiance-clock' help_result = subprocess.run([str(cli), '--help'], capture_output=True, text=True, check=True) assert all(command in help_result.stdout for command in ('read', 'serve', 'health-export')) with tempfile.TemporaryDirectory() as directory: root = Path(directory) key = ec.generate_private_key(ec.SECP256R1()) private = root / 'key.pem' private.write_bytes(key.private_bytes(serialization.Encoding.PEM, serialization.PrivateFormat.PKCS8, serialization.NoEncryption())) private.chmod(0o600) health = root / 'health.json' health.write_text(json.dumps({'quality': 'bounded', 'boot_id': Path('/proc/sys/kernel/random/boot_id').read_text().strip(), 'policy_id': 'wheel-test', 'observed_monotonic_ns': time.monotonic_ns(), 'error_ns': 1000})) config = {'private_key_file': str(private), 'health_file': str(health), 'health_owner_uid': os.getuid(), 'policy_id': 'wheel-test', 'authority_id': 'disposable', 'environment': 'test', 'kid': 'test-key', 'max_health_age_ns': 30_000_000_000, 'host_drift_ppm': 1000, 'max_error_ns': 100_000_000, 'max_continuity_error_ns': 50_000_000, 'max_sample_age_ns': 5_000_000_000} authority = Authority(config) server = Server(('127.0.0.1', 0), authority) thread = threading.Thread(target=server.serve_forever) thread.start() try: trust = admit(directory=root, authority_id='disposable', environment='test', kid='test-key', epoch=authority.epoch, policy_id='wheel-test', public_key_pem=key.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo).decode(), endpoint=f'http://127.0.0.1:{server.server_port}/v1/time-samples', admission_ref='disposable-wheel-test-only', transport='admitted-loopback', limits={'max_age_ns': 5_000_000_000, 'max_rtt_ns': 2_000_000_000, 'max_width_ns': 3_000_000_000, 'max_server_error_ns': 100_000_000, 'timer_ppm': 1000, 'timer_resolution_ns': 5_000_000, 'suspend_tolerance_ns': 5_000_000, 'trust_session_ns': 60_000_000_000}) result = subprocess.run([str(cli), 'read', '--trust', str(trust)], capture_output=True, text=True, check=True) window = json.loads(result.stdout) assert window['authority_id'] == 'disposable' assert window['epoch'] == authority.epoch assert window['lower_ns'] <= window['upper_ns'] bad = json.loads(trust.read_text()); bad['kid'] = 'wrong-key' trust.write_text(json.dumps(bad)) try: Clock(FileTrust(trust)).read() except ClockError: pass else: raise AssertionError('wrong key accepted') bad['kid'] = 'test-key'; trust.write_text(json.dumps(bad)) health.write_text('{"quality":"unusable"}') refused = subprocess.run([str(cli), 'read', '--trust', str(trust)], capture_output=True, text=True) assert refused.returncode == 1 and not refused.stdout assert refused.stderr == 'Railiance time unavailable or untrusted.\n' finally: server.shutdown(); server.server_close(); thread.join() distributions = sorted((d.metadata['Name'], d.version) for d in importlib.metadata.distributions()) print(json.dumps({'checks': ['installed_import', 'three_packaged_schemas', 'cli_help', 'signed_http_cli_read', 'wrong_key_refusal', 'unhealthy_cli_refusal'], 'distributions': distributions}, sort_keys=True)) if __name__ == '__main__': main()