"""Subprocess gate fixtures; no real registry, runtime, cosign or release key.""" import os from pathlib import Path import subprocess import tempfile import unittest HELPER = Path(__file__).parents[1] / 'lib/verified-image-pull.sh' IMAGE = 'registry.invalid/app@sha256:' + 'a' * 64 class VerifiedImagePullTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.addCleanup(self.tmp.cleanup) self.root = Path(self.tmp.name) self.key = self.root / 'cosign.pub' self.key.write_text('subprocess fixture, not a public key') for name, body in { 'cosign': '#!/bin/sh\nprintf "%s\\n" "$@" > "$FIXTURE_VERIFY_LOG"\nexit "${FIXTURE_VERIFY_EXIT:-0}"\n', 'podman': '#!/bin/sh\nprintf "%s\\n" "$@" > "$FIXTURE_PULL_LOG"\n', }.items(): path = self.root / name path.write_text(body) path.chmod(0o700) self.env = dict(os.environ, PATH=str(self.root) + ':/usr/bin:/bin', ARCHIPELAGO_COSIGN_PUBKEY=str(self.key), DOCKER=str(self.root / 'podman'), FIXTURE_VERIFY_LOG=str(self.root / 'verify'), FIXTURE_PULL_LOG=str(self.root / 'pull')) def run_gate(self, image=IMAGE): return subprocess.run(['/bin/bash', '-c', 'source "$1"; verified_image_pull "$2"', 'fixture', str(HELPER), image], env=self.env, capture_output=True, text=True) def test_digest_verified_then_pulled_with_tls(self): self.assertEqual(self.run_gate().returncode, 0) self.assertEqual((self.root / 'pull').read_text().splitlines(), ['pull', '--tls-verify=true', IMAGE]) args = (self.root / 'verify').read_text().splitlines() self.assertEqual(args, ['verify', '--key', str(self.key), '--insecure-ignore-tlog=true', IMAGE]) def test_missing_key_or_verifier_prevents_runtime(self): self.key.unlink() self.assertNotEqual(self.run_gate().returncode, 0) self.assertFalse((self.root / 'pull').exists()) self.key.write_text('fixture') (self.root / 'cosign').unlink() self.env['PATH'] = str(self.root) self.assertNotEqual(self.run_gate().returncode, 0) self.assertFalse((self.root / 'pull').exists()) def test_verifier_rejection_prevents_runtime(self): self.env['FIXTURE_VERIFY_EXIT'] = '1' self.assertNotEqual(self.run_gate().returncode, 0) self.assertFalse((self.root / 'pull').exists()) def test_mutable_empty_and_malformed_references_fail_before_verifier(self): for image in ['', 'registry.invalid/app:latest', 'http://registry.invalid/app@sha256:' + 'a' * 64, IMAGE + ' --flag']: with self.subTest(image=image): self.assertNotEqual(self.run_gate(image).returncode, 0) self.assertFalse((self.root / 'verify').exists()) self.assertFalse((self.root / 'pull').exists()) if __name__ == '__main__': unittest.main()