Files
ITWorx_MCP_Hub-Public/tests/test_database_candidate_provenance.py
T

264 lines
13 KiB
Python

from __future__ import annotations
import hashlib
import io
import json
import os
import shutil
import subprocess
import sys
import tarfile
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
BUNDLE = ROOT / "evidence/WP-400/database-image-candidate-20261003"
SCAN_EVIDENCE = ROOT / "evidence/WP-400/DATABASE_REMEDIATION_SCANS.json"
PUBLICATION_EVIDENCE = ROOT / "evidence/WP-400/DATABASE_CANDIDATE_PUBLICATION_20261003.json"
def read_json(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))
def sha256(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
def bundle_files(bundle: Path) -> set[str]:
return {
path.relative_to(bundle).as_posix()
for path in bundle.rglob("*")
if path.is_file() and path != bundle / "FILE_HASHES.json"
}
def run_git(cwd: Path, *arguments: str) -> bytes:
result = subprocess.run( # noqa: S603
["git", *arguments], # noqa: S607
cwd=cwd,
check=True,
capture_output=True,
)
return result.stdout
class DatabaseCandidateProvenanceTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.manifest = read_json(BUNDLE / "candidate-provenance.json")
cls.scan_evidence = read_json(SCAN_EVIDENCE)
cls.publication = read_json(PUBLICATION_EVIDENCE)
def test_retained_recipe_sources_match_the_exact_build_recipe_hashes(self) -> None:
for service in ("postgres", "redis"):
with self.subTest(service=service):
item = self.manifest["images"][service]
build = read_json(BUNDLE / item["buildReceiptFile"])
self.assertEqual(set(item["sourceFiles"]), set(build["recipeHashes"]))
plan = (
read_json(BUNDLE / "recipes" / service / "plan.json")
if service == "postgres"
else None
)
for name, expected in item["sourceFiles"].items():
source = BUNDLE / "recipes" / service / name
if name.endswith(".tar.gz"):
self.assertFalse(
source.exists(), "the binary upstream archive must stay excluded"
)
self.assertFalse(
self.manifest["trackedBundle"]["binaryGosuSourceArchiveIncluded"]
)
self.assertEqual(expected, plan["source"]["archive_sha256"])
else:
self.assertTrue(source.is_file(), name)
self.assertEqual(sha256(source), expected, name)
self.assertEqual(build["recipeHashes"][name], expected, name)
def test_build_export_scan_and_publication_bind_the_same_candidates(self) -> None:
self.assertFalse(self.manifest["releaseEligible"])
self.assertFalse(self.manifest["reviewBoundary"]["releaseEligible"])
self.assertEqual(self.manifest["reviewBoundary"]["humanCveRiskAcceptance"], "pending")
self.assertFalse(self.manifest["reviewBoundary"]["agentMayApproveCveExceptions"])
self.assertFalse(self.manifest["reviewBoundary"]["bitForBitRebuildClaim"])
self.assertFalse(self.scan_evidence["productionDeployment"])
self.assertFalse(self.publication["productionDeployment"])
self.assertFalse(self.publication["cveRiskAccepted"])
for service in ("postgres", "redis"):
with self.subTest(service=service):
item = self.manifest["images"][service]
build = read_json(BUNDLE / item["buildReceiptFile"])
download = read_json(BUNDLE / item["downloadReceiptFile"])
scan = read_json(BUNDLE / item["scanReceiptFile"])
summary = read_json(BUNDLE / item["vulnerabilityScan"]["summaryFile"])
secret = read_json(BUNDLE / item["secretScan"]["sanitizedReceiptFile"])
image = build["image"]
published_ref = self.manifest["publishedImageRefs"][service]
published = self.publication["candidates"][service]
scanned = self.scan_evidence["images"][service]
self.assertEqual(item["publishedImageRef"], published_ref)
self.assertIsNone(item["productionImageRef"])
self.assertEqual(item["candidateOnly"], True)
self.assertIsNone(item["productionImageRef"])
self.assertEqual(published["reference"], published_ref)
self.assertEqual(scanned["artifact"]["publishedImage"]["reference"], published_ref)
self.assertEqual(published["scannedImageId"], image["id"])
self.assertEqual(published["pulledImageId"], image["id"])
self.assertTrue(published["immutablePullConfigMatchedScannedImage"])
self.assertEqual(item["vulnerabilityScan"]["artifactRef"]["imageId"], image["id"])
self.assertEqual(
item["vulnerabilityScan"]["rawReportSha256"],
scan["rawVulnerabilityReportSha256"],
)
self.assertEqual(download["artifactRef"]["imageId"], image["id"])
self.assertEqual(download["artifactRef"]["tag"], image["tag"])
self.assertEqual(download["localSha256"], build["archive"]["sha256"])
self.assertEqual(download["remoteSha256"], build["archive"]["sha256"])
self.assertEqual(scan["artifactRef"]["imageId"], image["id"])
self.assertEqual(scan["artifactRef"]["archiveSha256"], build["archive"]["sha256"])
self.assertEqual(scan["reportIdentity"]["ImageID"], image["id"])
self.assertEqual(scan["ignoreUnfixed"], False)
self.assertEqual(scan["findingFilters"], [])
self.assertEqual(scan["tlsVerification"], True)
self.assertEqual(scan["packageCount"], summary["packageCount"])
self.assertGreater(summary["packageCount"], 0)
inventory = summary["strictVersionInventory"]
self.assertTrue(inventory["allNamesAndVersionsPresent"])
self.assertEqual(inventory["packageEntriesChecked"], summary["packageCount"])
self.assertEqual(secret["ImageID"], image["id"])
self.assertEqual(secret["FindingCount"], 0)
self.assertFalse(secret["SensitiveFindingDetailsPersisted"])
self.assertEqual(scanned["humanRiskAcceptance"], "pending")
self.assertFalse(scanned["productionDeployment"])
def test_bundle_hash_manifest_covers_retained_recipe_and_receipt_files(self) -> None:
evidence = self.scan_evidence["recipeProvenance"]
self.assertEqual(
evidence["manifestPath"],
"evidence/WP-400/database-image-candidate-20261003/candidate-provenance.json",
)
self.assertEqual(evidence["manifestSha256"], sha256(BUNDLE / "candidate-provenance.json"))
self.assertEqual(
evidence["fileHashesPath"],
"evidence/WP-400/database-image-candidate-20261003/FILE_HASHES.json",
)
hashes_path = BUNDLE / "FILE_HASHES.json"
self.assertEqual(evidence["fileHashesSha256"], sha256(hashes_path))
hashes = read_json(hashes_path)
actual_files = bundle_files(BUNDLE)
self.assertEqual(set(hashes["files"]), actual_files)
for relative, expected in hashes["files"].items():
with self.subTest(path=relative):
self.assertEqual(sha256(BUNDLE / relative), expected)
def test_ci_compilation_preserves_strict_bundle_inventory(self) -> None:
with tempfile.TemporaryDirectory(prefix="wp400-compiled-provenance-") as temporary:
bundle = Path(temporary) / "evidence"
recipe = bundle / "recipes" / "test_recipe_contract.py"
recipe.parent.mkdir(parents=True)
recipe.write_text("assert True\n", encoding="utf-8")
source_hash = sha256(recipe)
cache_root = Path(temporary) / "managed-bytecode"
subprocess.run( # noqa: S603
[sys.executable, "-m", "py_compile", str(recipe)],
env=dict(os.environ, PYTHONPYCACHEPREFIX=str(cache_root)),
check=True,
capture_output=True,
)
self.assertTrue(any(cache_root.rglob("*.pyc")))
self.assertEqual(sha256(recipe), source_hash)
self.assertEqual(bundle_files(bundle), {"recipes/test_recipe_contract.py"})
unexpected = recipe.parent / "__pycache__" / "unexpected.json"
unexpected.parent.mkdir()
unexpected.write_text("{}\n", encoding="utf-8")
matching_cache = unexpected.with_name(
f"test_recipe_contract.{sys.implementation.cache_tag}.pyc"
)
matching_cache.write_bytes(b"unexpected cache bytes")
self.assertEqual(
bundle_files(bundle),
{
"recipes/test_recipe_contract.py",
"recipes/__pycache__/unexpected.json",
f"recipes/__pycache__/{matching_cache.name}",
},
)
workflow = (ROOT / ".gitea/workflows/managed-validation.yml").read_text(encoding="utf-8")
self.assertIn(
'PYTHONPYCACHEPREFIX="${RUNNER_TEMP}/managed-bytecode" '
"xargs -0 -r python -m py_compile",
workflow,
)
def test_git_objects_archives_and_autocrlf_checkouts_preserve_bundle_hashes(self) -> None:
file_hashes = read_json(BUNDLE / "FILE_HASHES.json")["files"]
expected_hashes = dict(file_hashes)
expected_hashes["FILE_HASHES.json"] = self.scan_evidence["recipeProvenance"][
"fileHashesSha256"
]
bundle_path = Path("evidence/WP-400/database-image-candidate-20261003")
with tempfile.TemporaryDirectory(prefix="wp400-git-byte-provenance-") as temporary:
temporary_root = Path(temporary)
source = temporary_root / "source"
source.mkdir()
shutil.copyfile(ROOT / ".gitattributes", source / ".gitattributes")
for relative in expected_hashes:
destination = source / bundle_path / relative
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(BUNDLE / relative, destination)
run_git(source, "init", "--quiet")
run_git(source, "config", "user.name", "WP-400 provenance test")
run_git(source, "config", "user.email", "wp400-provenance@example.invalid")
run_git(source, "config", "core.autocrlf", "true")
run_git(source, "config", "core.safecrlf", "false")
hooks = source / ".test-hooks"
hooks.mkdir()
run_git(source, "config", "core.hooksPath", ".test-hooks")
run_git(source, "add", "--all")
run_git(source, "commit", "--quiet", "-m", "byte-preserving provenance fixture")
archive = run_git(source, "archive", "--format=tar", "HEAD", str(bundle_path))
archive_prefix = bundle_path.as_posix() + "/"
with tarfile.open(fileobj=io.BytesIO(archive), mode="r:") as archived:
archived_files = {
member.name.removeprefix(archive_prefix): member
for member in archived.getmembers()
if member.isfile() and member.name.startswith(archive_prefix)
}
self.assertEqual(set(archived_files), set(expected_hashes))
for relative, expected in expected_hashes.items():
member_file = archived.extractfile(archived_files[relative])
self.assertIsNotNone(member_file)
self.assertEqual(
hashlib.sha256(member_file.read()).hexdigest(), expected, relative
)
for autocrlf in ("false", "true"):
with self.subTest(core_autocrlf=autocrlf):
checkout = temporary_root / f"checkout-{autocrlf}"
run_git(
temporary_root,
"clone",
"--quiet",
"--no-checkout",
str(source),
str(checkout),
)
run_git(checkout, "config", "core.autocrlf", autocrlf)
run_git(checkout, "config", "core.safecrlf", "false")
run_git(checkout, "checkout", "--force", "HEAD")
for relative, expected in expected_hashes.items():
self.assertEqual(sha256(checkout / bundle_path / relative), expected)
if __name__ == "__main__":
unittest.main()