243 lines
11 KiB
Python
243 lines
11 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Silent attended exact-policy update and existing reviewed reader bootstrap.
|
||
|
|
|
||
|
|
Unlike generic CCR metadata apply, this command NEVER writes the reused ESO role.
|
||
|
|
Installed role drift and differing ACL stop before mutations. --preflight reads
|
||
|
|
only role/ACL metadata; it does not request Forgejo credentials. --execute needs
|
||
|
|
approved CCR plus exact bootstrap and runner artifact receipts. Outer sanctioned
|
||
|
|
OpenBao login owns identity, browser, helper containment and self-revocation.
|
||
|
|
"""
|
||
|
|
import argparse
|
||
|
|
import hashlib
|
||
|
|
import importlib.util
|
||
|
|
import json
|
||
|
|
import os
|
||
|
|
import tempfile
|
||
|
|
from pathlib import Path
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import yaml
|
||
|
|
|
||
|
|
ROOT=Path(__file__).resolve().parent.parent
|
||
|
|
SCRIPT='scripts/apply-reuse-surface-reader-custody.py'
|
||
|
|
CANDIDATE_FILE='docs/proposals/2026-10-15-reuse-private-reader/conditional-approved-ccr-state-candidate-r1.json'
|
||
|
|
POLICY_FILE='openbao/policies/workload-kv-read-reuse-surface-runtime-eso.hcl'
|
||
|
|
POLICY='workload-kv-read-reuse-surface-runtime-eso'
|
||
|
|
ROLE='auth/kubernetes/role/reuse-surface-runtime-eso'
|
||
|
|
BASELINE='''path "platform/data/workloads/reuse/reuse-surface/runtime-secrets" {
|
||
|
|
capabilities = ["read"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "auth/token/lookup-self" {
|
||
|
|
capabilities = ["read"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "auth/token/revoke-self" {
|
||
|
|
capabilities = ["update"]
|
||
|
|
}
|
||
|
|
'''
|
||
|
|
spec=importlib.util.spec_from_file_location('reuse_reader_bootstrap',ROOT/'scripts/provision-reuse-surface-forgejo-source.py')
|
||
|
|
p=importlib.util.module_from_spec(spec);spec.loader.exec_module(p)
|
||
|
|
|
||
|
|
|
||
|
|
def validate_role(data):
|
||
|
|
expected={'bound_service_account_names':['reuse-surface-eso'],'bound_service_account_namespaces':['reuse'],
|
||
|
|
'audience':'openbao','token_ttl':900,'token_max_ttl':900,'token_explicit_max_ttl':900,
|
||
|
|
'token_no_default_policy':True,'token_policies':[POLICY]}
|
||
|
|
if not isinstance(data,dict) or any(data.get(k)!=v for k,v in expected.items()):
|
||
|
|
raise p.Refused('installed_eso_role_drift')
|
||
|
|
if 'policies' in data and data['policies']!=[POLICY]:
|
||
|
|
raise p.Refused('installed_eso_role_drift')
|
||
|
|
if data.get('token_period',0)!=0 or data.get('token_bound_cidrs',[]) or data.get('bound_service_account_namespace_selector',''):
|
||
|
|
raise p.Refused('installed_eso_role_drift')
|
||
|
|
|
||
|
|
|
||
|
|
def read_policy():
|
||
|
|
result=p.Bao.run(['policy','read',POLICY])
|
||
|
|
if result.returncode!=0:
|
||
|
|
raise p.Refused('policy_read_failed')
|
||
|
|
try:
|
||
|
|
return result.stdout.decode().strip()
|
||
|
|
except Exception:
|
||
|
|
raise p.Refused('policy_invalid_encoding') from None
|
||
|
|
|
||
|
|
|
||
|
|
def preflight(journal, desired_text=None):
|
||
|
|
result=p.Bao.run(['read','-format=json',ROLE])
|
||
|
|
if result.returncode!=0:
|
||
|
|
raise p.Refused('installed_eso_role_read_failed')
|
||
|
|
try:
|
||
|
|
data=json.loads(result.stdout)['data']
|
||
|
|
except Exception:
|
||
|
|
raise p.Refused('installed_eso_role_invalid') from None
|
||
|
|
validate_role(data)
|
||
|
|
desired=(ROOT/POLICY_FILE).read_text().strip() if desired_text is None else desired_text
|
||
|
|
current=read_policy()
|
||
|
|
if current not in (BASELINE.strip(),desired):
|
||
|
|
raise p.Refused('installed_policy_drift')
|
||
|
|
journal.put('verified',operation='installed_eso_role_and_policy',status='matched_immutable_role')
|
||
|
|
return current,desired
|
||
|
|
|
||
|
|
|
||
|
|
def approval_envelope(path):
|
||
|
|
"""Bind conditional future CCR bytes without recording imaginary consent."""
|
||
|
|
try:
|
||
|
|
receipt=json.loads(Path(path).read_text())
|
||
|
|
if receipt['ccr_id']!=p.CCR or receipt['decision']!='approved' or not receipt['supervisor'] or not receipt['decision_ref']:
|
||
|
|
raise p.Refused('runner_approval_invalid')
|
||
|
|
if set(receipt['runner_artifacts'])!={SCRIPT,POLICY_FILE,CANDIDATE_FILE}:
|
||
|
|
raise p.Refused('runner_approval_artifact_set')
|
||
|
|
for rel in (SCRIPT,POLICY_FILE,CANDIDATE_FILE):
|
||
|
|
if hashlib.sha256((ROOT/rel).read_bytes()).hexdigest()!=receipt['runner_artifacts'][rel]:
|
||
|
|
raise p.Refused('runner_approved_revision_mismatch')
|
||
|
|
wrapper=json.loads((ROOT/CANDIDATE_FILE).read_text())
|
||
|
|
before=wrapper['source_yaml'].encode()
|
||
|
|
after=wrapper['candidate_yaml'].encode()
|
||
|
|
if hashlib.sha256(before).hexdigest()!=wrapper['source_sha256'] or hashlib.sha256(after).hexdigest()!=wrapper['candidate_sha256']:
|
||
|
|
raise p.Refused('candidate_digest_invalid')
|
||
|
|
old=yaml.safe_load(before); new=yaml.safe_load(after)
|
||
|
|
if old['id']!=p.CCR or old['status']!='proposed' or old['openbao']['auth']['bound_claims_confirmed'] is not False:
|
||
|
|
raise p.Refused('candidate_predecessor_invalid')
|
||
|
|
old['status']='approved'; old['openbao']['auth']['bound_claims_confirmed']=True
|
||
|
|
if old!=new:
|
||
|
|
raise p.Refused('candidate_changes_exceed_scope')
|
||
|
|
exact={p.CCR_FILE,p.PLAN_FILE,p.SCRIPT_FILE,POLICY_FILE}
|
||
|
|
if set(receipt['approved_artifacts'])!=exact or receipt['approved_artifacts'][p.CCR_FILE]!=wrapper['candidate_sha256']:
|
||
|
|
raise p.Refused('candidate_approval_invalid')
|
||
|
|
for rel in exact-{p.CCR_FILE}:
|
||
|
|
if hashlib.sha256((ROOT/rel).read_bytes()).hexdigest()!=receipt['approved_artifacts'][rel]:
|
||
|
|
raise p.Refused('bootstrap_approved_revision_mismatch')
|
||
|
|
current=(ROOT/p.CCR_FILE).read_bytes()
|
||
|
|
if current not in (before,after):
|
||
|
|
raise p.Refused('ccr_source_precondition_failed')
|
||
|
|
return before,after,receipt['approved_artifacts'][POLICY_FILE]
|
||
|
|
except p.Refused:
|
||
|
|
raise
|
||
|
|
except Exception:
|
||
|
|
raise p.Refused('runner_approval_invalid') from None
|
||
|
|
|
||
|
|
|
||
|
|
def activate_candidate(before,after,journal):
|
||
|
|
"""Called ONLY after receipt validation and installed claims verification."""
|
||
|
|
path=ROOT/p.CCR_FILE
|
||
|
|
if path.read_bytes()==after:
|
||
|
|
return
|
||
|
|
if path.read_bytes()!=before:
|
||
|
|
raise p.Refused('ccr_source_precondition_failed')
|
||
|
|
journal.put('intent',operation='conditional_ccr_state_transition')
|
||
|
|
temporary=None
|
||
|
|
try:
|
||
|
|
with tempfile.NamedTemporaryFile(dir=path.parent,prefix='.cust81-ccr-',delete=False) as file:
|
||
|
|
temporary=Path(file.name)
|
||
|
|
file.write(after);file.flush();os.fsync(file.fileno())
|
||
|
|
os.chmod(temporary,path.stat().st_mode & 0o777)
|
||
|
|
if path.read_bytes()!=before:
|
||
|
|
raise p.Refused('ccr_source_precondition_failed')
|
||
|
|
os.replace(temporary,path);temporary=None
|
||
|
|
directory=os.open(path.parent,os.O_DIRECTORY)
|
||
|
|
try: os.fsync(directory)
|
||
|
|
finally: os.close(directory)
|
||
|
|
if path.read_bytes()!=after:
|
||
|
|
raise p.Refused('ccr_transition_unverified')
|
||
|
|
journal.put('verified',operation='conditional_ccr_state_transition',status='exact_candidate_installed_after_claim_proof')
|
||
|
|
finally:
|
||
|
|
if temporary is not None:
|
||
|
|
temporary.unlink(missing_ok=True)
|
||
|
|
|
||
|
|
|
||
|
|
def verify_ready(journal,desired):
|
||
|
|
current,_=preflight(journal,desired_text=desired)
|
||
|
|
if current!=desired:
|
||
|
|
raise p.Refused('approved_policy_not_installed')
|
||
|
|
journal.put('verified',operation='desired_acl_and_immutable_role',status='matched')
|
||
|
|
|
||
|
|
|
||
|
|
def execute(approval,receipt,journal):
|
||
|
|
before,after,approved_policy_sha256=approval_envelope(approval)
|
||
|
|
current,_=preflight(journal)
|
||
|
|
activate_candidate(before,after,journal)
|
||
|
|
p.approval(approval)
|
||
|
|
# Capture exact approved bytes once. Later repo-file changes cannot alter
|
||
|
|
# the authorized ACL input: Bao receives only this snapshot through stdin.
|
||
|
|
policy_snapshot=(ROOT/POLICY_FILE).read_bytes()
|
||
|
|
if hashlib.sha256(policy_snapshot).hexdigest()!=approved_policy_sha256:
|
||
|
|
raise p.Refused('approved_policy_snapshot_mismatch')
|
||
|
|
try:
|
||
|
|
desired=policy_snapshot.decode().strip()
|
||
|
|
except Exception:
|
||
|
|
raise p.Refused('policy_invalid_encoding') from None
|
||
|
|
if current!=desired:
|
||
|
|
# Recheck immediately before the exact write. OpenBao ACL has no CAS;
|
||
|
|
# this is an attended owner operation, never an unattended reconcile.
|
||
|
|
if read_policy()!=current:
|
||
|
|
raise p.Refused('policy_changed_since_preflight')
|
||
|
|
journal.put('intent',operation='exact_eso_policy_update')
|
||
|
|
try:
|
||
|
|
result=p.Bao.run(['policy','write',POLICY,'-'],stdin=policy_snapshot)
|
||
|
|
except p.Refused:
|
||
|
|
journal.put('outcome',operation='exact_eso_policy_update',status='ambiguous')
|
||
|
|
raise
|
||
|
|
journal.put('outcome',operation='exact_eso_policy_update',status='observed' if result.returncode==0 else 'ambiguous')
|
||
|
|
if read_policy()!=desired:
|
||
|
|
raise p.Refused('policy_update_unverified')
|
||
|
|
journal.put('verified',operation='exact_eso_policy_update',status='matched')
|
||
|
|
# Verify both immutable role and desired ACL even on the idempotent path.
|
||
|
|
verify_ready(journal,desired)
|
||
|
|
journal.put('intent',operation='reviewed_forgejo_bootstrap_route')
|
||
|
|
try:
|
||
|
|
result=subprocess.run([sys.executable,str(ROOT/p.SCRIPT_FILE),'--approval',str(Path(approval).resolve()),'--receipt',str(Path(receipt).resolve())],capture_output=True,check=False,timeout=1000,cwd=ROOT)
|
||
|
|
except Exception:
|
||
|
|
journal.put('outcome',operation='reviewed_forgejo_bootstrap_route',status='ambiguous')
|
||
|
|
raise p.Refused('bootstrap_observation_failed') from None
|
||
|
|
# Even whitespace violates quiet owner command. Raw child/network bytes
|
||
|
|
# never enter receipts or caller output; failed/ambiguous writes retained.
|
||
|
|
if result.returncode!=0 or result.stdout or result.stderr:
|
||
|
|
journal.put('outcome',operation='reviewed_forgejo_bootstrap_route',status='stopped_check_child_receipt')
|
||
|
|
raise p.Refused('bootstrap_route_unverified')
|
||
|
|
journal.put('outcome',operation='reviewed_forgejo_bootstrap_route',status='observed_success')
|
||
|
|
verify_ready(journal,desired)
|
||
|
|
journal.put('terminal',outcome='policy_and_custody_verified_delivery_pending')
|
||
|
|
|
||
|
|
|
||
|
|
def main(argv=None):
|
||
|
|
parser=argparse.ArgumentParser()
|
||
|
|
mode=parser.add_mutually_exclusive_group(required=True)
|
||
|
|
mode.add_argument('--preflight',action='store_true')
|
||
|
|
mode.add_argument('--execute',action='store_true')
|
||
|
|
parser.add_argument('--approval')
|
||
|
|
parser.add_argument('--receipt',required=True)
|
||
|
|
parser.add_argument('--bootstrap-receipt')
|
||
|
|
args=parser.parse_args(argv)
|
||
|
|
journal=None
|
||
|
|
lane_lock=None
|
||
|
|
try:
|
||
|
|
if args.execute and (not args.approval or not args.bootstrap_receipt or Path(args.receipt).resolve()==Path(args.bootstrap_receipt).resolve()):
|
||
|
|
raise p.Refused('execute_inputs_invalid')
|
||
|
|
lane_lock=os.open('/tmp/'+p.CCR+'-policy-state-'+str(os.getuid())+'.lock',os.O_RDWR|os.O_CREAT|os.O_NOFOLLOW,0o600)
|
||
|
|
if os.fstat(lane_lock).st_uid!=os.getuid() or os.fstat(lane_lock).st_mode & 0o077:
|
||
|
|
raise p.Refused('lane_lock_owner_or_permissions')
|
||
|
|
p.fcntl.flock(lane_lock,p.fcntl.LOCK_EX|p.fcntl.LOCK_NB)
|
||
|
|
journal=p.Journal(args.receipt)
|
||
|
|
if args.preflight:
|
||
|
|
preflight(journal)
|
||
|
|
journal.put('terminal',outcome='read_only_preflight_verified')
|
||
|
|
else:
|
||
|
|
execute(args.approval,args.bootstrap_receipt,journal)
|
||
|
|
return 0
|
||
|
|
except Exception as error:
|
||
|
|
if journal:
|
||
|
|
journal.put('terminal',outcome='stopped_reconcile_before_retry',error_code=str(error) if isinstance(error,p.Refused) else 'internal_failure')
|
||
|
|
return 1
|
||
|
|
finally:
|
||
|
|
if journal:
|
||
|
|
journal.close()
|
||
|
|
if lane_lock is not None:
|
||
|
|
os.close(lane_lock)
|
||
|
|
|
||
|
|
if __name__=='__main__':
|
||
|
|
try:
|
||
|
|
result=main()
|
||
|
|
except Exception:
|
||
|
|
result=1
|
||
|
|
raise SystemExit(result)
|