#!/usr/bin/env python3 """Install one reviewed CLI bundle offline into a new owner-controlled prefix.""" import argparse import hashlib import json from pathlib import Path import platform import shutil import subprocess import sys def digest(path): return hashlib.sha256(path.read_bytes()).hexdigest() def install(bundle, prefix, expected_manifest, python, uv): manifest_path = bundle / "manifest.json" if digest(manifest_path) != expected_manifest: raise ValueError("bundle manifest differs from reviewed digest") manifest = json.loads(manifest_path.read_text()) if manifest["schema"] != "secrets-engine.cli-bundle.v1": raise ValueError("unsupported bundle") if manifest['system'] != platform.system() or manifest['machine'] != platform.machine(): raise ValueError("bundle platform differs from installer host") expected_files = set(manifest['artifacts']) | {'manifest.json'} actual_files = {str(p.relative_to(bundle)) for p in bundle.rglob('*') if p.is_file()} if actual_files != expected_files: raise ValueError("bundle file set differs") for name, expected in manifest['artifacts'].items(): relative = Path(name) if relative.is_absolute() or '..' in relative.parts: raise ValueError("invalid artifact path") artifact = bundle / relative if any(parent.is_symlink() for parent in (artifact,*artifact.parents)) or digest(artifact) != expected: raise ValueError("bundle artifact missing or changed") # Reserve once; never replace an installed prefix or follow an existing link. prefix.mkdir(mode=0o700, parents=False, exist_ok=False) try: subprocess.run([uv,'--no-config','venv','--python',python,'--no-python-downloads',str(prefix/'venv')],check=True) subprocess.run([uv,'--no-config','pip','install','--python',str(prefix/'venv/bin/python'), '--no-index','--find-links',str(bundle/'wheels'),str(bundle/manifest['wheel'])],check=True) (prefix/'libexec').mkdir(mode=0o700) helper=prefix/'libexec/secrets-engine-pdp-verify' shutil.copyfile(bundle/'bin/secrets-engine-pdp-verify',helper);helper.chmod(0o700) (prefix/'bin').mkdir(mode=0o700) launcher=prefix/'bin/secrets-engine' # An absolute venv interpreter fixes the installed dependency environment. launcher.write_text('#!'+str(prefix/'venv/bin/python')+'\n'+(bundle/'release_cli.py').read_text()) launcher.chmod(0o700) receipt={"schema":"secrets-engine.cli-install.v1","manifest_sha256":expected_manifest, "helper_sha256":digest(helper),"launcher_sha256":digest(launcher),"prefix":str(prefix), "admission":"artifact integrity only; trust and keys not admitted"} (prefix/'install-receipt.json').write_text(json.dumps(receipt,sort_keys=True,indent=2)+'\n') return receipt except BaseException: # Preserve a failed prefix as evidence; never retry into a partial install. (prefix/'INSTALL-FAILED').write_text('Incomplete installation; use a new prefix.\n') raise def main(): parser=argparse.ArgumentParser(description=__doc__) parser.add_argument('--bundle',type=Path,default=Path(__file__).resolve().parent) parser.add_argument('--prefix',type=Path,required=True) parser.add_argument('--manifest-sha256',required=True) parser.add_argument('--python',default=sys.executable) parser.add_argument('--uv',default='uv') args=parser.parse_args() try: if not args.prefix.is_absolute() or args.prefix.parent.is_symlink(): raise ValueError('prefix must be absolute with an admitted parent') receipt=install(args.bundle.resolve(),args.prefix,args.manifest_sha256,args.python,args.uv) print(json.dumps(receipt,sort_keys=True)) except (OSError,ValueError,KeyError,subprocess.SubprocessError) as exc: print('bundle install refused: '+str(exc),file=sys.stderr) return 1 return 0 if __name__=='__main__': raise SystemExit(main())