Connect policy-gated browser review and audit runtime

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
tegwick 2026-09-11 00:31:03 +02:00
parent 2cc32168ac
commit 83849b75d4
35 changed files with 2381 additions and 83 deletions

View file

@ -0,0 +1,79 @@
"""Disposable actual Flex Auth HTTP process, with synthetic Kubernetes custody.
The evaluator and inbound caller authenticator are real. TokenReview and its
identities are fixtures; this does not admit any production caller or policy.
"""
from contextlib import contextmanager
from datetime import datetime, timedelta, timezone
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import json
import os
from pathlib import Path
import socket
import subprocess
import threading
import time
from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.x509.oid import NameOID
from informed_decision.http_transport import JSONTransport, TransportError
from informed_decision.policy import PolicyClient
FIXTURE = Path(__file__).parent / 'fixtures/review-policy'
@contextmanager
def flex_component(binary, directory, signing_key):
tokens={'synthetic-workload-token':'system:serviceaccount:informed-decision:review',
'synthetic-wrong-caller':'system:serviceaccount:other:other'}
calls=[]
class Reviewer(BaseHTTPRequestHandler):
def log_message(self,*args):pass
def do_POST(self):
body=json.loads(self.rfile.read(int(self.headers['Content-Length'])))
token=body['spec']['token'];calls.append({'known':token in tokens,'audiences':body['spec']['audiences']})
valid=(self.path=='/apis/authentication.k8s.io/v1/tokenreviews'
and self.headers.get('Authorization')=='Bearer synthetic-reviewer'
and body['spec']['audiences']==['flex-auth'] and token in tokens)
raw=json.dumps({'status':{'authenticated':valid,'audiences':['flex-auth'] if valid else [],
'user':{'username':tokens.get(token,'')}}}).encode()
self.send_response(201);self.send_header('Content-Type','application/json');self.end_headers();self.wfile.write(raw)
server=ThreadingHTTPServer(('127.0.0.1',0),Reviewer)
thread=threading.Thread(target=server.serve_forever,daemon=True);thread.start()
now=datetime.now(timezone.utc)
name=x509.Name([x509.NameAttribute(NameOID.COMMON_NAME,'synthetic-tokenreview-fixture')])
cert=(x509.CertificateBuilder().subject_name(name).issuer_name(name).public_key(signing_key.public_key())
.serial_number(x509.random_serial_number()).not_valid_before(now-timedelta(minutes=1))
.not_valid_after(now+timedelta(hours=1)).add_extension(x509.BasicConstraints(ca=True,path_length=None),critical=True)
.sign(signing_key,hashes.SHA256()))
ca=directory/'fixture-ca.pem';ca.write_bytes(cert.public_bytes(serialization.Encoding.PEM))
reviewer=directory/'reviewer-token';reviewer.write_text('synthetic-reviewer');reviewer.chmod(0o600)
with socket.socket() as listener:
listener.bind(('127.0.0.1',0));port=listener.getsockname()[1]
origin=f'http://127.0.0.1:{port}'
process=subprocess.Popen([str(binary),'serve','--addr',f'127.0.0.1:{port}',
'--registry',str(FIXTURE/'registry.json'),'--policy',str(FIXTURE/'policy.md'),
'--caller-auth-mode','enforce','--caller-binding','informed-decision=system:serviceaccount:informed-decision:review',
'--caller-kubernetes-url',f'http://127.0.0.1:{server.server_port}',
'--caller-reviewer-token-file',str(reviewer),'--caller-ca-file',str(ca)],stdout=subprocess.DEVNULL,stderr=subprocess.PIPE)
try:
transport=JSONTransport(allow_internal_http=True)
for _ in range(100):
if process.poll() is not None:
raise RuntimeError('fixture evaluator exited: '+process.stderr.read().decode()[:1000])
try:
if transport.request('GET',origin+'/healthz')[0]==200:break
except TransportError:pass
time.sleep(.05)
else:raise RuntimeError('fixture evaluator did not start')
pin=json.loads((FIXTURE/'pin.json').read_text());pin.pop('fixture_only')
client=PolicyClient(origin,lambda:'synthetic-workload-token',allow_internal_http=True,**pin)
yield client,calls
finally:
process.terminate()
try:process.wait(timeout=5)
except subprocess.TimeoutExpired:process.kill();process.wait(timeout=5)
process.stderr.close();server.shutdown();server.server_close();thread.join(timeout=5)