1- import datetime
2-
31# from unittest import skip
42import logging
3+ import zoneinfo
4+ from datetime import datetime
55from pathlib import Path
6+ from unittest .mock import patch
67
8+ from dateutil .relativedelta import relativedelta
79from django .test import override_settings
810from django .test .client import Client
911from django .urls import reverse
@@ -777,13 +779,20 @@ def test_import_0_reimport_1_active_not_verified(self):
777779 # - active findings count should be 4
778780 # - total findings count should be 5
779781 # - zap1 active, zap4 inactive
780- def test_import_0_reimport_1_active_verified_reimport_0_active_verified (self ):
782+ # - zap1 is reactivated but should not have a new sla start date and expiration date
783+ def test_import_0_reimport_1_active_verified_reimport_0_active_verified_sla_no_restart (self ):
781784 logger .debug ("reimporting updated zap xml report, 1 new finding and 1 no longer present, verified=True and then 0 again" )
782785
783786 import0 = self .import_scan_with_params (self .zap_sample0_filename )
784787
785788 test_id = import0 ["test" ]
786789 findings = self .get_test_findings_api (test_id )
790+
791+ for finding in findings ["results" ]:
792+ if "Zap1" in finding ["title" ]:
793+ zap1_initial_sla_start_date = finding ["sla_start_date" ]
794+ zap1_initial_sla_expiration_date = finding ["sla_expiration_date" ]
795+
787796 self .log_finding_summary_json_api (findings )
788797
789798 self .db_finding_count ()
@@ -820,6 +829,8 @@ def test_import_0_reimport_1_active_verified_reimport_0_active_verified(self):
820829 for finding in findings ["results" ]:
821830 if "Zap1" in finding ["title" ]:
822831 self .assertTrue (finding ["active" ])
832+ self .assertEqual (finding ["sla_start_date" ], zap1_initial_sla_start_date )
833+ self .assertEqual (finding ["sla_expiration_date" ], zap1_initial_sla_expiration_date )
823834 zap1_ok = True
824835 if "Zap4" in finding ["title" ]:
825836 self .assertFalse (finding ["active" ])
@@ -845,6 +856,90 @@ def test_import_0_reimport_1_active_verified_reimport_0_active_verified(self):
845856 # zap4 was created and then closed -> only 1 note
846857 self .assertEqual (notes_count_before + 2 + 1 , self .db_notes_count ())
847858
859+ # import 0 and then reimport 1 with zap4 as extra finding, zap1 closed and then reimport 0 again
860+ # - active findings count should be 4
861+ # - total findings count should be 5
862+ # - zap1 active, zap4 inactive
863+ # - zap1 is reactivated and should have a new sla start date and expiration date since we enabled that flag in the test case
864+ @patch ("django.utils.timezone.now" )
865+ def test_import_0_reimport_1_active_verified_reimport_0_active_verified_sla_restart (self , mock_now ):
866+ fake_now = datetime (2025 , 7 , 1 , tzinfo = zoneinfo .ZoneInfo ("UTC" ))
867+ mock_now .return_value = fake_now
868+ logger .debug ("reimporting updated zap xml report, 1 new finding and 1 no longer present, verified=True and then 0 again" )
869+
870+ import0 = self .import_scan_with_params (self .zap_sample0_filename )
871+
872+ test_id = import0 ["test" ]
873+ findings = self .get_test_findings_api (test_id )
874+
875+ for finding in findings ["results" ]:
876+ if "Zap1" in finding ["title" ]:
877+ finding ["sla_start_date" ]
878+ finding ["sla_expiration_date" ]
879+ zap1 = Finding .objects .get (id = finding ["id" ])
880+ sla_configuration = zap1 .get_sla_configuration ()
881+ sla_configuration .restart_sla_on_reactivation = True
882+ sla_configuration .save ()
883+
884+ self .log_finding_summary_json_api (findings )
885+
886+ self .db_finding_count ()
887+ endpoint_count_before = self .db_endpoint_count ()
888+ endpoint_status_count_before_active = self .db_endpoint_status_count (mitigated = False )
889+ endpoint_status_count_before_mitigated = self .db_endpoint_status_count (mitigated = True )
890+ notes_count_before = self .db_notes_count ()
891+
892+ reimport1 = self .reimport_scan_with_params (test_id , self .zap_sample1_filename )
893+
894+ # zap1 should be closed 2 endpoint statuses less, but 2 extra for zap4
895+ self .assertEqual (endpoint_status_count_before_active - 3 + 2 , self .db_endpoint_status_count (mitigated = False ))
896+ self .assertEqual (endpoint_status_count_before_mitigated + 2 , self .db_endpoint_status_count (mitigated = True ))
897+
898+ endpoint_status_count_before_active = self .db_endpoint_status_count (mitigated = False )
899+ endpoint_status_count_before_mitigated = self .db_endpoint_status_count (mitigated = True )
900+
901+ with assertTestImportModelsCreated (self , reimports = 1 , affected_findings = 2 , closed = 1 , reactivated = 1 , untouched = 3 ):
902+ self .reimport_scan_with_params (test_id , self .zap_sample0_filename )
903+
904+ test_id = reimport1 ["test" ]
905+ self .assertEqual (test_id , test_id )
906+
907+ self .get_test_api (test_id )
908+ findings = self .get_test_findings_api (test_id )
909+ self .log_finding_summary_json_api (findings )
910+
911+ # active findings must be equal to those in both reports
912+ findings = self .get_test_findings_api (test_id )
913+ self .assert_finding_count_json (4 + 1 , findings )
914+
915+ for finding in findings ["results" ]:
916+ if "Zap1" in finding ["title" ]:
917+ self .assertTrue (finding ["active" ])
918+ self .assertEqual (finding ["sla_start_date" ], fake_now .date ().isoformat ())
919+ sla_days = finding ["severity" ].lower ()
920+ sla_config = Finding .objects .get (id = finding ["id" ]).test .engagement .product .sla_configuration
921+ sla_expiration_date = fake_now .date () + relativedelta (days = getattr (sla_config , sla_days ))
922+ self .assertEqual (finding ["sla_expiration_date" ], sla_expiration_date .isoformat ())
923+ else :
924+ self .assertIsNone (finding ["sla_start_date" ])
925+
926+ # verified findings must be equal to those in report 0
927+ findings = self .get_test_findings_api (test_id , verified = True )
928+ self .assert_finding_count_json (0 , findings )
929+
930+ findings = self .get_test_findings_api (test_id , verified = False )
931+ self .assert_finding_count_json (5 , findings )
932+
933+ self .assertEqual (endpoint_count_before , self .db_endpoint_count ())
934+
935+ # zap4 should be closed again so 2 mitigated eps, zap1 should be open again so 3 active extra
936+ self .assertEqual (endpoint_status_count_before_active + 3 - 2 , self .db_endpoint_status_count (mitigated = False ))
937+ self .assertEqual (endpoint_status_count_before_mitigated - 3 + 2 , self .db_endpoint_status_count (mitigated = True ))
938+
939+ # zap1 was closed and then opened -> 2 notes
940+ # zap4 was created and then closed -> only 1 note
941+ self .assertEqual (notes_count_before + 2 + 1 , self .db_notes_count ())
942+
848943 # import 0 and then reimport 2 with an extra endpoint for zap1
849944 # - extra endpoint should be present in db
850945 # - reimport doesn't look at endpoints to match against existing findings
@@ -1584,8 +1679,8 @@ def test_import_reimport_vulnerability_ids(self):
15841679 engagement = test .engagement ,
15851680 test_type = test_type ,
15861681 scan_type = self .anchore_grype_scan_type ,
1587- target_start = datetime .datetime . now (datetime . UTC ),
1588- target_end = datetime .datetime . now (datetime . UTC ),
1682+ target_start = datetime .now (timezone . get_current_timezone () ),
1683+ target_end = datetime .now (timezone . get_current_timezone () ),
15891684 )
15901685 reimport_test .save ()
15911686
0 commit comments