Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 6m35s
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
116 lines
5.8 KiB
Python
116 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
|
"""One founder-attended SMTP proof using the existing telemetry credential projection."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PACKET = ROOT / "docs/release/backup-alert-email-2026-10-31"
|
|
NODE = r'''
|
|
import json,os,socket,subprocess,sys
|
|
p=json.load(sys.stdin);plan=p['plan'];job=p['job'];mode=p['mode']
|
|
def command(args,payload=None,allowed=(0,),timeout=30):
|
|
r=subprocess.run(args,input=payload,capture_output=True,timeout=timeout,env=dict(os.environ,KUBECONFIG='/etc/rancher/k3s/k3s.yaml'))
|
|
if r.returncode not in allowed:raise RuntimeError('bounded_command_failed')
|
|
return r.stdout
|
|
def doc(*args):return json.loads(command(['kubectl',*args,'-o','json']))
|
|
result={'schema':'coulomb.backup-email-proof-result.v1','event_id':plan['event_id'],'proposal_digest':p['digest'],'email_sent':False,'recipient_confirmed':False,'automatic_monitoring_active':False}
|
|
try:
|
|
assert mode in ('preflight','execute')
|
|
assert doc('get','namespace','kube-system')['metadata']['uid']==plan['cluster_uid']
|
|
assert doc('get','namespace',plan['namespace'])['metadata']['uid']==plan['namespace_uid']
|
|
policy=doc('get','networkpolicy','telemetry-smtp-egress','-n',plan['namespace'])
|
|
assert policy['spec']==plan['smtp_policy_spec']
|
|
resolved=socket.getaddrinfo('smtp.ionos.de',587,socket.AF_INET,socket.SOCK_STREAM)
|
|
addresses={r[4][0] for r in resolved}
|
|
assert addresses==set(plan['smtp_ipv4'])
|
|
es=doc('get','externalsecret',plan['secret_reference'],'-n',plan['namespace'])
|
|
assert es['spec']['target']['name']==plan['secret_reference']
|
|
conditions=es.get('status',{}).get('conditions',[])
|
|
assert any(c['type']=='Ready' and c['status']=='True' for c in conditions)
|
|
existing=command(['kubectl','get','job',plan['job_name'],'-n',plan['namespace'],'--ignore-not-found','-o','json'])
|
|
assert not existing.strip(), 'existing_job_requires_inspection_not_replay'
|
|
raw=json.dumps(job).encode()
|
|
command(['kubectl','create','--dry-run=server','-f','-','-o','json'],raw)
|
|
result.update(status='preflight_verified',namespace_identity_verified=True,smtp_projection_ready=True,smtp_egress_matches_current_dns=True,server_dry_run=True)
|
|
if mode=='execute':
|
|
# Never replace a Job or retry an uncertain create/send. Kubernetes refuses a duplicate name.
|
|
result['status']='creation_outcome_unconfirmed'
|
|
created=json.loads(command(['kubectl','create','-f','-','-o','json'],raw))
|
|
result['job_uid']=created['metadata']['uid'];result['job_name']=plan['job_name']
|
|
command(['kubectl','wait','--for=condition=complete','--timeout=130s','job/'+plan['job_name'],'-n',plan['namespace']],timeout=145)
|
|
current=doc('get','job',plan['job_name'],'-n',plan['namespace'])
|
|
assert current['metadata']['uid']==result['job_uid'] and current['status'].get('succeeded')==1
|
|
raw_log=command(['kubectl','logs','job/'+plan['job_name'],'-n',plan['namespace'],'--container=send'])
|
|
assert len(raw_log)<=8192
|
|
receipt=json.loads(raw_log)
|
|
assert receipt['status']=='smtp-accepted' and receipt['message_id']==plan['message_id']
|
|
result.update(status='smtp_provider_accepted',email_sent=True,provider_receipt=receipt)
|
|
except Exception as e:
|
|
result.update(
|
|
status='execution_requires_inspection' if mode=='execute' else 'preflight_refused',
|
|
failure_type=type(e).__name__,email_sent=None if mode=='execute' else False)
|
|
print(json.dumps(result));sys.exit(1)
|
|
print(json.dumps(result))
|
|
'''
|
|
|
|
|
|
def canonical(value):
|
|
return json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
|
|
|
|
|
|
def prepare(packet=PACKET):
|
|
plan = json.loads((packet / "plan.json").read_bytes())
|
|
job = json.loads((packet / "job.json").read_bytes())
|
|
digest = "sha256:" + hashlib.sha256(canonical({
|
|
"plan": plan, "job": job,
|
|
"launcher_sha256": hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
|
|
})).hexdigest()
|
|
return plan, job, digest
|
|
|
|
|
|
def main(argv=None):
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
action = parser.add_mutually_exclusive_group()
|
|
action.add_argument("--preflight", action="store_true")
|
|
action.add_argument("--execute", action="store_true")
|
|
parser.add_argument("--expect-digest")
|
|
args = parser.parse_args(argv)
|
|
plan, job, digest = prepare()
|
|
if args.expect_digest and args.expect_digest != digest:
|
|
raise SystemExit("Reviewed email proposal changed; no action")
|
|
if not (args.preflight or args.execute):
|
|
print(json.dumps({"status": "prepared", "proposal_digest": digest,
|
|
"recipient": plan["recipient"], "email_sent": False}))
|
|
return 0
|
|
if args.execute:
|
|
if not args.expect_digest or not sys.stdin.isatty():
|
|
raise SystemExit("Founder terminal and reviewed digest required")
|
|
print("Send one backup-alert verification email to " + plan["recipient"])
|
|
if input("Type SEND followed by the full digest: ").strip() != "SEND " + digest:
|
|
raise SystemExit("Not confirmed; no action")
|
|
payload = canonical({"plan": plan, "job": job, "digest": digest,
|
|
"mode": "execute" if args.execute else "preflight"})
|
|
try:
|
|
response = subprocess.run(
|
|
["ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=10", "railiance01",
|
|
"sudo -n python3 -c " + shlex.quote(NODE)],
|
|
input=payload, capture_output=True, timeout=240,
|
|
)
|
|
result = json.loads(response.stdout)
|
|
except (subprocess.TimeoutExpired, ValueError):
|
|
print(json.dumps({"status": "remote_outcome_unconfirmed", "job_name": plan["job_name"],
|
|
"proposal_digest": digest, "retry_automatically": False}))
|
|
return 1
|
|
print(json.dumps(result))
|
|
return int(response.returncode != 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|