Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a1468b-63fa-7710-85dc-8f2e16b3ebfa
221 lines
14 KiB
Python
221 lines
14 KiB
Python
#!/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()<end:time.sleep(.05)
|
|
require((root/(case+'.barrier')).exists())
|
|
execution=json.loads((root/(case+'.json')).read_text())['execution_binding'];require(execution['pid']==child.pid)
|
|
fd=os.pidfd_open(child.pid)
|
|
try:signal.pidfd_send_signal(fd,signal.SIGKILL)
|
|
finally:os.close(fd)
|
|
child.wait(timeout=max(1,end-time.monotonic()))
|
|
receipt=json.loads((root/(case+'.json')).read_text())
|
|
summary['receipts'][case]=receipt
|
|
if case=='deadline':require((root/(case+'.barrier')).exists())
|
|
if case=='positive':
|
|
require(receipt.get('status')=='isolated_keycape_native_registration_checked' and receipt.get('container_cleanup_verified') and receipt.get('temporary_plaintext_cleanup_verified'))
|
|
require(receipt.get('native_service_registration_verified') and receipt.get('original_public_signing_key_in_live_jwks'))
|
|
summary['actual_issuer_original_hostname_tls_verified']=True
|
|
else:
|
|
require(receipt.get('status')!='isolated_keycape_native_registration_checked')
|
|
outcome=Path(receipt['reaper_outcome_path'])
|
|
while not outcome.exists() and time.monotonic()<end:time.sleep(.05)
|
|
require(outcome.exists());cleanup=json.loads(outcome.read_text())
|
|
require(cleanup.get('execution_quiescence_verified') and cleanup.get('temporary_plaintext_cleanup_verified'))
|
|
if case=='nonzero-after-accept':require(cleanup.get('status')=='bounded_cleanup_uncertain' and cleanup.get('in_flight_daemon_request_uncertain'))
|
|
else:require(cleanup.get('status')=='bounded_cleanup_verified')
|
|
summary['cases'][case]='passed'
|
|
finally:
|
|
if child.poll() is None:
|
|
fd=os.pidfd_open(child.pid)
|
|
try:signal.pidfd_send_signal(fd,signal.SIGKILL)
|
|
finally:os.close(fd)
|
|
child.wait(timeout=5)
|
|
|
|
|
|
def main():
|
|
p=argparse.ArgumentParser(description=__doc__);p.add_argument('--plan',action='store_true')
|
|
p.add_argument('--execute-reviewed-fixture',action='store_true');p.add_argument('--expected-manifest-sha256')
|
|
p.add_argument('--worker-root');p.add_argument('--worker-case',choices=CASES);p.add_argument('--case',choices=(*CASES,'all'),default='positive');args=p.parse_args()
|
|
if not args.execute_reviewed_fixture:
|
|
print(MANIFEST.read_text());return 0
|
|
require(not args.plan);manifest=reviewed_manifest(args.expected_manifest_sha256);os.umask(0o077)
|
|
if args.worker_root:
|
|
root=Path(args.worker_root);require(root.parent==Path('/dev/shm') and root.name.startswith('nk49-keycape-fixture-'))
|
|
s.bundle.private(root,True);return worker(root,args.worker_case)
|
|
require(not args.worker_case)
|
|
s.local.preflight();s.run(['docker','image','inspect',s.adapter.IMAGE,'--format','{{.Id}}'])
|
|
safe=Path(tempfile.mkdtemp(prefix='nk49-keycape-native-fixture-review-',dir='/tmp'))
|
|
summary={'schema':'nk49.synthetic-keycape-native-fixture.v1','status':'failed','manifest_sha256':args.expected_manifest_sha256,
|
|
'cases':{},'receipts':{},'actual_credentials_used':False,'actual_recovery_proven':False,'docker_executed':True}
|
|
print('Safe synthetic fixture result: '+str(safe/'result.json'),flush=True)
|
|
try:
|
|
with tempfile.TemporaryDirectory(prefix='nk49-keycape-fixture-',dir='/dev/shm') as temporary:
|
|
root=Path(temporary);materials(root);run_cases(root,summary,CASES if args.case=='all' else (args.case,))
|
|
summary['status']='synthetic_native_fixture_passed'
|
|
finally:(safe/'result.json').write_text(json.dumps(summary,indent=2)+'\n')
|
|
print('Safe synthetic fixture result: '+str(safe/'result.json'))
|
|
return int(summary['status']!='synthetic_native_fixture_passed')
|
|
|
|
if __name__=='__main__':raise SystemExit(main())
|