fix: reject broken runtime launchers and preserve failed proof evidence
Some checks failed
Governed runtime contract / contract (push) Failing after 16s
Some checks failed
Governed runtime contract / contract (push) Failing after 16s
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e387-534d-70e3-ad53-4ea05676db8c
This commit is contained in:
parent
4e666d6fa3
commit
43e621439a
26 changed files with 1367 additions and 3 deletions
140
scripts/attended-metered-proof.py
Normal file
140
scripts/attended-metered-proof.py
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
"""Contained workstation login envelope for the exact Railiance native proof.
|
||||
|
||||
Run the reader through Warden. Both attended sessions self-revoke. Values stay
|
||||
in private tmpfs / process memory and encrypted SSH stdin; output is suppressed.
|
||||
"""
|
||||
import importlib.util
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from urllib.request import Request, build_opener, ProxyHandler, HTTPRedirectHandler
|
||||
|
||||
ROOT = Path("/home/worsch/rein-aharness")
|
||||
PLATFORM = Path("/home/worsch/railiance-platform")
|
||||
PYTHON = "/home/worsch/secrets-engine/.venv/bin/python"
|
||||
REMOTE = "/home/tegwick/hfact/native-metered-20260927"
|
||||
KUBE = ["kubectl", "--kubeconfig", "/home/worsch/.kube/config-railiance01"]
|
||||
RECEIPT = ROOT / "docs/evidence/2026-09-27-metered-attended-execution.json"
|
||||
RESUME = len(sys.argv) > 1 and sys.argv[1] in ("reader-resume", "admin-resume")
|
||||
if RESUME:
|
||||
RECEIPT = ROOT / "docs/evidence/2026-09-27-metered-attended-resume.json"
|
||||
spec = importlib.util.spec_from_file_location("native", ROOT / "scripts/metered-native-owner.py")
|
||||
native = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(native)
|
||||
require, private, run, write_new = native.require, native.private, native.run, native.write_new
|
||||
|
||||
|
||||
class NoRedirect(HTTPRedirectHandler):
|
||||
def redirect_request(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
|
||||
def receipt(phase, **fields):
|
||||
data = json.loads(RECEIPT.read_text()) if RECEIPT.exists() else {}
|
||||
data.update(phase=phase, **fields)
|
||||
RECEIPT.write_text(json.dumps(data, indent=2) + "\n")
|
||||
|
||||
|
||||
def helper():
|
||||
require(Path.home().parent.name == ".warden-attended-login" and not os.getenv("BAO_TOKEN") and not os.getenv("VAULT_TOKEN"), "attended_containment_required")
|
||||
path = Path.home() / ".vault-token"
|
||||
private(path)
|
||||
return path
|
||||
|
||||
|
||||
def reader():
|
||||
require(not RECEIPT.exists(), "prior_session_requires_reconciliation")
|
||||
receipt("reader_preflight", status="in_progress", credential_values_emitted=False)
|
||||
token_file = helper()
|
||||
spec = importlib.util.spec_from_file_location("reader", PLATFORM / "scripts/approval-client-reader-preflight.py")
|
||||
pre = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(pre)
|
||||
pre.validate_identity(pre.bao("token", "lookup", "-format=json")["data"])
|
||||
for path, expected in pre.EXPECTED.items():
|
||||
require(sorted(pre.bao("token", "capabilities", "-format=json", path)) == expected, "reader_scope_failed")
|
||||
runtime = Path("/run/user") / str(os.getuid())
|
||||
private(runtime, True)
|
||||
require(run(["findmnt", "-n", "-o", "FSTYPE", "-T", str(runtime)]) == "tmpfs", "private_tmpfs_required")
|
||||
with tempfile.TemporaryDirectory(prefix="metered-attended-", dir=runtime) as name:
|
||||
directory = Path(name)
|
||||
req = Request("http://127.0.0.1:18200/v1/platform/data/workloads/secrets-engine/approval-client?version=1", headers={"X-Vault-Token": token_file.read_text().strip()})
|
||||
with build_opener(ProxyHandler({}), NoRedirect()).open(req, timeout=20) as response:
|
||||
raw = response.read(65537)
|
||||
require(len(raw) <= 65536, "credential_response_bound")
|
||||
data = json.loads(raw)
|
||||
require(data["data"]["metadata"]["version"] == 1, "custody_version_drift")
|
||||
value = data["data"]["data"]["CLIENT_SECRET"]
|
||||
require(isinstance(value, str) and 0 < len(value) <= 16384, "credential_invalid")
|
||||
write_new(directory / "client-secret", value)
|
||||
del value, raw, data, req
|
||||
receipt("attended_admin_login", reader_scope_verified=True, kv_version=1)
|
||||
result = subprocess.run(["python3", str(PLATFORM / "scripts/openbao-attended-exec.py"), "--", PYTHON, "-B", str(Path(__file__).resolve()), "admin-resume" if RESUME else "admin", str(directory), str(token_file)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=780)
|
||||
require(result.returncode == 0, "attended_execution_failed")
|
||||
receipt("attended_sessions_completed", status="completed", local_private_runtime_removed=True)
|
||||
|
||||
|
||||
def admin(directory, negative):
|
||||
admin_file = helper()
|
||||
private(directory, True)
|
||||
private(directory / "client-secret")
|
||||
private(negative)
|
||||
forwards = []
|
||||
payload = {}
|
||||
try:
|
||||
for namespace, label, image, port in (("approval-engine", "approval-engine", "251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49", 19281), ("flex-auth", "flex-auth-secrets-engine", "05a03a8790c2210c48ea92391441c77ddf640d0cd32f5ec09838f5393171fcbd", 19282)):
|
||||
pods = json.loads(run(KUBE + ["-n", namespace, "get", "pods", "-l", "app.kubernetes.io/name=" + label, "-o", "json"]))["items"]
|
||||
require(len(pods) == 1, "single_owner_pod_required")
|
||||
pod = pods[0]
|
||||
require(any(c.get("ready") and c.get("imageID", "").endswith("@sha256:" + image) for c in pod.get("status", {}).get("containerStatuses", [])), "native_image_pin_drift")
|
||||
forwards.append(subprocess.Popen(KUBE + ["-n", namespace, "port-forward", "pod/" + pod["metadata"]["name"], str(port) + ":8080", "--address=127.0.0.1"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL))
|
||||
for port in (19281, 19282):
|
||||
for _ in range(50):
|
||||
require(all(p.poll() is None for p in forwards), "native_forward_failed")
|
||||
try:
|
||||
with socket.create_connection(("127.0.0.1", port), timeout=.2):
|
||||
break
|
||||
except OSError:
|
||||
time.sleep(.1)
|
||||
else:
|
||||
raise ValueError("native_forward_not_ready")
|
||||
bridge = subprocess.Popen(["ssh", "-N", "-o", "ExitOnForwardFailure=yes", "-R", "127.0.0.1:28200:127.0.0.1:18200", "-R", "127.0.0.1:28281:127.0.0.1:19281", "-R", "127.0.0.1:28282:127.0.0.1:19282", "railiance01"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
forwards.append(bridge)
|
||||
time.sleep(1)
|
||||
require(bridge.poll() is None, "ssh_bridge_failed")
|
||||
payload = dict(client_secret=(directory / "client-secret").read_text(), negative_token=negative.read_text().strip(), backend_token=admin_file.read_text().strip(), pdp_token=run(KUBE + ["-n", "secrets-engine", "create", "token", "secrets-engine", "--audience=flex-auth", "--duration=10m"]))
|
||||
receipt("remote_native_execution_started", named_owner_images_verified=True)
|
||||
result = subprocess.run(["ssh", "railiance01", "env", "PATH=/home/tegwick/.local/bin:/usr/local/bin:/usr/bin:/bin", "PYTHONPATH=/home/tegwick/secrets-engine/src", "/home/tegwick/secrets-engine/.venv/bin/python", "-B", REMOTE + "/metered-native-owner.py", "resume" if RESUME else "execute", REMOTE], input=json.dumps(payload), text=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=650)
|
||||
payload.clear()
|
||||
receipt("remote_native_execution_returned", remote_exit_code=result.returncode)
|
||||
require(result.returncode == 0, "remote_native_execution_failed")
|
||||
finally:
|
||||
payload.clear()
|
||||
for process in reversed(forwards):
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait()
|
||||
receipt("native_transport_closed", owner_forwards_closed=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
if sys.argv[1:] in (["reader"], ["reader-resume"]):
|
||||
reader()
|
||||
elif len(sys.argv) == 4 and sys.argv[1] in ("admin", "admin-resume"):
|
||||
admin(Path(sys.argv[2]), Path(sys.argv[3]))
|
||||
else:
|
||||
raise ValueError("unsupported_mode")
|
||||
except Exception as error:
|
||||
fields = {"status": "failed", "failure_type": type(error).__name__}
|
||||
if type(error) is ValueError and str(error).replace("_", "").isalnum():
|
||||
fields["failure_code"] = str(error)
|
||||
receipt("failed", **fields)
|
||||
raise SystemExit(1) from None
|
||||
Loading…
Add table
Add a link
Reference in a new issue