Attended, silent, check-and-set. Evidence 2026-10-02: created, version 1, no values. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: sonnet Assistant-Process: 292700@bnt-lap001 Assistant-Session: 42de6b79-9019-4cfd-b49a-6db3bbfe9341
180 lines
6.1 KiB
Python
Executable file
180 lines
6.1 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Attended seed of the tenant-engine sender token into its dedicated KV path.
|
|
|
|
ops-mason MASON-WP-0007 / tenant-engine TEN-IN-0005, plan row 7. The registry
|
|
document holds every sender, and OpenBao policies scope by path, not by field,
|
|
so External Secrets reads a one-field copy instead:
|
|
|
|
source: platform/data/workloads/audit-core/senders (sender "tenant-engine")
|
|
destination: platform/data/workloads/tenant-engine/audit-core-sender (field "token")
|
|
|
|
Read and write happen in this one process. The token is never printed, never
|
|
passed on a command line, never written to evidence; evidence holds versions,
|
|
booleans and counts only. Silent: warden access --exec fails closed on any
|
|
child stdout/stderr.
|
|
|
|
./scripts/attended-seed-tenant-engine-audit-core-sender.sh
|
|
|
|
Re-running is safe. Equal value: no write. Different value (rotation re-seed):
|
|
one check-and-set write against the version just read. No destination: cas 0.
|
|
When the registry holds several tokens for the sender (rotation overlap), the
|
|
last one is seeded, which is the newest appended.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
|
|
REGISTRY = "platform/data/workloads/audit-core/senders"
|
|
SENDER = "tenant-engine"
|
|
DEST_DATA = "platform/data/workloads/tenant-engine/audit-core-sender"
|
|
DEST_META = "platform/metadata/workloads/tenant-engine/audit-core-sender"
|
|
FIELD = "token"
|
|
EVIDENCE_DIR = Path("/home/worsch/audit-core/docs/evidence")
|
|
|
|
|
|
class NotFound(Exception):
|
|
"""The path holds no value. Distinct from a failed call."""
|
|
|
|
|
|
def _now() -> str:
|
|
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
|
|
|
|
|
def evidence_path() -> Path:
|
|
return EVIDENCE_DIR / f"{_now()[:10]}-tenant-engine-audit-core-sender-seed.json"
|
|
|
|
|
|
def _evidence(step: str, extra: dict | None = None) -> None:
|
|
doc = {
|
|
"step": step,
|
|
"observed_at": _now(),
|
|
"sender": SENDER,
|
|
"source": "platform/workloads/audit-core/senders",
|
|
"destination": "platform/workloads/tenant-engine/audit-core-sender",
|
|
"credential_values_emitted": False,
|
|
}
|
|
if extra:
|
|
doc.update(extra)
|
|
path = evidence_path()
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(json.dumps(doc, indent=2) + "\n")
|
|
|
|
|
|
def _fail(reason: str, extra: dict | None = None) -> int:
|
|
payload = {"reason": reason}
|
|
if extra:
|
|
payload.update(extra)
|
|
_evidence("failed", payload)
|
|
return 1
|
|
|
|
|
|
def bao(args: list[str], *, payload: dict | None = None) -> dict:
|
|
env = os.environ.copy()
|
|
for name in ("BAO_TOKEN", "VAULT_TOKEN", "OPENBAO_TOKEN"):
|
|
env.pop(name, None)
|
|
proc = subprocess.run(
|
|
["bao", *args],
|
|
input=None if payload is None else json.dumps(payload).encode(),
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
env=env,
|
|
check=False,
|
|
)
|
|
if proc.returncode != 0:
|
|
# stderr is inspected, never emitted.
|
|
err = proc.stderr.decode(errors="replace").lower()
|
|
if "no value found" in err or "404" in err:
|
|
raise NotFound()
|
|
raise RuntimeError("bao_failed")
|
|
return json.loads(proc.stdout.decode() or "{}")
|
|
|
|
|
|
def pick_token(rows: list) -> str:
|
|
"""The sender's newest token. Raises ValueError with a reason, never a value."""
|
|
row = next((r for r in rows if isinstance(r, dict) and r.get("name") == SENDER), None)
|
|
if row is None:
|
|
raise ValueError("sender_not_in_registry")
|
|
tokens = [t for t in (row.get("tokens") or []) if isinstance(t, str) and t]
|
|
if not tokens:
|
|
raise ValueError("sender_has_no_tokens")
|
|
return tokens[-1]
|
|
|
|
|
|
def seed(token: str, call=bao) -> dict:
|
|
"""Write token to the destination if needed. Returns metadata only."""
|
|
try:
|
|
current = call(["read", "-format=json", DEST_DATA])["data"]
|
|
version = current["metadata"]["version"]
|
|
existing = (current.get("data") or {}).get(FIELD)
|
|
except NotFound:
|
|
version, existing = 0, None
|
|
if existing == token:
|
|
return {"action": "already_seeded", "version": version}
|
|
call(
|
|
["write", "-format=json", DEST_DATA, "-"],
|
|
payload={"options": {"cas": version}, "data": {FIELD: token}},
|
|
)
|
|
after = call(["read", "-format=json", DEST_DATA])["data"]
|
|
if (after.get("data") or {}).get(FIELD) != token:
|
|
raise RuntimeError("readback_mismatch")
|
|
return {
|
|
"action": "created" if version == 0 else "reseeded",
|
|
"version": after["metadata"]["version"],
|
|
}
|
|
|
|
|
|
def main() -> int:
|
|
_evidence("started")
|
|
if Path.home().parent.name != ".warden-attended-login":
|
|
return _fail("attended_warden_envelope_required")
|
|
if os.environ.get("BAO_TOKEN") or os.environ.get("VAULT_TOKEN"):
|
|
return _fail("token_env_must_be_unset")
|
|
try:
|
|
identity = bao(["token", "lookup", "-format=json"])["data"]
|
|
except Exception:
|
|
return _fail("token_lookup_failed")
|
|
policies = identity.get("policies") or []
|
|
if "platform-admin" not in policies or "root" in policies:
|
|
return _fail("attended_platform_admin_required")
|
|
|
|
try:
|
|
raw = bao(["read", "-format=json", REGISTRY])["data"]
|
|
registry_version = raw["metadata"]["version"]
|
|
rows = json.loads(raw["data"]["senders.json"])
|
|
except Exception:
|
|
return _fail("registry_read_failed")
|
|
try:
|
|
token = pick_token(rows)
|
|
except ValueError as exc:
|
|
return _fail(str(exc), {"registry_version": registry_version})
|
|
_evidence("registry_read", {"registry_version": registry_version})
|
|
|
|
try:
|
|
result = seed(token)
|
|
except Exception as exc:
|
|
return _fail("seed_failed", {"error_class": exc.__class__.__name__})
|
|
_evidence(
|
|
"done",
|
|
{
|
|
"registry_version": registry_version,
|
|
"destination_version": result["version"],
|
|
"action": result["action"],
|
|
"field": FIELD,
|
|
},
|
|
)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
raise SystemExit(main())
|
|
except SystemExit:
|
|
raise
|
|
except Exception:
|
|
_fail("contained_operation_failed")
|
|
raise SystemExit(1)
|