#!/usr/bin/python3 """Opt-in real Bash installer acceptance in an owned image, without host services.""" import argparse import hashlib import json import os from pathlib import Path import shutil import subprocess import tempfile from verify_prepared_release import WORKSPACE, execute def verify(args): result = { "status": "running", "checks": [], "transport": "local signed assets; actual generated Bash entry and Rust bootstrap", "online_install_and_update": "not_run", "entry_sha256": hashlib.sha256(args.entry.read_bytes()).hexdigest(), } def passed(name): result["checks"].append(name) args.report.write_text(json.dumps(result, indent=2) + "\n") print(f"PASS {name}", flush=True) try: with tempfile.TemporaryDirectory(prefix="dever-install-entry-", dir=args.scratch_parent) as directory: scratch = Path(directory) release = scratch / "release" release.mkdir() for name in ("manifest.json", "manifest.sig"): shutil.copyfile(args.release / name, release / name) manifest = json.loads((release / "manifest.json").read_bytes()) if manifest["platform"] != "linux-x86_64": raise ValueError("this acceptance fixture requires a Linux x86_64 release") result["payload_version"] = manifest["version"] result["manifest_sha256"] = hashlib.sha256((release / "manifest.json").read_bytes()).hexdigest() key = scratch / "release.pub" shutil.copyfile(WORKSPACE / "skills/assets/release.pub", key) extraction = scratch / "extract.json" extraction.write_text(json.dumps({ "release": str(release), "archive": str(args.assets / "dever-linux-x86_64.tar.zst"), "trusted_key": str(key), })) execute([args.extractor, "--dever-extract", extraction]) passed("prepared_release_authenticated_by_existing_rust_extractor") # A copied standalone entry has no adjacent skill or source checkout. entry = scratch / "install" shutil.copyfile(args.entry, entry) image = scratch / "image" image.mkdir() arguments = ["--release", str(release), "--system-root", str(image), "--no-start"] execute(["/bin/bash", entry, *arguments]) machine = image / "opt/dever" launcher = machine / "bin/dever" installed = machine / "versions" / manifest["version"] if execute([launcher, "version"]) != manifest["version"]: raise RuntimeError("installed launcher selected the wrong version") skill = installed / "skills/dever-language" if execute([launcher, "skill", "path"]) != str(skill): raise RuntimeError("installed skill does not match the selected core") if (image / "usr/local/bin/dever").readlink() != Path("/opt/dever/bin/dever"): raise RuntimeError("public launcher symlink was not installed") passed("standalone_bash_first_install_and_matching_skill") tracked = [launcher, machine / "bin/deverd", installed / "manifest.json", installed / "dever-core"] baseline = {str(path): hashlib.sha256(path.read_bytes()).hexdigest() for path in tracked} def unchanged(): current = {str(path): hashlib.sha256(path.read_bytes()).hexdigest() for path in tracked} if current != baseline: raise RuntimeError("existing installed state changed") if list(image.glob(".dever-install-*")): raise RuntimeError("installer left private staging behind") repeated = subprocess.run( ["/bin/bash", "-s", "--", *arguments], input=entry.read_bytes(), cwd=scratch, env={}, capture_output=True, timeout=180, ) if repeated.returncode: raise RuntimeError(repeated.stderr.decode(errors="replace")) unchanged() # Bootstrap records another activation even for the same version. # Compare the selected version here, then freeze the journal for failure checks. if execute([launcher, "version"]) != manifest["version"]: raise RuntimeError("reinstall changed the selected version") active = machine / "state/active-version" tracked.append(active) baseline[str(active)] = hashlib.sha256(active.read_bytes()).hexdigest() passed("pipe_reinstall_preserves_installed_state_and_cleans_staging") (release / "manifest.sig").write_text("00" * 64 + "\n") rejected = subprocess.run( ["/bin/bash", entry, *arguments], cwd=scratch, env={}, capture_output=True, timeout=30, ) if rejected.returncode == 0 or "签名校验失败" not in rejected.stderr.decode(errors="replace"): raise RuntimeError("corrupt signature did not fail at authentication") unchanged() if execute([launcher, "version"]) != manifest["version"]: raise RuntimeError("failed install changed the selected version") passed("corrupt_signature_rejected_existing_install_preserved") result["status"] = "passed" except BaseException as error: result["status"] = "failed" result["error"] = str(error) raise finally: args.report.write_text(json.dumps(result, indent=2) + "\n") def main(): parser = argparse.ArgumentParser(description=__doc__) for name in ("release", "assets", "extractor", "scratch-parent", "report"): parser.add_argument(f"--{name}", required=True, type=Path) parser.add_argument("--entry", type=Path, default=WORKSPACE / "install") args = parser.parse_args() if os.geteuid() != 0: parser.error("requires root for its own image; never installs host services") for name, value in vars(args).items(): setattr(args, name, value.absolute()) args.report.parent.mkdir(parents=True, exist_ok=True) verify(args) if __name__ == "__main__": main()