#!/usr/bin/python3 """Opt-in root install 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 root 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()