#!/usr/bin/env python3 """Prepare/run the exact reviewed T18 candidate on disposable synthetic material. Default --plan performs no Docker calls and generates no key/material. Execution requires the reviewed fixture manifest hash and source closure. This runner calls the candidate itself; hooks only pause or inject a post-response transport fault. """ import argparse import base64 from datetime import datetime,timedelta,timezone import hashlib import importlib.util import io import json import os import re from pathlib import Path import signal import subprocess import sys import tarfile import tempfile import time import uuid ROOT=Path(__file__).resolve().parents[1] MANIFEST=ROOT/'tests/isolated-keycape-native-fixture-manifest.json' ISSUER='https://nk49-fixture.invalid' CASES=('positive','hard-parent-loss','deadline','nonzero-after-accept') def load(name,path): spec=importlib.util.spec_from_file_location(name,path) module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module);return module s=load('session',ROOT/'tools/bootstrap-recovery/isolated-keycape-session.py') def require(condition): if not condition:raise RuntimeError('synthetic_fixture_refused') def reviewed_manifest(expected): raw=MANIFEST.read_bytes();require(hashlib.sha256(raw).hexdigest()==expected) manifest=json.loads(raw) for name,digest in manifest['source_sha256'].items(): require(isinstance(digest,str) and re.fullmatch('sha256:[a-f0-9]{64}',digest)) require('sha256:'+hashlib.sha256((ROOT/name).read_bytes()).hexdigest()==digest) return manifest def private_write(path,value): path.parent.mkdir(mode=0o700,parents=True,exist_ok=True) fd=os.open(path,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600) with os.fdopen(fd,'wb') as out:out.write(value) def materials(root): """Reuse the existing full archive fixture factory, no real archive accepted.""" from cryptography import x509 from cryptography.hazmat.primitives import hashes,serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID import yaml existing=load('existing_bundle_fixture',ROOT/'tests/test_identity_bundle.py') payload=existing.stage.__wrapped__(root) config={'issuer':ISSUER,'port':8080,'privateKeyPem':'/etc/keycape/key.pem','environment':'dev','tokenLifetime':'5m', 'lldap':{'url':'ldap://127.0.0.1:1','bindDN':'cn=fixture','bindPW':'synthetic-only','baseDN':'dc=fixture'}, 'authelia':{'baseURL':'http://127.0.0.1:1','clientId':'synthetic','clientSecret':'synthetic','redirectURI':ISSUER+'/authorize/callback'}, 'privacyidea':{'baseURL':'http://127.0.0.1:1'}, 'clients':[{'clientId':'nk49-fixture-consumer','clientType':'confidential','audience':'nk49-fixture', 'grantTypes':['client_credentials'],'allowedScopes':['fixture:read'],'secretRef':'env:KEYCAPE_FIXTURE_CLIENT_SECRET', 'serviceSubject':'service:nk49-fixture','tenant':'tenant:fixture','roles':['fixture-reader']}]+ [{'clientId':name,'displayName':name,'clientType':'public','grantTypes':['authorization_code'], 'redirectUris':['https://nk49-fixture.invalid/callback'],'allowedScopes':['openid'],'mfaRequired':True} for name in ('vergabe-demo-company','user-engine-portal')]} secret_path=payload/'resources/sso/secret/keycape-config.json';secret=json.loads(secret_path.read_text()) secret['data']['config.yaml']=base64.b64encode(yaml.safe_dump(config).encode()).decode();secret_path.write_text(json.dumps(secret)) client_path=payload/'resources/sso/secret/keycape-rapp-qonto-client.json';client=json.loads(client_path.read_text()) client['data']={'client-secret':base64.b64encode(b'synthetic-fixture-client-secret').decode()};client_path.write_text(json.dumps(client)) factor_path=payload/'resources/sso/secret/keycape-factor-read.json';factor=json.loads(factor_path.read_text()) factor['data']={'admin-token':base64.b64encode(b'synthetic-unused-factor-reader').decode()};factor_path.write_text(json.dumps(factor)) dep_path=payload/'resources/sso/deployment/keycape.json';dep=json.loads(dep_path.read_text()) dep['spec']={'template':{'spec':{'containers':[{'name':'keycape','image':s.adapter.IMAGE,'env':[ {'name':'KEYCAPE_CONFIG','value':'/etc/keycape/config.yaml'}, {'name':'KEYCAPE_POLICY_PATH','value':'/var/lib/keycape-policy/policy.json'}, {'name':'KEYCAPE_FIXTURE_CLIENT_SECRET','valueFrom':{'secretKeyRef':{'name':'keycape-rapp-qonto-client','key':'client-secret'}}}]}]}}};dep_path.write_text(json.dumps(dep)) policy={'Revision':1,'Modes':{k:'mandatory' for k in ('vergabe-demo-company','user-engine-portal')},'History':[ {'reference':'synthetic-retained-receipt','actor':'service:fixture','client':'user-engine-portal','before':'mandatory','after':'mandatory','revision':1,'at':1}]} # JSON tags in the owner store are lowercase; retain an existing lock inode # representation as part of the archived tree, never synthesize it after import. policy={k.lower():v for k,v in policy.items()};(payload/'data/keycape/policy.json').write_text(json.dumps(policy)) private_write(payload/'data/keycape/policy.json.lock',b'') key=rsa.generate_private_key(public_exponent=65537,key_size=2048) subject=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'nk49-fixture.invalid')]);now=datetime.now(timezone.utc) cert=(x509.CertificateBuilder().subject_name(subject).issuer_name(subject).public_key(key.public_key()).serial_number(x509.random_serial_number()) .not_valid_before(now-timedelta(minutes=5)).not_valid_after(now+timedelta(days=1)) .add_extension(x509.SubjectAlternativeName([x509.DNSName('nk49-fixture.invalid')]),critical=False) .add_extension(x509.BasicConstraints(ca=True,path_length=None),critical=True).sign(key,hashes.SHA256())) tls={'/recovery-tls/server.pem':cert.public_bytes(serialization.Encoding.PEM), '/recovery-tls/server-key.pem':key.private_bytes(serialization.Encoding.PEM,serialization.PrivateFormat.PKCS8,serialization.NoEncryption()), '/recovery-tls/trust.pem':cert.public_bytes(serialization.Encoding.PEM)} for path,value in tls.items():private_write(root/Path(path).name,value) age=root/'synthetic-age.key';s.run(['age-keygen','-o',str(age)]) recipient=s.run(['age-keygen','-y',str(age)]).decode().strip();profile=s.bundle.profile();profile['public_recipient']=recipient s.bundle.profile=lambda:profile artifact=root/'net-kingdom-identity-20261016T063159Z-0123456789ab.tar.age';s.bundle.seal(payload,artifact,{'synthetic_native_keycape_fixture':True}) raw=s.run(['age','-d','-i',str(age),str(artifact)],max_output=s.bundle.LIMIT) with tarfile.open(fileobj=io.BytesIO(raw)) as archive:manifest=json.load(archive.extractfile('manifest.json')) transfer={'schema':'netkingdom.identity-offsite.v1','status':'readback_verified','provider':'Storage Share', 'folder':'Backup/railiance-backups/net-kingdom-identity','artifact':artifact.name,'ciphertext_bytes':artifact.stat().st_size, 'ciphertext_sha256':hashlib.sha256(artifact.read_bytes()).hexdigest(),'etag':'"synthetic"','fetched_path':str(artifact), 'independent_owner_retrieval_verified':True} # Derive public executable identity only from the exact cached admitted image. probe=s.plan_session();name=probe['public_image_probe'] try: s.run(['docker','create','--pull=never','--name',name,'--network','none','--read-only','--label',s.adapter.LABEL+'='+probe['run_id'],s.adapter.IMAGE]) binary=s.adapter.container_file(name,'/keycape') finally:s.adapter.cleanup({**probe,'containers':[name]}, {}) admission={'issuer':ISSUER,'ciphertext_sha256':transfer['ciphertext_sha256'], 'manifest_sha256':hashlib.sha256(json.dumps(manifest,sort_keys=True,separators=(',',':')).encode()).hexdigest(), 'verifier_sha256':hashlib.sha256(binary).hexdigest(),'trust_sha256':hashlib.sha256(tls['/recovery-tls/trust.pem']).hexdigest(), 'tls_cert_sha256':hashlib.sha256(tls['/recovery-tls/server.pem']).hexdigest(), 'consumer':{'client_id':'nk49-fixture-consumer','secret_env':'KEYCAPE_FIXTURE_CLIENT_SECRET','audience':'nk49-fixture','scope':'fixture:read', 'subject':'service:nk49-fixture','tenant':'tenant:fixture','roles':'fixture-reader','deny_scope':'fixture:write'}} private_write(root/'fixture.json',json.dumps({'schema':'nk49.generated-keycape-fixture.v1','transfer':transfer,'admission':admission,'recipient':recipient}).encode()) def worker(root,case): execution=s.isolate_execution();execution['deadline']=time.monotonic()+(20 if case=='deadline' else 120) data=json.loads((root/'fixture.json').read_text());require(data['schema']=='nk49.generated-keycape-fixture.v1') profile=s.bundle.profile();profile['public_recipient']=data['recipient'];s.bundle.profile=lambda:profile s.local.verify.custody.private_key_fd=lambda:os.open(root/'synthetic-age.key',os.O_RDONLY|os.O_NOFOLLOW) tls={'/recovery-tls/'+name:(root/name).read_bytes() for name in ('server.pem','server-key.pem','trust.pem')} receipt={};output=root/(case+'.json');checkpoint=lambda r:output.write_text(json.dumps(r)) provision=s.provision def paused(*args): provision(*args) if case in ('hard-parent-loss','deadline'): private_write(root/(case+'.barrier'),b'private-import-and-default-launch-complete') time.sleep(150) s.provision=paused if case=='nonzero-after-accept': original=s.adapter.subprocess.run;injected=False def fault(argv,**kwargs): nonlocal injected result=original(argv,**kwargs) if argv[:3]==['docker','--host',s.adapter.ENDPOINT] and 'run' in argv and not injected and result.returncode==0: injected=True return subprocess.CompletedProcess(argv,1,b'',b'') return result s.adapter.subprocess.run=fault try:s.execute(data['transfer'],data['admission'],tls,receipt,execution,checkpoint=checkpoint) except BaseException:receipt['status']='failed' finally:output.write_text(json.dumps(receipt)) return int(receipt.get('status')!='isolated_keycape_native_registration_checked') def run_cases(root,summary,cases): for case in cases: child=subprocess.Popen([sys.executable,str(Path(__file__).resolve()),'--worker-root',str(root),'--worker-case',case, '--execute-reviewed-fixture','--expected-manifest-sha256',summary['manifest_sha256']],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL) try: end=time.monotonic()+150 if case=='hard-parent-loss': while not (root/(case+'.barrier')).exists() and child.poll() is None and time.monotonic()