Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a09cbb-87c6-7900-a145-4ce53ba9f1a6
195 lines
13 KiB
Python
195 lines
13 KiB
Python
"""Single-attempt T03 owner procedure; native PEP checks precede every action."""
|
|
import argparse,base64,copy,contextlib,io,json,os,stat,subprocess,sys,tempfile
|
|
from pathlib import Path
|
|
from datetime import datetime,timezone
|
|
from dataclasses import replace
|
|
import yaml
|
|
ROOT=Path('/home/worsch/secrets-engine')
|
|
sys.path.insert(0,str(ROOT/'src'))
|
|
sys.path.insert(0,'/home/worsch/railiance-clock/src')
|
|
from secrets_engine.config import Config
|
|
from secrets_engine.catalog import get_entry
|
|
from secrets_engine.authorization import build_action_request,digest_material
|
|
from secrets_engine.approval_consume import authorize_action
|
|
from secrets_engine.cli import build_parser
|
|
from secrets_engine.decisions import resolve_decision,require_approved
|
|
from secrets_engine.openbao import OpenBaoClient
|
|
from secrets_engine.exec_owner import validate_delivery_target
|
|
from secrets_engine.plan import build_plan
|
|
RECEIPT=ROOT/'docs/evidence/2026-09-15-t03-native-execution.json'
|
|
KUBE=['kubectl','--kubeconfig','/home/worsch/.kube/config-railiance01']
|
|
ROLE='se-prod-openrouter-llm-connect'; LANE='openrouter-llm-connect'
|
|
IDS={'apply':'9935335c-8e9a-566e-a48e-6a5b5f4882eb','verify':'273d6882-6253-5dc9-ac54-544f92ef5e56','exec':'7ba0c13b-68cd-5b3e-9481-42ba9e385e68'}
|
|
|
|
def require(value,code):
|
|
if not value:raise ValueError(code)
|
|
def private(p,directory=False):
|
|
s=p.lstat();require(s.st_uid==os.getuid() and stat.S_IMODE(s.st_mode)==(0o700 if directory else 0o600) and (stat.S_ISDIR(s.st_mode) if directory else stat.S_ISREG(s.st_mode)),'private_path_required')
|
|
def run(*args):
|
|
p=subprocess.run(args,capture_output=True,text=True,timeout=30);require(p.returncode==0,'metadata_command_failed');return p.stdout
|
|
def bao(*args):return json.loads(run('bao',*args))
|
|
def save(receipt):RECEIPT.write_text(json.dumps(receipt,indent=2)+'\n')
|
|
def prepare(directory):
|
|
source=yaml.safe_load((ROOT/'docs/proposals/openrouter-key-check.yaml').read_text())
|
|
configs={};entries={}
|
|
for action,approval in IDS.items():
|
|
folder=directory/action;folder.mkdir();doc=copy.deepcopy(source);doc['approval']['authorization_id']=approval
|
|
(folder/(LANE+'.yaml')).write_text(yaml.safe_dump(doc,sort_keys=False))
|
|
cfg=replace(Config.load(),catalog_dir=folder,bao_addr='http://127.0.0.1:18200',approval_url='http://127.0.0.1:18281',approval_token_file=None,approval_client_secret_file=directory/'client-secret',keycape_token_url='https://kc.coulomb.social/token',keycape_issuer='https://kc.coulomb.social',keycape_client_secret_file=None,openbao_jwt_login_file=None,authorization_subject_id='secrets-engine',authorization_subject_type='service',authorization_policy_package='secrets-engine.catalog-lane.lifecycle',authorization_policy_version='v2',authorization_min_approvals=1,pdp_url='http://127.0.0.1:18282',pdp_token_file=directory/'pdp-caller')
|
|
entry=get_entry(folder,LANE);fields=() if action=='apply' else tuple(entry.fields)
|
|
actual=build_action_request(entry,action,subject_id='secrets-engine',subject_type='service',purpose=entry.approval['purpose'],fields=fields,policy_targets=(entry.policy_name,),auth_targets=(entry.role_name,))
|
|
expected=json.loads((ROOT/f'docs/evidence/2026-09-14-openrouter-final-{action}-request.json').read_text())
|
|
require(digest_material(actual)==digest_material(expected),'frozen_action_request_drift')
|
|
configs[action]=cfg;entries[action]=entry
|
|
command=source['delivery_config']['exec_owner']['command']
|
|
validate_delivery_target(entries['exec'],entries['exec'].fields[0],command,'exec-env')
|
|
plan=build_plan(entries['apply'],'prod');require(plan.policy_name==ROLE and plan.role_name==ROLE,'plan_target_drift')
|
|
return configs,entries,command
|
|
|
|
def health():
|
|
# Metadata only: never request Kubernetes Secret payloads.
|
|
result={}
|
|
for kind in ('deployment','externalsecret'):
|
|
items=json.loads(run(*KUBE,'get',kind,'-A','-o','json'))['items']
|
|
rows=[]
|
|
for obj in items:
|
|
if 'llm-connect' not in obj['metadata']['name']:continue
|
|
if kind=='deployment':
|
|
require(obj.get('status',{}).get('readyReplicas',0)>=1,'llm_connect_not_ready')
|
|
rows.append({'namespace':obj['metadata']['namespace'],'name':obj['metadata']['name'],'ready':obj['status']['readyReplicas']})
|
|
else:
|
|
require(any(c['type']=='Ready' and c['status']=='True' for c in obj.get('status',{}).get('conditions',[])),'llm_connect_eso_not_ready')
|
|
rows.append({'namespace':obj['metadata']['namespace'],'name':obj['metadata']['name'],'ready':True})
|
|
require(rows,'llm_connect_health_target_missing');result[kind]=rows
|
|
return result
|
|
|
|
def verify_session_cleanup(client):
|
|
# Keep the explicit scoped token in memory: close() clears session.client.token,
|
|
# which otherwise makes a subsequent CLI call use the attended admin helper.
|
|
from urllib.request import Request,build_opener,ProxyHandler,HTTPRedirectHandler
|
|
from urllib.error import HTTPError
|
|
class NoRedirect(HTTPRedirectHandler):
|
|
def redirect_request(self,*a,**k):return None
|
|
with client.approle_session(ROLE) as session:
|
|
probe_token=session.client.token
|
|
probes=['platform/data/workloads/secrets-engine/approval-client','platform/metadata/workloads/activity-core']
|
|
require(all(session.client.token_capabilities(p,token=probe_token)==['deny'] for p in probes),'unrelated_path_authority')
|
|
try:
|
|
require(session.revocation_succeeded,'session_revocation_failed')
|
|
req=Request(client.addr+'/v1/auth/token/lookup-self',headers={'X-Vault-Token':probe_token})
|
|
try:
|
|
with build_opener(ProxyHandler({}),NoRedirect()).open(req,timeout=20) as response:
|
|
raise ValueError('revoked_token_still_usable')
|
|
except HTTPError as error:
|
|
require(error.code==403,'revocation_probe_not_definitive')
|
|
finally:
|
|
del probe_token
|
|
return {'unrelated_path_denied':True,'session_revocation_verified':True,'revoked_token_lookup_status':403}
|
|
|
|
def resume_receipt():
|
|
prior=json.loads((ROOT/'docs/evidence/2026-09-15-t03-native-execution.json').read_text())
|
|
require(prior.get('phase')=='verify_attempt_started' and prior.get('failure_code')=='revoked_token_still_usable','unexpected_prior_failure')
|
|
require(prior.get('actions')==[{'action':'apply','approval_id':IDS['apply'],'exit_code':0,'limits':{'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}}],'prior_apply_not_verified')
|
|
return prior
|
|
|
|
def admin(directory,negative,resume=False):
|
|
require(not RECEIPT.exists(),'existing_execution_receipt_requires_reconciliation')
|
|
receipt={'status':'failed','phase':'preflight','observed_at':datetime.now(timezone.utc).isoformat(),'actions':[]}
|
|
forwards=[]
|
|
try:
|
|
require(Path.home().parent.name=='.warden-attended-login' and not os.getenv('BAO_TOKEN') and not os.getenv('VAULT_TOKEN'),'attended_envelope_required')
|
|
private(directory,True);private(directory/'client-secret');private(negative)
|
|
identity=bao('token','lookup','-format=json')['data'];policies=set(identity['policies'])|set(identity.get('identity_policies',[]))
|
|
require('platform-admin' in policies and 'root' not in policies and identity.get('entity_id') and 0<identity['ttl']<=3600,'attended_operator_required')
|
|
require(bao('read','-format=json','sys/auth')['data'].get('approle/') is not None,'existing_approle_mount_required')
|
|
configs,entries,command=prepare(directory)
|
|
from secrets_engine.application_time import read_window
|
|
require(all(cfg.clock_trust_file for cfg in configs.values()),'admitted_railiance_clock_required')
|
|
for cfg in configs.values():read_window(cfg)
|
|
receipt['health_before']=health()
|
|
for ns,label,image,port in [('approval-engine','approval-engine','251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49',18281),('flex-auth','flex-auth-secrets-engine','05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd',18282)]:
|
|
pods=json.loads(run(*KUBE,'-n',ns,'get','pods','-l','app.kubernetes.io/name='+label,'-o','json'))['items']
|
|
require(len(pods)==1,'single_owner_pod_required');pod=pods[0]
|
|
require(any(c.get('ready') and c.get('imageID','').endswith('@sha256:'+image) for c in pod.get('status',{}).get('containerStatuses',[])),'native_image_pin_drift')
|
|
p=subprocess.Popen(KUBE+['-n',ns,'port-forward','pod/'+pod['metadata']['name'],str(port)+':8080','--address=127.0.0.1'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL);forwards.append(p)
|
|
import socket,time
|
|
for port in (18281,18282):
|
|
for attempt in range(50):
|
|
try:
|
|
with socket.create_connection(('127.0.0.1',port),timeout=.2):break
|
|
except OSError:time.sleep(.1)
|
|
else:raise ValueError('owner_forward_not_ready')
|
|
fd=os.open(directory/'pdp-caller',os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600)
|
|
with os.fdopen(fd,'w') as out:out.write(run(*KUBE,'-n','secrets-engine','create','token','secrets-engine','--audience=flex-auth','--duration=10m').strip())
|
|
# Validate real claims and exact current decisions before any consumption.
|
|
actions=('exec',) if resume else tuple(IDS)
|
|
for action in actions:
|
|
auth=authorize_action(configs[action],entries[action],action,fields=() if action=='apply' else tuple(entries[action].fields),policy_targets=(ROLE,),auth_targets=(ROLE,))
|
|
require(auth is not None,'native_authorization_missing')
|
|
receipt['phase']='all_claims_and_pdp_checks_passed';save(receipt)
|
|
client=OpenBaoClient.resolve('http://127.0.0.1:18200')
|
|
existing=client.read_policy(ROLE)
|
|
if resume:
|
|
prior=resume_receipt()
|
|
plan=build_plan(entries['apply'],'prod')
|
|
require(existing is not None and existing.strip()==plan.policy_hcl.strip(),'applied_policy_drift')
|
|
role=bao('read','-format=json','auth/approle/role/'+ROLE)['data']
|
|
require(all(role.get(k)==v for k,v in prior['actions'][0]['limits'].items()) and role.get('token_policies')==[ROLE],'applied_role_drift')
|
|
code="import json;from approval_engine.store import Engine;e=Engine('/data/approvals.sqlite');print(json.dumps({k:e.claim(v) for k,v in "+repr(IDS)+".items()}))"
|
|
claims=json.loads(run(*KUBE,'-n','approval-engine','exec','statefulset/approval-engine','--','python','-c',code))
|
|
require(all(claims[a]['consumed'] and claims[a]['approval_id']==IDS[a] for a in ('apply','verify')) and claims['exec']['valid_now'] and not claims['exec']['consumed'],'resume_approval_state_mismatch')
|
|
receipt['prior_receipt']='2026-09-15-t03-native-execution.json'
|
|
receipt['completed_actions_not_replayed']=['apply','verify']
|
|
receipt['supplemental_cleanup']=verify_session_cleanup(client);save(receipt)
|
|
else:
|
|
require(existing is None and not client.approle_exists(ROLE),'existing_native_objects_require_reconciliation')
|
|
for action in actions:
|
|
receipt['phase']=action+'_attempt_started';save(receipt)
|
|
if action=='apply':argv=['apply',LANE,'--stage','prod','--auth','env']
|
|
elif action=='verify':argv=['verify',LANE,'--auth','env','--negative-token-file',str(negative)]
|
|
else:argv=['exec','--catalog',LANE,'--auth','env','--mode','exec-env','--',*command]
|
|
args=build_parser().parse_args(argv)
|
|
if action=='exec':args.command=args.command[1:]
|
|
output=io.StringIO()
|
|
with contextlib.redirect_stdout(output),contextlib.redirect_stderr(io.StringIO()):rc=args.func(configs[action],args)
|
|
require(rc==0,'native_action_failed')
|
|
row={'action':action,'approval_id':IDS[action],'exit_code':rc}
|
|
if action=='apply':
|
|
role=bao('read','-format=json','auth/approle/role/'+ROLE)['data']
|
|
limits={'token_ttl':900,'token_max_ttl':1800,'secret_id_ttl':900,'secret_id_num_uses':1,'token_num_uses':8}
|
|
require(all(role.get(k)==v for k,v in limits.items()) and role.get('token_policies')==[ROLE],'role_limits_mismatch');row['limits']=limits
|
|
elif action=='verify':
|
|
row.update(verify_session_cleanup(client))
|
|
else:
|
|
result=json.loads(output.getvalue());require(result=={'result':'authenticated','http_status':200},'key_check_result_invalid');row['key_check']=result
|
|
receipt['actions'].append(row);receipt['phase']=action+'_completed';save(receipt)
|
|
receipt['health_after']=health();receipt['status']='passed';receipt['phase']='all_actions_completed'
|
|
except Exception as exc:
|
|
receipt['failure_type']=type(exc).__name__
|
|
import traceback
|
|
frame=traceback.extract_tb(exc.__traceback__)[-1]
|
|
receipt['failure_location']=frame.filename+':'+str(frame.lineno)
|
|
# Only explicit local codes are eligible; no backend exception text is exported.
|
|
if type(exc) is ValueError and str(exc).replace('_','').isalnum():receipt['failure_code']=str(exc)
|
|
raise
|
|
finally:
|
|
for p in forwards:
|
|
p.terminate()
|
|
try:p.wait(timeout=5)
|
|
except subprocess.TimeoutExpired:p.kill();p.wait()
|
|
receipt['owner_forwards_closed']=True;save(receipt)
|
|
|
|
if __name__=='__main__':
|
|
p=argparse.ArgumentParser();p.add_argument('mode',choices=['preflight','admin','resume-exec']);p.add_argument('--directory',type=Path);p.add_argument('--negative-token-file',type=Path);a=p.parse_args()
|
|
try:
|
|
if a.mode=='preflight':
|
|
with tempfile.TemporaryDirectory() as t:prepare(Path(t))
|
|
print('Three frozen requests and pinned recipient passed; native claims checked at execution.')
|
|
else:
|
|
if a.mode=='resume-exec':
|
|
resume_receipt()
|
|
RECEIPT=ROOT/'docs/evidence/2026-09-16-t03-resume-exec.json'
|
|
admin(a.directory,a.negative_token_file,resume=a.mode=='resume-exec')
|
|
except Exception:
|
|
if a.mode=='preflight':raise
|
|
raise SystemExit(1) from None
|