#!/usr/bin/env python3 """Prove each new publisher can abort its own upload and cannot write elsewhere. No completed object is left behind. The receipt contains status codes only. """ from __future__ import annotations import json import subprocess from pathlib import Path import boto3 from botocore.exceptions import ClientError RECEIPT = Path("/home/worsch/.local/state/railiance/receipts/backup-publisher-prefix-proof.json") BUCKET = "railiance-platform-pg-backup" PROFILES = { "coulomb-social": "platform-pg/application-archives/coulomb-social/.policy-probe", "email-connect": "platform-pg/application-archives/email-connect/.policy-probe", } FOREIGN = "platform-pg/apps-pg/.policy-probe" def kv(path): proc = subprocess.run(["bao", "kv", "get", "-format=json", path], capture_output=True) if proc.returncode: raise SystemExit(81) return json.loads(proc.stdout)["data"]["data"] def client(values): return boto3.client( "s3", region_name="nl-ams", endpoint_url="https://s3.nl-ams.scw.cloud", aws_access_key_id=values["AWS_ACCESS_KEY_ID"], aws_secret_access_key=values["AWS_SECRET_ACCESS_KEY"], ) def code(exc): return exc.response.get("Error", {}).get("Code", "error") def attempt(action): try: action() return "ok" except ClientError as exc: return code(exc) def open_or_deny(remote, key): try: upload = remote.create_multipart_upload(Bucket=BUCKET, Key=key) except ClientError as exc: return code(exc) remote.abort_multipart_upload(Bucket=BUCKET, Key=key, UploadId=upload["UploadId"]) return "opened_then_aborted" def main(): rows = [] for name, own_key in PROFILES.items(): remote = client(kv(f"platform/workloads/{name}/backup-primary")) own = "error" try: upload = remote.create_multipart_upload(Bucket=BUCKET, Key=own_key) remote.abort_multipart_upload( Bucket=BUCKET, Key=own_key, UploadId=upload["UploadId"] ) own = "aborted" except ClientError as exc: own = code(exc) sibling_key = next(key for other, key in PROFILES.items() if other != name) foreign = open_or_deny(remote, FOREIGN) sibling = open_or_deny(remote, sibling_key) delete = attempt(lambda key=own_key: remote.delete_object(Bucket=BUCKET, Key=key)) rows.append({ "application": name, "own_multipart": own, "foreign_multipart": foreign, "sibling_multipart": sibling, "delete_object": delete, }) RECEIPT.parent.mkdir(mode=0o700, exist_ok=True) RECEIPT.write_text(json.dumps({"proofs": rows}, indent=2) + "\n") RECEIPT.chmod(0o600) if __name__ == "__main__": try: main() except SystemExit: raise except Exception: raise SystemExit(82) from None