net-kingdom/sso-mfa/k8s/keycape/test_openbao_node_route.py
tegwick 7ceac4372d
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Publish reviewed bounded JWT ready handoff and retained owner history
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
2026-10-11 18:31:04 +02:00

198 lines
13 KiB
Python

"""Offline route readiness: public responses and lifecycle mocks only."""
import importlib.util
import json
from pathlib import Path
import unittest
from unittest.mock import patch
import copy
import time
import tempfile
import sys
import signal
import io
spec=importlib.util.spec_from_file_location('fixtures',Path(__file__).with_name('test_openbao_negative_session.py'))
f=importlib.util.module_from_spec(spec);spec.loader.exec_module(f);s=f.s
HEALTH={'initialized':True,'sealed':False,'standby':False,'performance_standby':False,'cluster_id':'synthetic-public-cluster'}
PIN=s.digest(HEALTH['cluster_id'].encode())
class NodeRouteTests(unittest.TestCase):
def setUp(self):
s.CLEANING=False;s.REQUEST_DEADLINE=None
s.BUSINESS_MONOTONIC_DEADLINE=None;s.CLEANUP_MONOTONIC_DEADLINE=None
def test_public_health_get_has_no_authentication_and_only_digest_retained(self):
transport=s.SessionTransport('http://127.0.0.1:18200');receipt={}
response=type('Response',(),{'getcode':lambda self:200,'read':lambda self,size:json.dumps(HEALTH).encode(),'close':lambda self:None})()
with patch.object(transport.opener,'open',return_value=response) as calls:
s.verify_bao_route(transport,{'bao_health_identity_sha256':PIN},receipt)
req=calls.call_args.args[0]
self.assertEqual(req.full_url,'http://127.0.0.1:18200/v1/sys/health')
self.assertEqual(req.method,'GET');self.assertEqual(req.headers,{})
self.assertEqual(receipt,{'bao_public_route_verified':True})
self.assertNotIn(HEALTH['cluster_id'],json.dumps(receipt))
def test_unreachable_redirect_sealed_standby_uninitialized_and_malformed_health_refuse(self):
transport=s.SessionTransport('http://openbao.openbao.svc:8200')
cases=[(None,b''),(302,b'{}'),(503,json.dumps(HEALTH).encode()),(200,b'not-json'),
(200,b'[]'),(200,json.dumps(dict(HEALTH,sealed=True)).encode()),
(200,json.dumps(dict(HEALTH,initialized=False)).encode()),
(200,json.dumps(dict(HEALTH,standby=True)).encode()),
(200,json.dumps(dict(HEALTH,sealed=0)).encode()),
(200,json.dumps(dict(HEALTH,cluster_id='')).encode())]
for status,body in cases:
with self.subTest(status=status,body_length=len(body)),patch.object(transport,'request',return_value=(status,body)):
with self.assertRaises(s.Refused):transport.health_identity()
def test_identity_drift_or_missing_approved_pin_refuse(self):
transport=s.SessionTransport('http://127.0.0.1:18200')
with patch.object(transport,'health_identity',return_value=PIN) as health:
with self.assertRaisesRegex(s.Refused,'bao_public_health_identity_changed'):
s.verify_bao_route(transport,{'bao_health_identity_sha256':'0'*64},{})
health.reset_mock()
with self.assertRaisesRegex(s.Refused,'approved_bao_health_identity_required'):
s.verify_bao_route(transport,{}, {})
health.assert_not_called()
def setup_execute(self):
raw=f.baseline()
spec={'replicas':1,'strategy':{'type':'Recreate'},'template':{'spec':{'containers':[{'name':'keycape','env':[]}]}}}
config={'metadata':{'name':'keycape-config','uid':'cfg','resourceVersion':'1'},'data':{'config.yaml':s.base64.b64encode(raw.encode()).decode()}}
dep={'metadata':{'name':'keycape','uid':'dep','resourceVersion':'1'},'spec':spec}
e=f.envelope();e.update(runner_path='fixture-runner',bao_health_identity_sha256=PIN,
config_metadata=s.meta(config),deployment_metadata=s.meta(dep),registry_sha256=s.digest(raw.encode()),deployment_spec_sha256=s.canonical(spec))
e['source_hashes']['fixture-runner']='fixture'
return e,config,dep
def test_unavailable_initial_node_route_stops_before_any_native_or_secret_access(self):
e,config,dep=self.setup_execute()
with patch.object(s,'verify_sources',return_value=150),patch.object(s,'load_probe'), \
patch.object(s,'SessionTransport') as factory,patch.object(s,'k') as k,patch.object(s,'get') as get:
factory.return_value.discovery.return_value={'issuer':'https://kc.coulomb.social','token_endpoint':'https://kc.coulomb.social/token'}
factory.return_value.health_identity.side_effect=s.Refused('bao_public_health_unavailable')
with self.assertRaisesRegex(s.Refused,'bao_public_health_unavailable'):
s.execute(e,{'human_token':'synthetic','coding_agent_token':'synthetic'}, {})
k.assert_not_called();get.assert_not_called()
def test_route_loss_after_dry_runs_stops_before_temporary_create_or_restarts(self):
e,config,dep=self.setup_execute()
with patch.object(s,'verify_sources',return_value=150),patch.object(s,'load_probe'), \
patch.object(s,'SessionTransport') as factory, \
patch.object(s,'k',return_value={'metadata':{'uid':s.CLUSTER}}) as k, \
patch.object(s,'get',side_effect=[config,dep]),patch.object(s,'patch') as patches,patch.object(s,'ready',return_value=True):
factory.return_value.discovery.return_value={'issuer':'https://kc.coulomb.social','token_endpoint':'https://kc.coulomb.social/token'}
factory.return_value.health_identity.side_effect=[PIN,s.Refused('bao_public_health_unavailable')]
with self.assertRaisesRegex(s.Refused,'bao_public_health_unavailable'):
s.execute(e,{'human_token':'synthetic','coding_agent_token':'synthetic'}, {})
self.assertEqual(factory.return_value.health_identity.call_count,2)
self.assertTrue(all(c.kwargs.get('dry') is True for c in patches.call_args_list))
self.assertTrue(all(c.args[0][0]!='create' or '--dry-run=server' in c.args[0] for c in k.call_args_list))
def test_recovery_route_refusal_precedes_native_reads(self):
e,config,dep=self.setup_execute();e['disposition']='recovery-approved'
with patch.object(s,'verify_sources',return_value=None),patch.object(s,'SessionTransport') as factory, \
patch.object(s,'k') as k,patch.object(s,'get') as get:
factory.return_value.health_identity.side_effect=s.Refused('bao_public_health_unavailable')
with self.assertRaisesRegex(s.Refused,'bao_public_health_unavailable'):
s.recover(e,{})
k.assert_not_called();get.assert_not_called()
def test_public_health_uses_total_elapsed_limit(self):
transport=s.SessionTransport('http://127.0.0.1:18200')
class Slow:
def getcode(self):return 200
def read(self,size):time.sleep(0.5);return json.dumps(HEALTH).encode()
def close(self):pass
started=time.monotonic()
with patch.object(s,'HTTP_TOTAL_SECONDS',0.008),patch.object(transport.opener,'open',return_value=Slow()):
with self.assertRaisesRegex(s.Refused,'request_total_timeout'):transport.health_identity()
self.assertLess(time.monotonic()-started,0.08)
def test_public_route_mode_has_no_native_secret_or_private_input(self):
with tempfile.TemporaryDirectory() as folder:
receipt=Path(folder)/'receipt.json'
argv=['session','route-preflight','--bao-addr','http://127.0.0.1:18200','--receipt',str(receipt)]
with patch.object(sys,'argv',argv),patch.object(s,'SessionTransport') as factory, \
patch.object(s,'k') as k,patch.object(s,'get') as get,patch.object(sys,'stdin') as stdin:
factory.return_value.health_identity.return_value=PIN
self.assertEqual(s.main(),0)
k.assert_not_called();get.assert_not_called();stdin.read.assert_not_called()
data=json.loads(receipt.read_text())
self.assertEqual(data['bao_health_identity_sha256'],PIN)
self.assertEqual(data['probe_location'],'current_process_only')
self.assertFalse(data['native_accepted'])
def main_fixture(self,folder,mode):
envelope=f.envelope()
envelope['bao_health_identity_sha256']=PIN
if mode=='recover':envelope['disposition']='recovery-approved'
path=Path(folder)/'approved.json';path.write_text(json.dumps(envelope));path.chmod(0o600)
receipt=Path(folder)/'receipt.json'
argv=['session',mode,'--envelope',str(path),'--receipt',str(receipt)]
return envelope,receipt,argv
def test_actual_main_health_failure_never_reads_private_stdin_execute_or_recover(self):
previous=signal.getsignal(signal.SIGTERM)
try:
for mode in ['execute','recover']:
with self.subTest(mode=mode),tempfile.TemporaryDirectory() as folder:
e,receipt,argv=self.main_fixture(folder,mode)
with patch.object(sys,'argv',argv),patch.object(s,'SessionTransport') as factory, \
patch.object(sys,'stdin') as stdin,patch.object(s,'k') as k,patch.object(s,'get') as get:
factory.return_value.health_identity.side_effect=s.Refused('bao_public_health_unavailable')
self.assertEqual(s.main(),1)
stdin.read.assert_not_called();stdin.buffer.read.assert_not_called();k.assert_not_called();get.assert_not_called()
data=json.loads(receipt.read_text())
self.assertEqual(data['reason'],'bao_public_health_unavailable')
self.assertFalse(data['cleanup_verified'])
s.CLEANING=False;s.CLEANUP_MONOTONIC_DEADLINE=None
finally:signal.signal(signal.SIGTERM,previous)
def test_actual_main_missing_approved_health_pin_never_reads_stdin(self):
previous=signal.getsignal(signal.SIGTERM)
try:
with tempfile.TemporaryDirectory() as folder:
e,receipt,argv=self.main_fixture(folder,'execute')
del e['bao_health_identity_sha256']
Path(argv[3]).write_text(json.dumps(e))
with patch.object(sys,'argv',argv),patch.object(sys,'stdin') as stdin, \
patch.object(s,'SessionTransport') as factory,patch.object(s,'k') as k:
self.assertEqual(s.main(),1)
stdin.read.assert_not_called();stdin.buffer.read.assert_not_called();factory.return_value.health_identity.assert_not_called();k.assert_not_called()
self.assertEqual(json.loads(receipt.read_text())['reason'],'approved_bao_health_identity_required')
finally:signal.signal(signal.SIGTERM,previous)
def test_actual_main_health_succeeds_before_stdin_and_preserves_started_window(self):
previous=signal.getsignal(signal.SIGTERM);events=[];started={}
try:
with tempfile.TemporaryDirectory() as folder:
e,receipt,argv=self.main_fixture(folder,'execute')
def health():
events.append('health');started['deadline']=s.BUSINESS_MONOTONIC_DEADLINE;return PIN
payloads=iter([b'{"human_token":"synthetic","coding_agent_token":"synthetic"}',b''])
def private_read(size):
if 'stdin' not in events:events.append('stdin')
self.assertGreater(size,0);return next(payloads)
def execute(*args,**kwargs):
events.append('execute');self.assertTrue(kwargs['window_started'])
self.assertEqual(s.BUSINESS_MONOTONIC_DEADLINE,started['deadline'])
with patch.object(sys,'argv',argv),patch.object(s,'SessionTransport') as factory, \
patch.object(sys,'stdin') as stdin,patch.object(s,'emit_private_ready'),patch.object(s,'execute',side_effect=execute), \
patch.object(s,'k') as k:
factory.return_value.health_identity.side_effect=health
stdin.buffer.read.side_effect=private_read
self.assertEqual(s.main(),0);k.assert_not_called()
self.assertEqual(events,['health','stdin','execute'])
finally:signal.signal(signal.SIGTERM,previous)
def test_execute_does_not_renew_expired_preinput_monotonic_window(self):
e=f.envelope();s.start_execution_window(e)
original=s.BUSINESS_MONOTONIC_DEADLINE
with patch.object(s.time,'monotonic',return_value=original+0.01),patch.object(s,'load_probe') as load, \
patch.object(s,'k') as k:
with self.assertRaisesRegex(s.Refused,'session_business_budget_expired'):
s.execute(e,{'human_token':'synthetic','coding_agent_token':'synthetic'}, {},window_started=True)
load.assert_not_called();k.assert_not_called()
self.assertEqual(s.BUSINESS_MONOTONIC_DEADLINE,original)
if __name__=='__main__':unittest.main(verbosity=2)