more changes
This commit is contained in:
1 parent
0fe06f2ba5
commit
be5d4dd97f
3 files changed
+152
-55
No files matched your search
+96
-6
@@ -559,9 +559,28 @@ class ReportTests(unittest.TestCase):
|
||||
self.assertIn("openssl 3.0.1 -> 3.0.2", body)
|
||||
self.assertIn("Overall severity: C 1/1 H 1/2", body)
|
||||
self.assertNotIn("Overall severity: C 1/1 H 1/2 M", body)
|
||||
self.assertIn("Overall: 2/3 fixable/total in 1 container(s)", body)
|
||||
self.assertIn("Overall: 2/3 fixable/total in 1 image(s)", body)
|
||||
self.assertNotIn("Total:", body)
|
||||
|
||||
def test_build_final_summary_body_merges_important_containers_per_image(self) -> None:
|
||||
result = scan.summarise(REPORT)
|
||||
target = scan.ScanTarget(image="nginx:1.27", containers=["web", "worker"])
|
||||
aggregated = scan.AggregatedReport()
|
||||
aggregated.results["nginx:1.27"] = result
|
||||
all_rows = scan.build_container_rows(
|
||||
[target], aggregated, scan.severity_rank("HIGH"), include_empty=True
|
||||
)
|
||||
body = scan.build_final_summary_body(
|
||||
[("worker", target, result), ("web", target, result)], all_rows, "HIGH"
|
||||
)
|
||||
# Both important containers share one image, so one table row and one
|
||||
# package line, listing both names.
|
||||
self.assertRegex(body, table_row_pattern(["nginx:1.27", "web, worker", "1/1", "1/2"]))
|
||||
self.assertIn("* web, worker: ", body)
|
||||
self.assertNotIn("* worker: ", body)
|
||||
self.assertNotIn("* web: ", body)
|
||||
self.assertIn("Overall: 2/3 fixable/total in 1 image(s)", body)
|
||||
|
||||
def test_summary_table_pads_every_column(self) -> None:
|
||||
table = scan.summary_table(
|
||||
[
|
||||
@@ -587,6 +606,54 @@ class ReportTests(unittest.TestCase):
|
||||
),
|
||||
)
|
||||
|
||||
def test_summary_table_sorts_by_container_then_image(self) -> None:
|
||||
counts = {"CRITICAL": 0, "HIGH": 0, "MEDIUM": 0, "LOW": 0}
|
||||
table = scan.summary_table(
|
||||
[
|
||||
("nginx:1.27", "web", counts, counts),
|
||||
("redis:7", "cache", counts, counts),
|
||||
("nginx:1.25", "web", counts, counts),
|
||||
],
|
||||
["CRITICAL", "HIGH"],
|
||||
)
|
||||
self.assertEqual(
|
||||
table,
|
||||
"\n".join(
|
||||
[
|
||||
"```",
|
||||
"| Image | Container | C | H |",
|
||||
"| ---------- | --------- | --- | --- |",
|
||||
"| redis:7 | cache | 0/0 | 0/0 |",
|
||||
"| nginx:1.25 | web | 0/0 | 0/0 |",
|
||||
"| nginx:1.27 | web | 0/0 | 0/0 |",
|
||||
"```",
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
def test_build_container_rows_merges_containers_per_image(self) -> None:
|
||||
aggregated = scan.AggregatedReport()
|
||||
for image in ("redis:7", "nginx:1.27", "alpine:3.20"):
|
||||
aggregated.results[image] = scan.summarise(REPORT)
|
||||
targets = [
|
||||
scan.ScanTarget(image="redis:7", containers=["cache"]),
|
||||
scan.ScanTarget(image="nginx:1.27", containers=["web", "cache", "worker"]),
|
||||
scan.ScanTarget(image="alpine:3.20"),
|
||||
]
|
||||
rows = scan.build_container_rows(
|
||||
targets, aggregated, scan.severity_rank("HIGH"), skip={"worker"}
|
||||
)
|
||||
# One row per image, containers joined and sorted; images without
|
||||
# containers keep an empty container cell.
|
||||
self.assertEqual(
|
||||
[(row[0], row[1]) for row in rows],
|
||||
[
|
||||
("alpine:3.20", ""),
|
||||
("redis:7", "cache"),
|
||||
("nginx:1.27", "cache, web"),
|
||||
],
|
||||
)
|
||||
|
||||
def test_build_missing_body_separates_missing_and_unscanned(self) -> None:
|
||||
body = scan.build_missing_body(["gone"], ["web"])
|
||||
self.assertIn("not running", body)
|
||||
@@ -710,7 +777,7 @@ printf '%s\\n' "$*" >> "$APPRISE_LOG"
|
||||
self.assertTrue(os.path.exists(os.path.join(self.env["REPORT_DIR"], "testphp-php.json")))
|
||||
self.assertIn("testphp-php", Path(self.apprise_log).read_text())
|
||||
|
||||
def test_important_container_always_notified_when_clean(self) -> None:
|
||||
def test_clean_important_container_only_in_final_summary(self) -> None:
|
||||
containers = [container("a" * 64, "alpine:3.20", name="web")]
|
||||
with FakeDocker(containers) as docker:
|
||||
code = self.run_main(
|
||||
@@ -719,12 +786,14 @@ printf '%s\\n' "$*" >> "$APPRISE_LOG"
|
||||
|
||||
self.assertEqual(code, 0)
|
||||
notification = Path(self.apprise_log).read_text()
|
||||
self.assertIn("Vulnerability scan: web (alpine:3.20)", notification)
|
||||
# No individual notification for a clean important container.
|
||||
self.assertNotIn("Vulnerability scan: web (alpine:3.20)", notification)
|
||||
self.assertNotIn("No CVEs at or above", notification)
|
||||
self.assertNotIn("Total:", notification)
|
||||
self.assertIn("No CVEs at or above", notification)
|
||||
# The final summary still lists it with 0/0 totals.
|
||||
self.assertIn("Vulnerability scan: summary", notification)
|
||||
self.assertRegex(notification, table_row_pattern(["alpine:3.20", "web", "0/0", "0/0"]))
|
||||
self.assertIn("Overall: 0/0 fixable/total in 1 container(s)", notification)
|
||||
self.assertIn("Overall: 0/0 fixable/total in 1 image(s)", notification)
|
||||
|
||||
def test_notification_includes_container(self) -> None:
|
||||
containers = [container("a" * 64, "testphp-php", name="testphp")]
|
||||
@@ -755,10 +824,31 @@ printf '%s\\n' "$*" >> "$APPRISE_LOG"
|
||||
self.assertRegex(notification, table_row_pattern(["redis:7", "cache", "1/1", "0/0"]))
|
||||
self.assertNotIn("Total:", notification)
|
||||
self.assertIn("Vulnerability scan: summary", notification)
|
||||
self.assertIn("Overall: 2/2 fixable/total in 2 container(s)", notification)
|
||||
self.assertIn("Overall: 2/2 fixable/total in 2 image(s)", notification)
|
||||
# The important container must not also appear in the summary.
|
||||
self.assertNotIn("testphp-php [web]", notification)
|
||||
|
||||
def test_containers_sharing_an_image_share_one_table_row(self) -> None:
|
||||
containers = [
|
||||
container("a" * 64, "testphp-php", name="web"),
|
||||
container("b" * 64, "testphp-php", name="web2"),
|
||||
container("c" * 64, "redis:7", name="cache"),
|
||||
]
|
||||
with FakeDocker(containers) as docker:
|
||||
code = self.run_main([], docker.socket_path, IMPORTANT_CONTAINERS="cache")
|
||||
|
||||
self.assertEqual(code, 1)
|
||||
notification = Path(self.apprise_log).read_text()
|
||||
self.assertIn("Vulnerability scan: cache (redis:7)", notification)
|
||||
self.assertIn("Vulnerability scan: other containers", notification)
|
||||
# Both containers on the same image are merged into a single row.
|
||||
self.assertRegex(
|
||||
notification, table_row_pattern(["testphp-php", "web, web2", "1/1", "0/0"])
|
||||
)
|
||||
self.assertIn("Vulnerability scan: summary", notification)
|
||||
self.assertRegex(notification, table_row_pattern(["redis:7", "cache", "1/1", "0/0"]))
|
||||
self.assertIn("Overall: 2/2 fixable/total in 2 image(s)", notification)
|
||||
|
||||
def test_missing_important_container_is_reported(self) -> None:
|
||||
containers = [container("a" * 64, "testphp-php", name="web")]
|
||||
with FakeDocker(containers) as docker:
|
||||
|
||||
Reference in new issue
Block a user