#!/usr/bin/env python3 """Attended custody child for CCR-2026-0033: KeyCape `secrets-engine-openbao` client secret. SOURCE ONLY until the founder approves this exact child. One run generates one value in process memory, compare-before-writes it as the authoritative KV-v2 version, writes the secrets-engine consumer copy in the same process, runs the consumer's value-free acceptance check and writes a metadata-only receipt. It never reads the KV value, never prints the value, never puts it in argv or the environment, and does not touch policies, roles, ESO, KeyCape or the cluster (later live steps, see CCR-2026-0033 live_order). """ from __future__ import annotations import argparse import hashlib import importlib.util import json import os from pathlib import Path import re import secrets import stat import sys from datetime import datetime, timezone sys.path.insert(0, str(Path(__file__).resolve().parent)) from state_hub_preflight_lane import ROOT, LaneError, bao, command, data # noqa: E402 CCR_ID = 'CCR-2026-0033' CCR_PATH = ROOT / 'credential-change-requests/CCR-2026-0033.yaml' BOUNDARY_DECISION = '632a8893-0d6a-4591-a50b-40bbdb798f32' KV_PATH = 'platform/workloads/keycape/secrets-engine-openbao' KV_DATA = 'platform/data/workloads/keycape/secrets-engine-openbao' KV_METADATA = 'platform/metadata/workloads/keycape/secrets-engine-openbao' FIELD = 'CLIENT_SECRET' # secrets-engine coordinates (SECRETS-WP-0012, a3897c2); D1-D4 pending founder choice. CONSUMER_FILE = Path('/home/worsch/.secrets-engine/keycape/secrets-engine-openbao.client-secret') APPROVERS = ('platform-owner', 'key-cape-owner', 'net-kingdom-owner') UUID_RE = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') def require(condition, reason): if not condition: raise LaneError(reason) def attended_envelope(): return (Path.home().parent.name == '.warden-attended-login' and not os.environ.get('BAO_TOKEN') and not os.environ.get('VAULT_TOKEN')) def contract(decision_id): require(isinstance(decision_id, str) and UUID_RE.match(decision_id), 'approval_decision_id_required') require(decision_id != BOUNDARY_DECISION, 'boundary_decision_does_not_approve_custody_child') spec = importlib.util.spec_from_file_location('credential_change', ROOT / 'scripts/credential-change.py') module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) ccr, errors, _ = module.validate_ccr(CCR_PATH) require(not errors and ccr['id'] == CCR_ID, 'valid_ccr_required') require(ccr['status'] == 'approved', 'approved_ccr_required') comments = ccr['review']['comments'] for role in APPROVERS: require(any(c.get('decision') == 'approved' and role in c.get('reviewer', '') for c in comments), 'all_named_reviews_required') require(any(c.get('decision') == 'approved' and decision_id in str(c.get('comment', '')) for c in comments), 'custody_child_decision_not_recorded_in_ccr') openbao = ccr['openbao'] require(openbao['kv_path'] == KV_PATH and openbao['fields'] == [FIELD] and openbao['auth']['bound_claims_confirmed'] is True and ccr['custody_child']['script'] == 'scripts/keycape_secrets_engine_openbao_custody.py' and ccr['consumer_copy']['file'] == str(CONSUMER_FILE), 'exact_approved_contract_required') return hashlib.sha256(CCR_PATH.read_bytes()).hexdigest() def kv_current_version(): """Metadata only. None when the path has never been written.""" result = bao(['read', '-format=json', KV_METADATA], allow_failure=True) if result.returncode != 0: require(b'404' in result.stderr or b'No value found' in result.stderr, 'absence_not_proven') return None meta = data(result)['data'] current = meta['current_version'] version = meta['versions'][str(current)] require(not version.get('destroyed') and not version.get('deletion_time'), 'current_version_not_live') return current def write_kv(value, cas): result = data(bao(['write', '-format=json', KV_DATA, '-'], payload={'options': {'cas': cas}, 'data': {FIELD: value}})) require(result['data']['version'] == cas + 1, 'unexpected_kv_version') return result['data']['version'], result.get('request_id') def fsync_dir(path): fd = os.open(path, os.O_RDONLY | os.O_DIRECTORY) try: os.fsync(fd) finally: os.close(fd) def prepare_parent(target): parent = target.parent grand = os.lstat(parent.parent) require(stat.S_ISDIR(grand.st_mode), 'consumer_grandparent_invalid') try: info = os.lstat(parent) except FileNotFoundError: os.mkdir(parent, 0o700) fsync_dir(parent.parent) info = os.lstat(parent) require(stat.S_ISDIR(info.st_mode) and info.st_uid == os.geteuid() and stat.S_IMODE(info.st_mode) == 0o700, 'consumer_parent_must_be_owned_0700_directory') require(not os.path.lexists(target), 'consumer_file_exists_rotation_needs_separate_approval') def write_consumer(target, value, receipt): parent = target.parent temp = parent / ('.' + target.name + '.' + secrets.token_hex(8) + '.tmp') fd = os.open(temp, os.O_CREAT | os.O_EXCL | os.O_WRONLY | os.O_NOFOLLOW, 0o600) try: try: os.write(fd, (value + '\n').encode()) os.fsync(fd) finally: os.close(fd) os.rename(temp, target) fsync_dir(parent) except BaseException: try: os.unlink(temp) receipt['consumer_temp_removed'] = True except FileNotFoundError: pass raise info = os.lstat(target) require(stat.S_ISREG(info.st_mode) and stat.S_IMODE(info.st_mode) == 0o600 and info.st_uid == os.geteuid(), 'consumer_file_readback_failed') def check_consumer(target, secrets_engine): result = command([secrets_engine, 'service-auth', 'check-secret-file', '--path', str(target), '--json'], allow_failure=True) try: ok = bool(json.loads(result.stdout).get('ok')) except (ValueError, AttributeError): ok = False return result.returncode == 0 and ok def retry_cas(prior_path, current): prior = json.loads(Path(prior_path).read_text()) require(prior.get('ccr') == CCR_ID and prior.get('status') == 'failed' and prior.get('kv_written') and not prior.get('consumer_written'), 'retryable_partial_receipt_required') require(current is not None and prior.get('kv_version') == current, 'kv_version_changed_since_prior_receipt') return current def run(args, receipt): receipt['approval_decision_id'] = args.approval_decision receipt['ccr_sha256'] = contract(args.approval_decision) require(attended_envelope(), 'attended_warden_envelope_required') os.umask(0o077) identity = data(bao(['token', 'lookup', '-format=json']))['data'] require('platform-admin' in identity['policies'] and 'root' not in identity['policies'], 'attended_platform_admin_required') current = kv_current_version() if args.prior_receipt: cas = retry_cas(args.prior_receipt, current) receipt['retry_of_kv_version'] = cas else: require(current is None, 'existing_custody_requires_retry_receipt_or_rotation_approval') cas = 0 prepare_parent(CONSUMER_FILE) receipt['phase'] = 'kv_write' value = secrets.token_urlsafe(48) try: version, request_id = write_kv(value, cas) receipt.update(kv_written=True, kv_version=version, kv_request_id=request_id, kv_cas=cas) receipt['phase'] = 'consumer_write' write_consumer(CONSUMER_FILE, value, receipt) receipt['consumer_written'] = True finally: value = None receipt['phase'] = 'consumer_check' receipt['consumer_check_ok'] = check_consumer(CONSUMER_FILE, args.secrets_engine) require(receipt['consumer_check_ok'], 'consumer_check_failed') receipt['status'] = 'custody_written_pending_issuer_delivery' receipt['phase'] = 'done' def main(argv=None): parser = argparse.ArgumentParser(description=__doc__.splitlines()[0]) parser.add_argument('action', choices=['provision']) parser.add_argument('--approval-decision', required=True, help='founder decision id approving this exact custody child') parser.add_argument('--receipt', required=True) parser.add_argument('--prior-receipt', help='failed receipt with kv_written and no consumer file') parser.add_argument('--secrets-engine', default='secrets-engine', help='secrets-engine executable') args = parser.parse_args(argv) receipt = {'schema': 'platform.keycape-secrets-engine-openbao-custody.v1', 'ccr': CCR_ID, 'status': 'failed', 'phase': 'preflight', 'started_at': datetime.now(timezone.utc).isoformat(), 'credential_values_emitted': False, 'client_side_read_admitted': False, 'kv_written': False, 'consumer_written': False} fd = os.open(args.receipt, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) try: run(args, receipt) except Exception as exc: receipt['status'] = 'failed' receipt['error'] = str(exc) if isinstance(exc, LaneError) else 'contained_operation_failed' finally: receipt['finished_at'] = datetime.now(timezone.utc).isoformat() with os.fdopen(fd, 'w') as out: json.dump(receipt, out, indent=2) out.write('\n') return 0 if receipt['status'] != 'failed' else 1 if __name__ == '__main__': raise SystemExit(main())