railiance-platform/scripts/keycape_factor_renew.py
codex 2e2c31d237
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
KeyCape factor custody acceptance / acceptance (push) Successful in 7s
Establish scoped KeyCape factor custody and verified automatic renewal
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
2026-09-13 16:25:33 +02:00

74 lines
3.8 KiB
Python

"""Dedicated Kubernetes renewal worker. Only sanitized outcome metadata is emitted."""
import base64,json,sys,time,urllib.request,urllib.error,urllib.parse
from pathlib import Path
BAO="http://openbao.openbao.svc.cluster.local:8200/v1"
PI="http://privacyidea.mfa.svc.cluster.local:8080"
ISSUER="platform/data/workloads/net-kingdom/keycape-factor-issuer"
TARGET="platform/data/workloads/net-kingdom/keycape-factor-read"
USER="keycape-factor-reader"
PROVENANCE="RPF-WP-0040"
class Failure(Exception):pass
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self,*args,**kwargs):return None
def http(url,body=None,headers=None,method=None,form=False):
data=None
headers=dict(headers or {})
if body is not None:
data=(urllib.parse.urlencode(body) if form else json.dumps(body)).encode()
headers["Content-Type"]="application/x-www-form-urlencoded" if form else "application/json"
req=urllib.request.Request(url,data=data,headers=headers,method=method)
try:
with urllib.request.build_opener(NoRedirect()).open(req,timeout=15) as r:
raw=r.read(1048577)
if len(raw)>1048576:raise Failure()
return r.status,json.loads(raw) if raw else {}
except urllib.error.HTTPError as e:return e.code,{}
def success(code,data):
if code!=200 or not data.get("result",{}).get("status"):raise Failure()
return data["result"]["value"]
def run():
session=None;receipt={"success":False,"phase":"workload_login"}
try:
jwt=Path("/var/run/keycape-factor/token").read_text().strip()
code,body=http(BAO+"/auth/kubernetes/login",{"role":"keycape-factor-renewer","jwt":jwt})
if code!=200:raise Failure()
session=body["auth"]["client_token"];headers={"X-Vault-Token":session}
receipt["phase"]="issuer_custody"
code,body=http(BAO+"/"+ISSUER,headers=headers)
if code!=200:raise Failure()
issuer=body["data"]["data"]
if issuer.get("REQUEST")!=PROVENANCE or issuer.get("USERNAME")!=USER:raise Failure()
receipt["phase"]="provider_authentication"
value=success(*http(PI+"/auth",{"username":USER,"password":issuer["PASSWORD"]},form=True))
if value.get("role")!="admin" or value.get("username")!=USER:raise Failure()
token=value["token"];claims=json.loads(base64.urlsafe_b64decode(token.split('.')[1]+'==='));expiry=int(claims["exp"])
if not 300<expiry-time.time()<=7200:raise Failure()
receipt["phase"]="provider_scope"
provider_headers={"Authorization":token}
listing=success(*http(PI+"/token/?tokenrealm=coulomb&active=True&pagesize=1",headers=provider_headers))
if not isinstance(listing.get("tokens"),list) or not isinstance(listing.get("count"),int):raise Failure()
code,_=http(PI+"/policy/",headers=provider_headers)
if code not in (401,403):raise Failure()
receipt["phase"]="publish"
code,body=http(BAO+"/"+TARGET,headers=headers)
if code!=200 or body["data"]["data"].get("REQUEST")!=PROVENANCE:raise Failure()
version=body["data"]["metadata"]["version"]
code,_=http(BAO+"/"+TARGET,{"options":{"cas":version},"data":{"TOKEN":token,"EXPIRES_AT":expiry,"REQUEST":PROVENANCE}},headers=headers)
if code!=200:raise Failure()
code,body=http(BAO+"/"+TARGET,headers=headers)
if code!=200 or body["data"]["data"]["TOKEN"]!=token:raise Failure()
receipt.update(success=True,phase="complete",expires_at=expiry,kv_version=body["data"]["metadata"]["version"],cross_user_factor_visible=listing["count"]>0)
except Exception:pass
finally:
if session:
try:
code,_=http(BAO+"/auth/token/revoke-self",headers={"X-Vault-Token":session},method="POST")
receipt["session_revoked"]=code in (200,204)
except Exception:receipt["session_revoked"]=False
if not receipt["session_revoked"]:receipt["success"]=False;receipt["phase"]="session_cleanup"
return receipt
if __name__=="__main__":
receipt=run();print(json.dumps(receipt));raise SystemExit(0 if receipt["success"] else 1)