mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-14 06:37:25 +00:00
The make test-security report now holds every finding at the threshold, a suppressed one with its suppressed_until day, and the scan fails only on the unsuppressed rows. The per-image issue keeps listing a suppressed CVE with that day, unsuppressed and CRITICAL rows first, so the issue stays open while a suppression runs instead of closing until it expires. The job summary counts the failing findings and names the suppressed total apart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
94 lines
3.0 KiB
Python
94 lines
3.0 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest import TestCase, main
|
|
|
|
import cli.contributing.security.summary.__main__ as summary_main
|
|
from utils.cache.files import read_text
|
|
|
|
|
|
def _row(image, cve, engine="grype", suppressed_until=None):
|
|
return {
|
|
"image": image,
|
|
"id": cve,
|
|
"engine": engine,
|
|
"suppressed_until": suppressed_until,
|
|
}
|
|
|
|
|
|
REPORT = {
|
|
"findings": [
|
|
_row("docker.io/a:1", "CVE-2026-1001"),
|
|
_row("docker.io/a:1", "CVE-2026-1001", engine="trivy"),
|
|
_row("docker.io/a:1", "CVE-2026-1002"),
|
|
_row("docker.io/b:2", "CVE-2026-1001"),
|
|
_row("docker.io/d:4", "CVE-2026-1003", suppressed_until="2026-12-03"),
|
|
],
|
|
"errors": ["docker.io/c:3: the mirror served no digest"],
|
|
}
|
|
|
|
|
|
class TestCounts(TestCase):
|
|
def test_an_image_counts_its_distinct_cves(self):
|
|
self.assertEqual(
|
|
summary_main.counts(REPORT)["per_image"]["docker.io/a:1"],
|
|
{"cves": 2, "findings": 3},
|
|
)
|
|
|
|
def test_a_cve_counts_its_distinct_images(self):
|
|
self.assertEqual(
|
|
summary_main.counts(REPORT)["per_cve"]["CVE-2026-1001"],
|
|
{"images": 2, "findings": 3},
|
|
)
|
|
|
|
def test_totals_include_the_scan_errors(self):
|
|
counts = summary_main.counts(REPORT)
|
|
self.assertEqual((counts["findings"], counts["errors"]), (4, 1))
|
|
|
|
def test_a_suppressed_finding_is_counted_apart_from_the_failing_ones(self):
|
|
counts = summary_main.counts(REPORT)
|
|
self.assertEqual(
|
|
(counts["suppressed"], "docker.io/d:4" in counts["per_image"]), (1, False)
|
|
)
|
|
|
|
|
|
class TestMarkdown(TestCase):
|
|
def test_the_most_affected_image_comes_first(self):
|
|
text = summary_main.markdown(summary_main.counts(REPORT))
|
|
self.assertLess(text.index("docker.io/a:1"), text.index("docker.io/b:2"))
|
|
|
|
def test_the_headline_names_the_totals(self):
|
|
text = summary_main.markdown(summary_main.counts(REPORT))
|
|
self.assertIn(
|
|
"4 failing finding(s) in 2 image(s), 2 CVE(s), 1 suppressed finding(s), "
|
|
"1 scan error(s).",
|
|
text,
|
|
)
|
|
|
|
|
|
class TestMain(TestCase):
|
|
def test_the_counts_artifact_and_the_summary_are_written(self):
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
root = Path(tmp)
|
|
(root / "report.json").write_text(json.dumps(REPORT), encoding="utf-8")
|
|
summary_main.main(
|
|
[
|
|
"--report",
|
|
str(root / "report.json"),
|
|
"--counts",
|
|
str(root / "counts.json"),
|
|
"--summary",
|
|
str(root / "summary.md"),
|
|
]
|
|
)
|
|
counts = json.loads(read_text(str(root / "counts.json")))
|
|
text = read_text(str(root / "summary.md"))
|
|
self.assertEqual(counts["findings"], 4)
|
|
self.assertIn("Vulnerability scan of the mirror", text)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|