Establish scoped KeyCape factor custody and verified automatic renewal
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
parent
b75729b799
commit
2e2c31d237
22 changed files with 1169 additions and 1 deletions
39
scripts/keycape_factor_acceptance.py
Normal file
39
scripts/keycape_factor_acceptance.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
"""Run native delivery/scope/rotation acceptance; no attended admin or secret output."""
|
||||
import copy,json,subprocess,time,uuid
|
||||
from pathlib import Path
|
||||
from keycape_factor_activate import CLUSTER,kubectl
|
||||
ROOT=Path(__file__).resolve().parents[1]
|
||||
def run():
|
||||
if kubectl("get","ns","kube-system","-o","json")["metadata"]["uid"]!=CLUSTER:raise ValueError()
|
||||
cron=kubectl("-n","sso","get","cronjob","keycape-factor-renewer","-o","json")
|
||||
spec=copy.deepcopy(cron["spec"]["jobTemplate"]["spec"])
|
||||
spec.update(activeDeadlineSeconds=300,backoffLimit=0)
|
||||
p=spec["template"]["spec"];p["serviceAccountName"]="keycape-factor-eso"
|
||||
p["containers"][0]["command"]=["python3","-c",(ROOT/"scripts/keycape_factor_delivery_probe.py").read_text()]
|
||||
p["volumes"].append({"name":"factor","secret":{"secretName":"keycape-factor-read","defaultMode":288}})
|
||||
p["containers"][0]["volumeMounts"].append({"name":"factor","mountPath":"/factor","readOnly":True})
|
||||
suffix=uuid.uuid4().hex[:8];name="keycape-factor-proof-"+suffix
|
||||
kubectl("create","-f","-","-o","json",payload={"apiVersion":"batch/v1","kind":"Job","metadata":{"name":name,"namespace":"sso"},"spec":spec})
|
||||
deadline=time.monotonic()+310;rotating=False
|
||||
while time.monotonic()<deadline:
|
||||
r=subprocess.run(["kubectl","-n","sso","logs","job/"+name],capture_output=True,text=True,timeout=15)
|
||||
results=[]
|
||||
if r.returncode==0:
|
||||
for line in r.stdout.splitlines():
|
||||
try:results.append(json.loads(line))
|
||||
except ValueError:pass
|
||||
if results and not rotating:
|
||||
if results[0].get("phase")!="awaiting_rotation":raise ValueError()
|
||||
renewal={"apiVersion":"batch/v1","kind":"Job","metadata":{"name":"keycape-factor-rotate-"+suffix,"namespace":"sso"},"spec":cron["spec"]["jobTemplate"]["spec"]}
|
||||
kubectl("create","-f","-","-o","json",payload=renewal);rotating=True
|
||||
print(json.dumps({"phase":"waiting_for_mounted_rotation","job":name}),flush=True)
|
||||
if results and "phase" not in results[-1]:
|
||||
result={k:v for k,v in results[-1].items() if isinstance(v,bool)}
|
||||
result["job"]=name
|
||||
return result
|
||||
time.sleep(5)
|
||||
raise TimeoutError()
|
||||
if __name__=="__main__":
|
||||
try:result=run()
|
||||
except Exception:result={"success":False,"failure":"native acceptance failed or timed out"}
|
||||
print(json.dumps(result),flush=True);raise SystemExit(0 if result.get("success") else 1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue