Make remote harvest zipapp stdlib-only

Lazy-load manifest, explain, and validation dependencies so the remote
harvest zipapp does not require jsonschema, PyYAML, Paramiko, or other
site-packages on the target host.

Run the remote zipapp with Python isolated mode and site-packages
disabled, while preserving existing CLI monkeypatch hooks.
This commit is contained in:
Miguel Jacq 2026-08-03 15:58:14 +10:00
parent 70c90c62ae
commit 5932d22801
Signed by: mig5
GPG key ID: 03906B4110AAD3B8
3 changed files with 94 additions and 3 deletions

View file

@ -313,6 +313,9 @@ def test_remote_harvest_happy_path(tmp_path: Path, monkeypatch):
assert promote_argv.count("enroll.pyz") >= 2
assert "/tmp/enroll-root-123/enroll.pyz" in harvest_cmd
assert "/tmp/enroll-remote-123/enroll.pyz" not in harvest_cmd
harvest_argv = shlex.split(harvest_cmd)
pyz_i = harvest_argv.index("/tmp/enroll-root-123/enroll.pyz")
assert harvest_argv[pyz_i - 2 : pyz_i] == ["-I", "-S"]
assert not any(_is_pyz_verify_cmd(c) for c, _pty in calls)
# The trusted digest must be obtained while the archive is still private,
@ -1251,6 +1254,74 @@ def test_remote_verify_pyz_sha256_rejects_nonzero_rc():
)
def test_build_enroll_pyz_harvest_starts_without_site_packages(tmp_path: Path):
"""The remote payload must not depend on packages installed on the target.
``-S`` disables site-packages, reproducing a target that has Python but no
jsonschema/PyYAML. ``-I`` also ignores PYTHON* environment variables and
the current directory. The old eager CLI imports failed here before
argparse could dispatch to ``harvest``.
"""
import subprocess
import sys
import enroll.remote as r
pyz, _sha = r._build_enroll_pyz(tmp_path)
proc = subprocess.run(
[sys.executable, "-I", "-S", str(pyz), "harvest", "--help"],
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=15,
)
assert proc.returncode == 0, proc.stderr
assert "usage: enroll harvest" in proc.stdout
assert "ModuleNotFoundError" not in proc.stderr
assert "jsonschema" not in proc.stderr
assert "yaml" not in proc.stderr.lower()
def test_build_enroll_pyz_runs_harvest_without_site_packages(tmp_path: Path):
"""Exercise command dispatch and the actual harvest implementation under -S."""
import subprocess
import sys
import enroll.remote as r
build_dir = tmp_path / "build"
build_dir.mkdir()
pyz, _sha = r._build_enroll_pyz(build_dir)
out_dir = tmp_path / "bundle"
proc = subprocess.run(
[
sys.executable,
"-I",
"-S",
str(pyz),
"harvest",
"--out",
str(out_dir),
"--exclude-path",
"/**",
"--assume-safe-path",
],
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
timeout=60,
)
assert proc.returncode == 0, proc.stderr
assert (out_dir / "state.json").is_file()
assert "ModuleNotFoundError" not in proc.stderr
assert "jsonschema" not in proc.stderr
assert "yaml" not in proc.stderr.lower()
def test_build_enroll_pyz_excludes_tests_and_caches_and_returns_sha(tmp_path: Path):
import zipfile