Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a1abf1-7e95-7141-87c9-ee78332bf790
120 lines
6.2 KiB
Python
120 lines
6.2 KiB
Python
"""Select a successful attended point for the already-proved isolated restore."""
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
import vergabe_pilot_point as point
|
|
import vergabe_pilot_restore as restore
|
|
import vergabe_pilot_restore_remote as transport
|
|
from vergabe_pilot_recovery_store import require
|
|
|
|
|
|
def remote_command(sources, run, nonce, cleanup=False):
|
|
point.run_time(run)
|
|
require(re.fullmatch(r"[0-9a-f]{12}", nonce), "invalid_restore_nonce")
|
|
bootstrap = "import sys,types;"
|
|
for name in ("vergabe_pilot_recovery_store", "vergabe_pilot_export", "vergabe_pilot_point", "vergabe_pilot_restore"):
|
|
bootstrap += ("m=types.ModuleType(" + repr(name) + ");sys.modules[m.__name__]=m;"
|
|
"exec(compile(" + repr(sources[name]) + "," + repr(name + ".py") + ",'exec'),m.__dict__);")
|
|
selection = '''
|
|
import json,os,re,signal
|
|
from pathlib import Path
|
|
import vergabe_pilot_export as export
|
|
import vergabe_pilot_point as point
|
|
import vergabe_pilot_restore as restore
|
|
from vergabe_pilot_recovery_store import Refused,require
|
|
try:
|
|
run,nonce,mode=sys.argv[1:]
|
|
point.run_time(run)
|
|
require(os.geteuid()==0 and os.environ.get('SUDO_USER')=='tegwick','founder_node_sudo_required')
|
|
export.RUN_ID=run;export.NAME='vergabe-pilot-'+run
|
|
if mode!='cleanup':
|
|
stage=Path('/home/tegwick')/('vergabe-pilot-restore-'+nonce)
|
|
info=stage.lstat()
|
|
owner=int(os.environ['SUDO_UID'])
|
|
require(stage.is_dir() and not stage.is_symlink() and info.st_uid==owner and not info.st_mode&0o077,'private_founder_stage_required')
|
|
def read(name):
|
|
path=stage/name
|
|
info=export.regular(path,owner)
|
|
require(0<info.st_size<=16384,'restore_metadata_bound')
|
|
return json.loads(path.read_text())
|
|
origin=read('origin.json');provider=read('provider.json')
|
|
require(origin['run_id']==provider['run_id']==run,'restore_run_changed')
|
|
point.select(run,origin['files'])
|
|
require(all(isinstance(provider.get(k),str) and re.fullmatch('[0-9a-f]{64}',provider[k]) for k in ('ciphertext_sha256','plaintext_packet_sha256')),'restore_hash_shape')
|
|
restore.CIPHER=provider['ciphertext_sha256'];restore.PLAIN=provider['plaintext_packet_sha256']
|
|
def interrupted(signum,frame):raise Refused('restore_interrupted')
|
|
signal.signal(signal.SIGHUP,interrupted);signal.signal(signal.SIGTERM,interrupted)
|
|
sys.argv=['restore','--nonce',nonce,*(['--cleanup'] if mode=='cleanup' else [])]
|
|
code=restore.main()
|
|
except BaseException as error:
|
|
print(json.dumps({'status':'operating_restore_failed','failure':str(error) if isinstance(error,Refused) else 'operating_restore_error','details_suppressed':True}))
|
|
code=1
|
|
raise SystemExit(code)
|
|
'''
|
|
bootstrap += "exec(" + repr(selection) + ")"
|
|
command = shlex.join(["sudo", "/usr/bin/env", "KUBECONFIG=/etc/rancher/k3s/k3s.yaml", "/usr/bin/python3",
|
|
"-c", bootstrap, run, nonce, "cleanup" if cleanup else "restore"])
|
|
require(len(command.encode()) < 120000, "restore_transport_size_bound")
|
|
return ["ssh", "-t", "railiance01", command]
|
|
|
|
|
|
def selected_receipt(directory, run, sealed):
|
|
paths = list(directory.glob("provider-receipt-*.json"))
|
|
require(len(paths) <= 100, "provider_receipt_count_bound")
|
|
accepted = []
|
|
for path in paths:
|
|
body = point.read_private(path)
|
|
if point.successful_provider(body, run, sealed):
|
|
accepted.append((path, body))
|
|
require(accepted, "successful_provider_receipt_required")
|
|
path, body = max(accepted, key=lambda item: item[0].stat().st_mtime_ns)
|
|
restore.CIPHER = body["ciphertext_sha256"]
|
|
restore.PLAIN = body["plaintext_packet_sha256"]
|
|
# Full recovered ZIP/ciphertext/file verification, using the selected run.
|
|
kit, recovered, files = transport.verify_input(path)
|
|
return kit, recovered, files, path
|
|
|
|
|
|
def execute(directory, run, sealed, sources):
|
|
kit, recovered, files, receipt = selected_receipt(directory, run, sealed)
|
|
nonce = uuid.uuid4().hex[:12]
|
|
command = remote_command(sources, run, nonce)
|
|
require(subprocess.run(transport.stage_command(nonce, "create"), check=False).returncode == 0,
|
|
"restore_stage_creation_failed")
|
|
print(json.dumps({"status": "restore_transport_started", "run_id": run, "nonce": nonce}), flush=True)
|
|
with tempfile.TemporaryDirectory(prefix="restore-transfer-", dir=kit) as temporary:
|
|
temporary = Path(temporary)
|
|
for name in restore.FILES[:4]:
|
|
shutil.copy2(recovered / name, temporary / name)
|
|
shutil.copy2(receipt, temporary / "provider.json")
|
|
(temporary / "origin.json").write_text(json.dumps({"run_id": run, "files": files}))
|
|
(temporary / "origin.json").chmod(0o600)
|
|
for name in restore.FILES:
|
|
copied = subprocess.run(["scp", "-p", str(temporary / name),
|
|
"railiance01:vergabe-pilot-restore-" + nonce + "/" + name],
|
|
capture_output=True, timeout=120, check=False)
|
|
require(copied.returncode == 0, "restore_private_transfer_failed")
|
|
result = subprocess.run(command, check=False)
|
|
removed = result.returncode == 0 and subprocess.run(transport.stage_command(nonce, "cleanup"), check=False).returncode == 0
|
|
body = {"schema": "railiance.vergabe-pilot-native-restore-transport.v1", "run_id": run,
|
|
"nonce": nonce, "worker_exit_code": result.returncode, "node_stage_removed": removed,
|
|
"status": "complete" if result.returncode == 0 and removed else "requires_review"}
|
|
with os.fdopen(os.open(kit / ("native-restore-transport-" + nonce + ".json"),
|
|
os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600), "w") as stream:
|
|
json.dump(body, stream, indent=2)
|
|
print(json.dumps(body, indent=2))
|
|
return 0 if body["status"] == "complete" else 1
|
|
|
|
|
|
def cleanup(sources, run, nonce):
|
|
result = subprocess.run(remote_command(sources, run, nonce, cleanup=True), check=False)
|
|
staged = subprocess.run(transport.stage_command(nonce, "cleanup"), check=False)
|
|
return 0 if result.returncode == staged.returncode == 0 else 1
|