coulomb-social/scripts/keycape-client-repair.py

67 lines
2.4 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Restore the historical public client through NetKingdom's guarded lane.
Inspection is read-only. Apply requires exact founder approval and a fresh
UID/resource-version receipt. Secret values stay inside the owner helper.
"""
import importlib.util
import json
import os
import shlex
import subprocess
from pathlib import Path
from types import SimpleNamespace
def load(name, path):
spec = importlib.util.spec_from_file_location(name, path)
result = importlib.util.module_from_spec(spec)
spec.loader.exec_module(result)
return result
def configure(owner_root):
rollout = load("keycape_guarded_rollout", owner_root / "portal-client-rollout.py")
historical = load("coulomb_registration", owner_root / "register-coulomb-social.py")
original = rollout.replacement
rollout.portal = SimpleNamespace(CLIENT_ID=historical.CLIENT_ID, CLIENT=historical.CLIENT)
def replacement(secret):
_, config, _ = rollout.pin.issuer_document(secret)
for client in config.get("clients", []):
if client.get("clientId") == historical.CLIENT_ID:
rollout.require(client == historical.CLIENT, "existing_registration_differs")
return original(secret)
rollout.replacement = replacement
def kubectl(arguments, payload=None):
# Estate production changes execute on the node, never through a
# workstation context. Capture both streams: kubectl errors may include
# a Secret; only the owner's fixed reason code may leave this function.
result = subprocess.run(
["ssh", "railiance01", shlex.join([
"kubectl", "--request-timeout=20s", *arguments,
])],
input=None if payload is None else json.dumps(payload),
text=True, capture_output=True, timeout=40,
)
rollout.require(result.returncode == 0, "kubernetes_operation_failed")
return json.loads(result.stdout)
rollout.kubectl = kubectl
return rollout
if __name__ == "__main__":
try:
owner_root = Path(os.environ.get(
"NET_KINGDOM_KEYCAPE_DIR",
str(Path.home() / "net-kingdom/sso-mfa/k8s/keycape"),
))
helper = configure(owner_root)
except Exception:
print('{"status":"failed","reason":"owner_helper_unavailable"}')
raise SystemExit(1)
raise SystemExit(helper.main())