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:
parent
2cc32168ac
commit
83849b75d4
35 changed files with 2381 additions and 83 deletions
79
tests/review_components.py
Normal file
79
tests/review_components.py
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue