Skip to content

Commit a854911

Browse files
close old findings: make test cases test default behaviour (#12842)
* reimport: test cases must use default value in api * reimport: test cases must use default value in api * update comment for UI default * reimport: remove explicit close_old_findings params to use default * import: rely on default close_old_findings False for API tests
1 parent f3954fa commit a854911

File tree

2 files changed

+93
-24
lines changed

2 files changed

+93
-24
lines changed

unittests/dojo_test_case.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ def get_results_by_id(self, results: list, object_id: int) -> dict | None:
536536
return None
537537

538538
def import_scan_with_params(self, filename, scan_type="ZAP Scan", engagement=1, minimum_severity="Low", *, active=True, verified=False,
539-
push_to_jira=None, endpoint_to_add=None, tags=None, close_old_findings=False, group_by=None, engagement_name=None,
539+
push_to_jira=None, endpoint_to_add=None, tags=None, close_old_findings=None, group_by=None, engagement_name=None,
540540
product_name=None, product_type_name=None, auto_create_context=None, expected_http_status_code=201, test_title=None,
541541
scan_date=None, service=None, force_active=True, force_verified=True):
542542

@@ -546,9 +546,11 @@ def import_scan_with_params(self, filename, scan_type="ZAP Scan", engagement=1,
546546
"scan_type": scan_type,
547547
"file": testfile,
548548
"version": "1.0.1",
549-
"close_old_findings": close_old_findings,
550549
}
551550

551+
if close_old_findings is not None:
552+
payload["close_old_findings"] = close_old_findings
553+
552554
if active is not None:
553555
payload["active"] = active
554556

@@ -594,7 +596,7 @@ def import_scan_with_params(self, filename, scan_type="ZAP Scan", engagement=1,
594596
return self.import_scan(payload, expected_http_status_code)
595597

596598
def reimport_scan_with_params(self, test_id, filename, scan_type="ZAP Scan", engagement=1, minimum_severity="Low", *, active=True, verified=False, push_to_jira=None,
597-
tags=None, close_old_findings=True, group_by=None, engagement_name=None, scan_date=None, service=None,
599+
tags=None, close_old_findings=None, group_by=None, engagement_name=None, scan_date=None, service=None,
598600
product_name=None, product_type_name=None, auto_create_context=None, expected_http_status_code=201, test_title=None):
599601
with Path(filename).open(encoding="utf-8") as testfile:
600602
payload = {
@@ -604,9 +606,11 @@ def reimport_scan_with_params(self, test_id, filename, scan_type="ZAP Scan", eng
604606
"scan_type": scan_type,
605607
"file": testfile,
606608
"version": "1.0.1",
607-
"close_old_findings": close_old_findings,
608609
}
609610

611+
if close_old_findings is not None:
612+
payload["close_old_findings"] = close_old_findings
613+
610614
if test_id is not None:
611615
payload["test"] = test_id
612616

unittests/test_import_reimport.py

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -998,9 +998,42 @@ def test_import_0_reimport_3_active_verified(self):
998998
# - zap2 and zap5 closed
999999
self.assertEqual(notes_count_before + 2, self.db_notes_count())
10001000

1001+
# import 1 and then reimport 2 without closing old findings should result in old findings being closed as the default is True in serializers.py
1002+
# for the UI tests this also works as the default is True in the (re)import methods in this test class
1003+
# - reimport should mitigate the zap1
1004+
def test_import_reimport_without_close_old_findings(self):
1005+
# https://github.com/DefectDojo/django-DefectDojo/pull/12837
1006+
logger.debug("reimporting updated zap xml report and using default value for close_old_findings (True)")
1007+
1008+
import1 = self.import_scan_with_params(self.zap_sample1_filename)
1009+
1010+
test_id = import1["test"]
1011+
findings = self.get_test_findings_api(test_id)
1012+
self.assert_finding_count_json(4, findings)
1013+
1014+
with assertTestImportModelsCreated(self, reimports=1, affected_findings=2, closed=1, created=1, untouched=3):
1015+
reimport1 = self.reimport_scan_with_params(test_id, self.zap_sample2_filename)
1016+
1017+
test_id = reimport1["test"]
1018+
self.assertEqual(test_id, test_id)
1019+
1020+
findings = self.get_test_findings_api(test_id)
1021+
self.assert_finding_count_json(5, findings)
1022+
1023+
mitigated = 0
1024+
not_mitigated = 0
1025+
for finding in findings["results"]:
1026+
logger.debug(finding)
1027+
if finding["is_mitigated"]:
1028+
mitigated += 1
1029+
else:
1030+
not_mitigated += 1
1031+
self.assertEqual(mitigated, 1)
1032+
self.assertEqual(not_mitigated, 4)
1033+
10011034
# import 1 and then reimport 2 without closing old findings
10021035
# - reimport should not mitigate the zap1
1003-
def test_import_reimport_without_closing_old_findings(self):
1036+
def test_import_reimport_with_close_old_findings_false(self):
10041037
logger.debug("reimporting updated zap xml report and keep old findings open")
10051038

10061039
import1 = self.import_scan_with_params(self.zap_sample1_filename)
@@ -1015,12 +1048,9 @@ def test_import_reimport_without_closing_old_findings(self):
10151048
test_id = reimport1["test"]
10161049
self.assertEqual(test_id, test_id)
10171050

1018-
findings = self.get_test_findings_api(test_id, verified=False)
1051+
findings = self.get_test_findings_api(test_id)
10191052
self.assert_finding_count_json(5, findings)
10201053

1021-
findings = self.get_test_findings_api(test_id, verified=True)
1022-
self.assert_finding_count_json(0, findings)
1023-
10241054
mitigated = 0
10251055
not_mitigated = 0
10261056
for finding in findings["results"]:
@@ -1030,7 +1060,7 @@ def test_import_reimport_without_closing_old_findings(self):
10301060
else:
10311061
not_mitigated += 1
10321062
self.assertEqual(mitigated, 0)
1033-
self.assertEqual(not_mitigated, 0)
1063+
self.assertEqual(not_mitigated, 5)
10341064

10351065
# some parsers generate 1 finding for each vulnerable file for each vulnerability
10361066
# i.e
@@ -1211,7 +1241,7 @@ def test_import_6_reimport_6_gitlab_dep_scan_component_name_and_version(self):
12111241
def test_import_param_close_old_findings_with_additional_endpoint(self):
12121242
logger.debug("importing clair report with additional endpoint")
12131243
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1214-
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, endpoint_to_add=1)
1244+
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, endpoint_to_add=1)
12151245

12161246
test_id = import0["test"]
12171247
test = self.get_test(test_id)
@@ -1229,19 +1259,51 @@ def test_import_param_close_old_findings_with_additional_endpoint(self):
12291259
self.assertEqual(finding.endpoints.count(), 1)
12301260
self.assertEqual(finding.endpoints.first().id, 1)
12311261

1232-
# reimport empty report
1262+
# reimport empty report to close old findings
12331263
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, closed=4):
12341264
self.import_scan_with_params(self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, endpoint_to_add=1)
12351265

12361266
# all findings from import0 should be closed now
12371267
engagement_findings_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False).count()
12381268
self.assertEqual(engagement_findings_count, 0)
12391269

1270+
# import clair scan, testing:
1271+
# parameter endpoint_to_add: each imported finding should be related to endpoint with id=1
1272+
# close_old_findings functionality: secony (empty) import should not close all findings from the first import as we rely on the default value of close_old_findings=False
1273+
def test_import_param_close_old_findings_default_with_additional_endpoint(self):
1274+
logger.debug("importing clair report with additional endpoint")
1275+
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1276+
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, endpoint_to_add=1)
1277+
1278+
test_id = import0["test"]
1279+
test = self.get_test(test_id)
1280+
findings = self.get_test_findings_api(test_id)
1281+
self.log_finding_summary_json_api(findings)
1282+
# imported count must match count in the report
1283+
self.assert_finding_count_json(4, findings)
1284+
1285+
# imported findings should be active in the engagement
1286+
engagement_findings = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
1287+
self.assertEqual(engagement_findings.count(), 4)
1288+
1289+
# findings should have only one endpoint, added with endpoint_to_add
1290+
for finding in engagement_findings:
1291+
self.assertEqual(finding.endpoints.count(), 1)
1292+
self.assertEqual(finding.endpoints.first().id, 1)
1293+
1294+
# reimport empty report with no explicit close_old_findings parameter should not close old findings
1295+
with assertTestImportModelsCreated(self, imports=1, affected_findings=0, closed=0):
1296+
self.import_scan_with_params(self.clair_empty, scan_type=self.scan_type_clair, endpoint_to_add=1)
1297+
1298+
# all findings from import0 should be closed now
1299+
engagement_findings_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False).count()
1300+
self.assertEqual(engagement_findings_count, 4)
1301+
12401302
# close_old_findings functionality: second (empty) import should close all findings from the first import when setting the same service
12411303
def test_import_param_close_old_findings_with_same_service(self):
12421304
logger.debug("importing clair report with same service")
12431305
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1244-
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, service="service_1")
1306+
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, service="service_1")
12451307

12461308
test_id = import0["test"]
12471309
test = self.get_test(test_id)
@@ -1254,7 +1316,7 @@ def test_import_param_close_old_findings_with_same_service(self):
12541316
engagement_findings = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
12551317
self.assertEqual(engagement_findings.count(), 4)
12561318

1257-
# reimport empty report
1319+
# reimport empty report to close old findings
12581320
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, closed=4):
12591321
self.import_scan_with_params(self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, service="service_1")
12601322

@@ -1266,7 +1328,7 @@ def test_import_param_close_old_findings_with_same_service(self):
12661328
def test_import_param_close_old_findings_with_different_services(self):
12671329
logger.debug("importing clair report with different services")
12681330
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1269-
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, service="service_1")
1331+
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, service="service_1")
12701332

12711333
test_id = import0["test"]
12721334
test = self.get_test(test_id)
@@ -1279,7 +1341,7 @@ def test_import_param_close_old_findings_with_different_services(self):
12791341
engagement_findings = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
12801342
self.assertEqual(engagement_findings.count(), 4)
12811343

1282-
# reimport empty report
1344+
# reimport empty report to close old findings
12831345
with assertTestImportModelsCreated(self, imports=1, affected_findings=0, closed=0):
12841346
self.import_scan_with_params(self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, service="service_2")
12851347

@@ -1290,7 +1352,7 @@ def test_import_param_close_old_findings_with_different_services(self):
12901352
# close_old_findings functionality: second (empty) import should not close findings from the first import when setting a service in the first import but none in the second import
12911353
def test_import_param_close_old_findings_with_and_without_service_1(self):
12921354
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1293-
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, service="service_1")
1355+
import0 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, service="service_1")
12941356

12951357
test_id = import0["test"]
12961358
test = self.get_test(test_id)
@@ -1303,7 +1365,7 @@ def test_import_param_close_old_findings_with_and_without_service_1(self):
13031365
engagement_findings = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
13041366
self.assertEqual(engagement_findings.count(), 4)
13051367

1306-
# reimport empty report
1368+
# reimport empty report to close old findings
13071369
with assertTestImportModelsCreated(self, imports=1, affected_findings=0, closed=0):
13081370
self.import_scan_with_params(self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, service=None)
13091371

@@ -1339,7 +1401,7 @@ def test_import_param_close_old_findings_with_and_without_service_2(self):
13391401
def test_reimport_close_old_findings_different_engagements_different_services(self):
13401402
logger.debug("importing clair report with service A into engagement 1")
13411403
with assertTestImportModelsCreated(self, imports=1, affected_findings=4, created=4):
1342-
import1 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, engagement=1, close_old_findings=True, service="service_A")
1404+
import1 = self.import_scan_with_params(self.clair_few_findings, scan_type=self.scan_type_clair, engagement=1, service="service_A")
13431405

13441406
test_id = import1["test"]
13451407
test = self.get_test(test_id)
@@ -1353,7 +1415,7 @@ def test_reimport_close_old_findings_different_engagements_different_services(se
13531415
self.assertEqual(engagement1_findings.count(), 4)
13541416

13551417
# reimporting the same report into the same test with a different service should not close any findings and create 4 new findings
1356-
self.reimport_scan_with_params(test_id, self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, service="service_B")
1418+
self.reimport_scan_with_params(test_id, self.clair_few_findings, scan_type=self.scan_type_clair, service="service_B")
13571419

13581420
engagement1_active_finding_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
13591421
self.assertEqual(engagement1_active_finding_count.count(), 8)
@@ -1365,7 +1427,7 @@ def test_reimport_close_old_findings_different_engagements_different_services(se
13651427
self.assertFalse(finding.is_mitigated)
13661428

13671429
# reimporting an empty report with service A should close all findings from the first import, but not the reimported ones with service B
1368-
self.reimport_scan_with_params(test_id, self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, service="service_A")
1430+
self.reimport_scan_with_params(test_id, self.clair_empty, scan_type=self.scan_type_clair, service="service_A")
13691431

13701432
engagement1_active_finding_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
13711433
self.assertEqual(engagement1_active_finding_count.count(), 4)
@@ -1383,7 +1445,7 @@ def test_reimport_close_old_findings_different_engagements_different_services(se
13831445
self.assertEqual(finding.service, "service_A")
13841446

13851447
# reimporting an empty report with service B should close all findings from the second import, and not reopen any findings
1386-
self.reimport_scan_with_params(test_id, self.clair_empty, scan_type=self.scan_type_clair, close_old_findings=True, service="service_B")
1448+
self.reimport_scan_with_params(test_id, self.clair_empty, scan_type=self.scan_type_clair, service="service_B")
13871449

13881450
engagement1_active_finding_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
13891451
self.assertEqual(engagement1_active_finding_count.count(), 0)
@@ -1395,7 +1457,7 @@ def test_reimport_close_old_findings_different_engagements_different_services(se
13951457
self.assertTrue(finding.is_mitigated)
13961458

13971459
# reimporting a report with findings and service A should reopen the 4findings with service_A but leave the findings with service_B closed.
1398-
self.reimport_scan_with_params(test_id, self.clair_few_findings, scan_type=self.scan_type_clair, close_old_findings=True, service="service_A")
1460+
self.reimport_scan_with_params(test_id, self.clair_few_findings, scan_type=self.scan_type_clair, service="service_A")
13991461

14001462
engagement1_active_finding_count = Finding.objects.filter(test__engagement_id=1, test__test_type=test.test_type, active=True, is_mitigated=False)
14011463
self.assertEqual(engagement1_active_finding_count.count(), 4)
@@ -1954,7 +2016,10 @@ def import_scan_with_params_ui(self, filename, scan_type="ZAP Scan", engagement=
19542016

19552017
return self.import_scan_ui(engagement, payload)
19562018

1957-
def reimport_scan_with_params_ui(self, test_id, filename, scan_type="ZAP Scan", minimum_severity="Low", *, active=True, verified=False, push_to_jira=None, tags=None, close_old_findings=True, scan_date=None, service=None):
2019+
# For UI tests we cannot rely on the default for close_old_findings True as when we leave out the field in the request,
2020+
# Django (or rathet HTML FORM spec) will interpret that as False. So we explicitly set it to True here.
2021+
def reimport_scan_with_params_ui(self, test_id, filename, scan_type="ZAP Scan", minimum_severity="Low", *, active=True, verified=False, push_to_jira=None, tags=None,
2022+
close_old_findings=True, scan_date=None, service=None):
19582023
# Mimic old functionality for active/verified to avoid breaking tests
19592024
activePayload = "force_to_true"
19602025
if not active:

0 commit comments

Comments
 (0)