railiance-platform/scripts/render_backup_credential_contract.py
codex acbc78ffea
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Commit the prepared backup reader for both archive pairs.
The helper previews delivery with no OpenBao or node effect and refuses execution while the CCRs stay draft. Policies are read-only on each workload path. No provider key is included.

Assistant: grok
Assistant-Session: 01a11cdb-f9fe-7011-947c-936e72007e54
2026-10-08 22:12:34 +02:00

62 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Export a validated, public CCR as JSON for the stdlib node delivery helper.
Uses the platform's existing PyYAML validator. No credential lookup or live call.
After CCR status updates, YAML remains the source of truth; export and review its
new JSON hash before an attended delivery. Draft exports remain non-executable.
"""
from __future__ import annotations
import argparse
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import sys
from application_backup_credentials import PROFILES, contract
ROOT = Path(__file__).resolve().parents[1]
def render(source, application):
spec = importlib.util.spec_from_file_location("backup_ccr_validator", ROOT / "scripts/credential-change.py")
validator = importlib.util.module_from_spec(spec)
spec.loader.exec_module(validator)
ccr, errors, _ = validator.validate_ccr(source)
if errors or validator.applier_policy_violations(ccr):
raise ValueError("invalid_reader_contract")
policy = validator.policy_artifact_diff(ccr)
if not policy["matches"]:
raise ValueError("policy_source_mismatch")
ccr["source_ccr_sha256"] = hashlib.sha256(source.read_bytes()).hexdigest()
ccr["policy_sha256"] = hashlib.sha256(validator.generated_policy_hcl(ccr).encode()).hexdigest()
raw = (json.dumps(ccr, indent=2, sort_keys=True) + "\n").encode()
contract(raw, application)
return raw
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--ccr", type=Path, required=True)
parser.add_argument("--application", choices=PROFILES, required=True)
parser.add_argument("--output", type=Path, required=True)
args = parser.parse_args()
try:
raw = render(args.ccr, args.application)
fd = os.open(args.output, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
with os.fdopen(fd, "wb") as stream:
stream.write(raw)
stream.flush()
os.fsync(stream.fileno())
print(json.dumps({"status": "rendered", "application": args.application,
"ccr_sha256": hashlib.sha256(raw).hexdigest(), "effects": ["public_contract_export"]}))
return 0
except Exception: # noqa: BLE001 - metadata-only fixed diagnostics
print('{"status":"failed","code":"contract_export_failed"}', file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())