|
11 | 11 |
|
12 | 12 | import dojo.risk_acceptance.helper as ra_helper |
13 | 13 | from dojo.jira_link import helper as jira_helper |
14 | | -from dojo.models import Finding, Finding_Group, JIRA_Instance, Risk_Acceptance, User |
| 14 | +from dojo.models import Finding, Finding_Group, JIRA_Instance, Risk_Acceptance, Test, User |
15 | 15 | from unittests.dojo_test_case import ( |
16 | 16 | DojoVCRAPITestCase, |
17 | 17 | get_unit_tests_path, |
@@ -81,6 +81,9 @@ def setUp(self): |
81 | 81 | self.zap_sample5_filename = get_unit_tests_scans_path("zap") / "5_zap_sample_one.xml" |
82 | 82 | self.npm_groups_sample_filename = get_unit_tests_scans_path("npm_audit") / "many_vuln_with_groups.json" |
83 | 83 | self.npm_groups_sample_filename2 = get_unit_tests_scans_path("npm_audit") / "many_vuln_with_groups_different_titles.json" |
| 84 | + self.generic_one_finding_with_component_name = get_unit_tests_scans_path("generic") / "generic_one_finding_with_component_name.json" |
| 85 | + self.generic_two_findings_same_component_name = get_unit_tests_scans_path("generic") / "generic_two_findings_same_component_name.json" |
| 86 | + self.generic_report_with_findings = get_unit_tests_scans_path("generic") / "generic_report1.json" |
84 | 87 | self.clair_few_findings = get_unit_tests_scans_path("clair") / "clair_few_vuln.json" |
85 | 88 | self.client.force_login(self.get_test_admin()) |
86 | 89 |
|
@@ -1070,6 +1073,157 @@ def test_bulk_edit_mixed_findings_and_groups_jira_push_bug(self, mock_webhooks, |
1070 | 1073 | self.assertEqual(len(group_calls), 2, "Expected 2 finding groups to be pushed") |
1071 | 1074 | self.assertEqual(len(individual_calls), 2, "Expected 2 individual findings to be pushed") |
1072 | 1075 |
|
| 1076 | + def test_keep_sync_push_finding_then_update_individual_finding_with_no_push(self): |
| 1077 | + """ |
| 1078 | + With keep_sync enabled, import a scan with push_to_jira=True, then update one of the |
| 1079 | + findings with push_to_jira=False, but keep_sync enabled, should update the issue in JIRA |
| 1080 | + """ |
| 1081 | + # Set the finding sync setting |
| 1082 | + import0 = self.import_scan_with_params( |
| 1083 | + self.generic_one_finding_with_component_name, |
| 1084 | + scan_type="Generic Findings Import", |
| 1085 | + push_to_jira=True, |
| 1086 | + verified=True, |
| 1087 | + ) |
| 1088 | + test_id = import0["test"] |
| 1089 | + test = Test.objects.get(id=test_id) |
| 1090 | + self.assert_jira_issue_count_in_test(test_id, 1) |
| 1091 | + self.assert_jira_group_issue_count_in_test(test_id, 0) |
| 1092 | + # Enable the finding sync |
| 1093 | + self.toggle_jira_finding_sync(test, value=True) |
| 1094 | + # Get one of the findings |
| 1095 | + finding_id = self.get_test_findings_api(test_id)["results"][0]["id"] |
| 1096 | + # Ensure the status is what we expect before the update |
| 1097 | + pre_jira_status = self.get_jira_issue_status(finding_id) |
| 1098 | + self.assertEqual("Backlog", pre_jira_status.name) |
| 1099 | + # Make the update to the finding |
| 1100 | + self.patch_finding_api(finding_id, {"push_to_jira": False, "is_mitigated": True}) |
| 1101 | + # Verify that the status did in fact change |
| 1102 | + post_jira_status = self.get_jira_issue_status(finding_id) |
| 1103 | + self.assertEqual("Done", post_jira_status.name) |
| 1104 | + # by asserting full cassette is played we know issues have been updated in JIRA |
| 1105 | + self.assert_cassette_played() |
| 1106 | + |
| 1107 | + def test_keep_sync_push_finding_then_reimport_with_no_push(self): |
| 1108 | + """ |
| 1109 | + With keep_sync enabled, import a scan with push_to_jira=True, then reimport a second |
| 1110 | + scan with push_to_jira=False that closes one of the findings, should update the issue in JIRA |
| 1111 | + """ |
| 1112 | + # Set the finding sync setting |
| 1113 | + import0 = self.import_scan_with_params( |
| 1114 | + self.generic_two_findings_same_component_name, |
| 1115 | + scan_type="Generic Findings Import", |
| 1116 | + push_to_jira=True, |
| 1117 | + verified=True, |
| 1118 | + ) |
| 1119 | + test_id = import0["test"] |
| 1120 | + test = Test.objects.get(id=test_id) |
| 1121 | + self.assert_jira_issue_count_in_test(test_id, 2) |
| 1122 | + self.assert_jira_group_issue_count_in_test(test_id, 0) |
| 1123 | + # Enable the finding sync |
| 1124 | + self.toggle_jira_finding_sync(test, value=True) |
| 1125 | + # Get the finding that will be closing in the next reimport |
| 1126 | + finding_id = self.get_test_findings_api(test_id, severity="Critical")["results"][0]["id"] |
| 1127 | + # Ensure the status is what we expect before the update |
| 1128 | + pre_jira_status = self.get_jira_issue_status(finding_id) |
| 1129 | + self.assertEqual("Backlog", pre_jira_status.name) |
| 1130 | + # Reimport with a different file that has one finding closed, but push_to_jira=False |
| 1131 | + import0 = self.reimport_scan_with_params( |
| 1132 | + test_id, |
| 1133 | + self.generic_one_finding_with_component_name, |
| 1134 | + scan_type="Generic Findings Import", |
| 1135 | + push_to_jira=False, |
| 1136 | + verified=True, |
| 1137 | + close_old_findings=True, |
| 1138 | + ) |
| 1139 | + # Verify that the status did in fact change |
| 1140 | + post_jira_status = self.get_jira_issue_status(finding_id) |
| 1141 | + self.assertEqual("Done", post_jira_status.name) |
| 1142 | + # by asserting full cassette is played we know issues have been updated in JIRA |
| 1143 | + self.assert_cassette_played() |
| 1144 | + |
| 1145 | + def test_keep_sync_push_finding_groups_then_reimport_empty_file_with_no_push_change_status(self): |
| 1146 | + """ |
| 1147 | + With keep_sync enabled, import a scan with push_to_jira=True that creates a group, then reimport |
| 1148 | + an empty scan with push_to_jira=False that closes the finding in the group, should update the |
| 1149 | + issue in JIRA to closed |
| 1150 | + """ |
| 1151 | + # Set the finding sync setting |
| 1152 | + import0 = self.import_scan_with_params( |
| 1153 | + self.generic_two_findings_same_component_name, |
| 1154 | + scan_type="Generic Findings Import", |
| 1155 | + push_to_jira=True, |
| 1156 | + verified=True, |
| 1157 | + group_by="component_name", |
| 1158 | + ) |
| 1159 | + test_id = import0["test"] |
| 1160 | + test = Test.objects.get(id=test_id) |
| 1161 | + self.assert_jira_issue_count_in_test(test_id, 0) |
| 1162 | + self.assert_jira_group_issue_count_in_test(test_id, 1) |
| 1163 | + # Enable the finding sync |
| 1164 | + self.toggle_jira_finding_sync(test, value=True) |
| 1165 | + # Get the finding that will be closing in the next reimport |
| 1166 | + finding_id = self.get_test_findings_api(test_id, severity="Critical")["results"][0]["id"] |
| 1167 | + # Ensure the status is what we expect before the update |
| 1168 | + pre_jira_status = self.get_jira_issue_status(finding_id) |
| 1169 | + self.assertEqual("Backlog", pre_jira_status.name) |
| 1170 | + # Reimport with a different file that has one finding closed, but push_to_jira=False |
| 1171 | + import0 = self.reimport_scan_with_params( |
| 1172 | + test_id, |
| 1173 | + self.generic_report_with_findings, |
| 1174 | + scan_type="Generic Findings Import", |
| 1175 | + push_to_jira=False, |
| 1176 | + verified=True, |
| 1177 | + close_old_findings=True, |
| 1178 | + group_by="component_name", |
| 1179 | + ) |
| 1180 | + # Verify that the status did in fact change |
| 1181 | + post_jira_status = self.get_jira_issue_status(finding_id) |
| 1182 | + self.assertEqual("Done", post_jira_status.name) |
| 1183 | + # by asserting full cassette is played we know issues have been updated in JIRA |
| 1184 | + self.assert_cassette_played() |
| 1185 | + |
| 1186 | + def test_keep_sync_push_finding_groups_then_reimport_empty_file_with_no_push_change_priority(self): |
| 1187 | + """ |
| 1188 | + With keep_sync enabled, import a scan with push_to_jira=True that creates a group, then reimport |
| 1189 | + an empty scan with push_to_jira=False that closes the finding in the group, this should leave the |
| 1190 | + the high severity finding in the group, and reduce the priority from Critical to High |
| 1191 | + """ |
| 1192 | + # Set the finding sync setting |
| 1193 | + import0 = self.import_scan_with_params( |
| 1194 | + self.generic_two_findings_same_component_name, |
| 1195 | + scan_type="Generic Findings Import", |
| 1196 | + push_to_jira=True, |
| 1197 | + verified=True, |
| 1198 | + group_by="component_name", |
| 1199 | + ) |
| 1200 | + test_id = import0["test"] |
| 1201 | + test = Test.objects.get(id=test_id) |
| 1202 | + self.assert_jira_issue_count_in_test(test_id, 0) |
| 1203 | + self.assert_jira_group_issue_count_in_test(test_id, 1) |
| 1204 | + # Enable the finding sync |
| 1205 | + self.toggle_jira_finding_sync(test, value=True) |
| 1206 | + # Get the finding that will stay open in the next reimport |
| 1207 | + finding_id = self.get_test_findings_api(test_id, severity="High")["results"][0]["id"] |
| 1208 | + # Get the priority that we are starting out with |
| 1209 | + pre_jira_priority = self.get_jira_issue_priority(finding_id) |
| 1210 | + self.assertEqual("Highest", pre_jira_priority.name) |
| 1211 | + # Reimport with a different file that has one finding closed, but push_to_jira=False |
| 1212 | + import0 = self.reimport_scan_with_params( |
| 1213 | + test_id, |
| 1214 | + self.generic_one_finding_with_component_name, |
| 1215 | + scan_type="Generic Findings Import", |
| 1216 | + push_to_jira=False, |
| 1217 | + verified=True, |
| 1218 | + close_old_findings=True, |
| 1219 | + group_by="component_name", |
| 1220 | + ) |
| 1221 | + # Verify that the priority did in fact change |
| 1222 | + post_jira_priority = self.get_jira_issue_priority(finding_id) |
| 1223 | + self.assertEqual("High", post_jira_priority.name) |
| 1224 | + # by asserting full cassette is played we know issues have been updated in JIRA |
| 1225 | + self.assert_cassette_played() |
| 1226 | + |
1073 | 1227 | # creation of epic via the UI is already tested in test_jira_config_engagement_epic, so |
1074 | 1228 | # we take a shortcut here as creating an engagement with epic mapping via the API is not implemented yet |
1075 | 1229 | def create_engagement_epic(self, engagement): |
|
0 commit comments