mirror of
https://github.com/usestrix/strix.git
synced 2026-09-24 00:51:20 +00:00
test(install): cover checksum and provenance verification
Pin fail-closed installer paths for missing manifests, verifier fallback, and the skip-verify escape hatch (#1267).
This commit is contained in:
parent
0636584eef
commit
a079b6c418
1 changed files with 204 additions and 3 deletions
|
|
@ -48,14 +48,42 @@ esac
|
|||
""",
|
||||
)
|
||||
_write_executable(mock_bin / "docker", "#!/bin/sh\nexit 0\n")
|
||||
# Shadow any real gh/cosign on PATH. Behaviour is driven by env flags.
|
||||
_write_executable(
|
||||
mock_bin / "gh",
|
||||
"""#!/bin/sh
|
||||
# Prefer this mock over a real gh on PATH so tests do not hit GitHub.
|
||||
if [ "$1" = "attestation" ]; then
|
||||
if [ -n "${STRIX_TEST_NO_VERIFIER:-}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
if [ "$1" = "attestation" ] && [ "$2" = "verify" ]; then
|
||||
if [ "$3" = "--help" ]; then
|
||||
exit 0
|
||||
fi
|
||||
printf '%s\\n' "$*" >> "$STRIX_TEST_GH_LOG"
|
||||
if [ -n "${STRIX_TEST_GH_FAIL_VERIFY:-}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
""",
|
||||
)
|
||||
_write_executable(
|
||||
mock_bin / "cosign",
|
||||
"""#!/bin/sh
|
||||
if [ -n "${STRIX_TEST_NO_VERIFIER:-}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
if [ "$1" = "verify-blob-attestation" ]; then
|
||||
if [ "$2" = "--help" ]; then
|
||||
[ -n "${STRIX_TEST_USE_COSIGN:-}" ] && exit 0
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\\n' "$*" >> "$STRIX_TEST_COSIGN_LOG"
|
||||
[ -n "${STRIX_TEST_USE_COSIGN:-}" ] && exit 0
|
||||
exit 1
|
||||
fi
|
||||
exit 1
|
||||
""",
|
||||
)
|
||||
_write_executable(
|
||||
|
|
@ -75,11 +103,19 @@ while [ "$#" -gt 0 ]; do
|
|||
printf '%s\\n' "$1" >> "$STRIX_TEST_CURL_LOG"
|
||||
shift
|
||||
done
|
||||
if [ -n "${STRIX_TEST_CURL_FAIL:-}" ]; then
|
||||
case "$url" in
|
||||
*"$STRIX_TEST_CURL_FAIL"*) exit 22 ;;
|
||||
esac
|
||||
fi
|
||||
case "$url" in
|
||||
*/SHA256SUMS)
|
||||
name=$(basename "$STRIX_TEST_ARCHIVE")
|
||||
if [ -n "${STRIX_TEST_BAD_CHECKSUM:-}" ]; then
|
||||
printf '%s %s\\n' "0" "$name" > "$output"
|
||||
elif [ -n "${STRIX_TEST_SUMS_WRONG_NAME:-}" ]; then
|
||||
hash=$(sha256sum "$STRIX_TEST_ARCHIVE" | awk '{print $1}')
|
||||
printf '%s %s\\n' "$hash" "other-file.tar.gz" > "$output"
|
||||
else
|
||||
hash=$(sha256sum "$STRIX_TEST_ARCHIVE" | awk '{print $1}')
|
||||
printf '%s %s\\n' "$hash" "$name" > "$output"
|
||||
|
|
@ -113,6 +149,8 @@ def _create_installer_environment(
|
|||
download_path = tmp_path / "downloads"
|
||||
download_path.mkdir()
|
||||
curl_log_path = tmp_path / "curl.log"
|
||||
gh_log_path = tmp_path / "gh.log"
|
||||
cosign_log_path = tmp_path / "cosign.log"
|
||||
environment = {
|
||||
"HOME": str(home_path),
|
||||
"XDG_CONFIG_HOME": str(home_path / ".config"),
|
||||
|
|
@ -121,6 +159,8 @@ def _create_installer_environment(
|
|||
"TMPDIR": str(download_path),
|
||||
"STRIX_TEST_ARCHIVE": str(archive_path),
|
||||
"STRIX_TEST_CURL_LOG": str(curl_log_path),
|
||||
"STRIX_TEST_GH_LOG": str(gh_log_path),
|
||||
"STRIX_TEST_COSIGN_LOG": str(cosign_log_path),
|
||||
"VERSION": RELEASE_VERSION,
|
||||
}
|
||||
return environment, home_path, curl_log_path
|
||||
|
|
@ -154,7 +194,20 @@ def test_installer_downloads_and_runs_linux_arm64_release(tmp_path: Path) -> Non
|
|||
|
||||
assert result.returncode == 0, result.stderr
|
||||
expected_filename = f"strix-{RELEASE_VERSION}-{RELEASE_TARGET}.tar.gz"
|
||||
assert expected_filename in curl_log_path.read_text(encoding="utf-8")
|
||||
curl_log = curl_log_path.read_text(encoding="utf-8")
|
||||
assert expected_filename in curl_log
|
||||
assert f"releases/download/v{RELEASE_VERSION}/SHA256SUMS" in curl_log
|
||||
assert f"strix-{RELEASE_TARGET}.intoto.jsonl" in curl_log
|
||||
assert "Checksum verified" in result.stdout
|
||||
assert "Provenance verified" in result.stdout
|
||||
gh_log = (tmp_path / "gh.log").read_text(encoding="utf-8")
|
||||
assert "--repo usestrix/strix" in gh_log
|
||||
assert "--bundle strix-linux-arm64.intoto.jsonl" in gh_log
|
||||
assert (
|
||||
"--signer-workflow usestrix/strix/.github/workflows/build-release.yml" in gh_log
|
||||
)
|
||||
assert "--deny-self-hosted-runners" in gh_log
|
||||
assert not (tmp_path / "cosign.log").exists()
|
||||
|
||||
installed_binary = home_path / ".strix/bin/strix"
|
||||
installed_result = subprocess.run( # noqa: S603
|
||||
|
|
@ -215,3 +268,151 @@ def test_installer_leaves_existing_install_on_checksum_failure(tmp_path: Path) -
|
|||
check=True,
|
||||
)
|
||||
assert installed_result.stdout.strip() == "strix 1.0.0"
|
||||
|
||||
|
||||
def test_installer_rejects_missing_checksum_manifest(tmp_path: Path) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_CURL_FAIL"] = "SHA256SUMS"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "Failed to download checksum manifest" in result.stdout
|
||||
assert not (home_path / ".strix/bin/strix").exists()
|
||||
|
||||
|
||||
def test_installer_rejects_checksum_manifest_without_archive_entry(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_SUMS_WRONG_NAME"] = "1"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "No SHA256SUMS entry" in result.stdout
|
||||
assert not (home_path / ".strix/bin/strix").exists()
|
||||
|
||||
|
||||
def test_installer_rejects_missing_provenance_bundle(tmp_path: Path) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_CURL_FAIL"] = "intoto.jsonl"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "Failed to download provenance bundle" in result.stdout
|
||||
assert "Checksum verified" in result.stdout
|
||||
assert not (home_path / ".strix/bin/strix").exists()
|
||||
|
||||
|
||||
def test_installer_rejects_failed_gh_attestation_verify(tmp_path: Path) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_GH_FAIL_VERIFY"] = "1"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "gh attestation verify failed" in result.stdout
|
||||
assert not (home_path / ".strix/bin/strix").exists()
|
||||
assert not (tmp_path / "cosign.log").exists()
|
||||
|
||||
|
||||
def test_installer_uses_cosign_when_gh_cannot_verify(tmp_path: Path) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_USE_COSIGN"] = "1"
|
||||
_write_executable(
|
||||
mock_bin / "gh",
|
||||
"#!/bin/sh\nexit 1\n",
|
||||
)
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert "Provenance verified" in result.stdout
|
||||
assert "(cosign)" in result.stdout
|
||||
cosign_log = (tmp_path / "cosign.log").read_text(encoding="utf-8")
|
||||
assert "--new-bundle-format" in cosign_log
|
||||
assert "--certificate-oidc-issuer https://token.actions.githubusercontent.com" in (
|
||||
cosign_log
|
||||
)
|
||||
assert "build-release.yml" in cosign_log
|
||||
assert "--type slsaprovenance1" in cosign_log
|
||||
assert (home_path / ".strix/bin/strix").exists()
|
||||
|
||||
|
||||
def test_installer_rejects_when_no_provenance_verifier_is_available(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, _curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_TEST_NO_VERIFIER"] = "1"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode != 0
|
||||
assert "Neither a usable 'gh' nor 'cosign'" in result.stdout
|
||||
assert not (home_path / ".strix/bin/strix").exists()
|
||||
|
||||
|
||||
def test_installer_skip_verify_does_not_download_manifests(tmp_path: Path) -> None:
|
||||
repository_root = Path(__file__).resolve().parents[1]
|
||||
archive_path = _create_release_archive(tmp_path)
|
||||
mock_bin = _create_mock_commands(tmp_path, machine="aarch64")
|
||||
environment, home_path, curl_log_path = _create_installer_environment(
|
||||
tmp_path,
|
||||
archive_path,
|
||||
mock_bin,
|
||||
)
|
||||
environment["STRIX_INSTALL_SKIP_VERIFY"] = "1"
|
||||
|
||||
result = _run_installer(repository_root, environment)
|
||||
|
||||
assert result.returncode == 0, result.stderr
|
||||
curl_log = curl_log_path.read_text(encoding="utf-8")
|
||||
assert "SHA256SUMS" not in curl_log
|
||||
assert "intoto.jsonl" not in curl_log
|
||||
assert "skipping checksum and provenance checks" in result.stdout
|
||||
assert (home_path / ".strix/bin/strix").exists()
|
||||
assert not (tmp_path / "gh.log").exists()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue