docs(custody): record attended KeyCape first-provision authority proof
Assistant: codex Assistant-Model: gpt-5.6-luna Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc
This commit is contained in:
parent
a0bbae842c
commit
a94d06dbcf
5 changed files with 204 additions and 0 deletions
64
scripts/keycape-approval-custody-preflight.py
Normal file
64
scripts/keycape-approval-custody-preflight.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"""Read-only, silent owner preflight inside Warden's attended login envelope.
|
||||
|
||||
Queries only token capabilities for the exact two reviewed CCR targets. Reads
|
||||
no secret data, applies no metadata, and does not record an approval. Warden
|
||||
owns the temporary token helper and self-revokes after this command returns.
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
PATHS = [
|
||||
'sys/policies/acl/workload-kv-read-keycape-secrets-engine-approval',
|
||||
'sys/policies/acl/workload-kv-read-keycape-approval-engine-operator',
|
||||
'auth/kubernetes/role/external-secrets-keycape-secrets-engine-approval',
|
||||
'auth/kubernetes/role/external-secrets-keycape-approval-engine-operator',
|
||||
'platform/data/workloads/secrets-engine/approval-client',
|
||||
'platform/data/workloads/approval-engine/operator-client',
|
||||
]
|
||||
ALLOWED = {'create', 'read', 'update', 'patch', 'delete', 'list', 'sudo', 'deny', 'root'}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--receipt", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
receipt = {'observed_at': datetime.now(timezone.utc).isoformat(),
|
||||
'requests': ['CCR-2026-0017', 'CCR-2026-0018'],
|
||||
'operation': 'capabilities-self only', 'credential_data_read': False,
|
||||
'metadata_applied': False, 'custody_activated': False,
|
||||
'upstream_issuer_proven': False}
|
||||
caps = {}
|
||||
for path in PATHS:
|
||||
# This installed CLI accepts one PATH. Supplying several positional
|
||||
# arguments selects a different TOKEN/PATH form or refuses the call.
|
||||
result = subprocess.run(['bao', 'token', 'capabilities', '-format=json', path],
|
||||
capture_output=True, text=True, timeout=20)
|
||||
if result.returncode:
|
||||
receipt['status'] = 'capability-query-failed'
|
||||
break
|
||||
payload = json.loads(result.stdout)
|
||||
values = payload if isinstance(payload, list) else payload.get('capabilities')
|
||||
if not isinstance(values, list) or any(v not in ALLOWED for v in values):
|
||||
raise ValueError('unexpected capability response shape')
|
||||
caps[path] = sorted(set(values))
|
||||
else:
|
||||
receipt['status'] = 'observed'
|
||||
receipt['capabilities'] = caps
|
||||
receipt['required_metadata_capabilities_present'] = all(
|
||||
{'create', 'update'}.issubset(values) for values in caps.values())
|
||||
receipt['paths_verified'] = len(caps)
|
||||
fd = os.open(args.receipt, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
||||
with os.fdopen(fd, 'w') as stream:
|
||||
json.dump(receipt, stream, indent=2)
|
||||
stream.write('\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception:
|
||||
raise SystemExit(1) from None
|
||||
Loading…
Add table
Add a link
Reference in a new issue