regscale-cli 6.26.0.0__py3-none-any.whl → 6.27.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of regscale-cli might be problematic. Click here for more details.
- regscale/_version.py +1 -1
- regscale/core/app/application.py +1 -1
- regscale/core/app/internal/evidence.py +419 -2
- regscale/dev/code_gen.py +24 -20
- regscale/integrations/commercial/__init__.py +0 -1
- regscale/integrations/commercial/jira.py +367 -126
- regscale/integrations/commercial/qualys/__init__.py +7 -8
- regscale/integrations/commercial/qualys/scanner.py +8 -3
- regscale/integrations/commercial/synqly/assets.py +17 -0
- regscale/integrations/commercial/synqly/vulnerabilities.py +45 -28
- regscale/integrations/commercial/tenablev2/cis_parsers.py +453 -0
- regscale/integrations/commercial/tenablev2/cis_scanner.py +447 -0
- regscale/integrations/commercial/tenablev2/commands.py +142 -1
- regscale/integrations/commercial/tenablev2/scanner.py +0 -1
- regscale/integrations/commercial/tenablev2/stig_parsers.py +113 -57
- regscale/integrations/commercial/wizv2/WizDataMixin.py +1 -1
- regscale/integrations/commercial/wizv2/click.py +44 -59
- regscale/integrations/commercial/wizv2/compliance/__init__.py +15 -0
- regscale/integrations/commercial/wizv2/{policy_compliance_helpers.py → compliance/helpers.py} +78 -60
- regscale/integrations/commercial/wizv2/compliance_report.py +10 -9
- regscale/integrations/commercial/wizv2/core/__init__.py +133 -0
- regscale/integrations/commercial/wizv2/{async_client.py → core/client.py} +3 -3
- regscale/integrations/commercial/wizv2/{constants.py → core/constants.py} +1 -17
- regscale/integrations/commercial/wizv2/core/file_operations.py +237 -0
- regscale/integrations/commercial/wizv2/fetchers/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{data_fetcher.py → fetchers/policy_assessment.py} +5 -9
- regscale/integrations/commercial/wizv2/issue.py +1 -1
- regscale/integrations/commercial/wizv2/models/__init__.py +0 -0
- regscale/integrations/commercial/wizv2/parsers/__init__.py +34 -0
- regscale/integrations/commercial/wizv2/{parsers.py → parsers/main.py} +1 -1
- regscale/integrations/commercial/wizv2/processors/__init__.py +11 -0
- regscale/integrations/commercial/wizv2/{finding_processor.py → processors/finding.py} +1 -1
- regscale/integrations/commercial/wizv2/reports.py +1 -1
- regscale/integrations/commercial/wizv2/sbom.py +1 -1
- regscale/integrations/commercial/wizv2/scanner.py +40 -100
- regscale/integrations/commercial/wizv2/utils/__init__.py +48 -0
- regscale/integrations/commercial/wizv2/{utils.py → utils/main.py} +116 -61
- regscale/integrations/commercial/wizv2/variables.py +89 -3
- regscale/integrations/compliance_integration.py +0 -46
- regscale/integrations/control_matcher.py +22 -3
- regscale/integrations/due_date_handler.py +14 -8
- regscale/integrations/public/fedramp/docx_parser.py +10 -1
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +393 -340
- regscale/integrations/public/fedramp/fedramp_five.py +1 -1
- regscale/integrations/scanner_integration.py +127 -57
- regscale/models/integration_models/cisa_kev_data.json +132 -9
- regscale/models/integration_models/qualys.py +3 -4
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +24 -7
- regscale/models/integration_models/synqly_models/synqly_model.py +8 -1
- regscale/models/regscale_models/control_implementation.py +1 -1
- regscale/models/regscale_models/issue.py +0 -1
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/METADATA +1 -17
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/RECORD +94 -61
- tests/regscale/integrations/commercial/test_jira.py +481 -91
- tests/regscale/integrations/commercial/test_wiz.py +96 -200
- tests/regscale/integrations/commercial/wizv2/__init__.py +1 -1
- tests/regscale/integrations/commercial/wizv2/compliance/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/compliance/test_helpers.py +903 -0
- tests/regscale/integrations/commercial/wizv2/core/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/core/test_auth.py +701 -0
- tests/regscale/integrations/commercial/wizv2/core/test_client.py +1037 -0
- tests/regscale/integrations/commercial/wizv2/core/test_file_operations.py +989 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/fetchers/test_policy_assessment.py +805 -0
- tests/regscale/integrations/commercial/wizv2/parsers/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/parsers/test_main.py +1153 -0
- tests/regscale/integrations/commercial/wizv2/processors/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/processors/test_finding.py +671 -0
- tests/regscale/integrations/commercial/wizv2/test_WizDataMixin.py +537 -0
- tests/regscale/integrations/commercial/wizv2/test_click_comprehensive.py +851 -0
- tests/regscale/integrations/commercial/wizv2/test_compliance_report_comprehensive.py +910 -0
- tests/regscale/integrations/commercial/wizv2/test_file_cleanup.py +283 -0
- tests/regscale/integrations/commercial/wizv2/test_file_operations.py +260 -0
- tests/regscale/integrations/commercial/wizv2/test_issue.py +1 -1
- tests/regscale/integrations/commercial/wizv2/test_issue_comprehensive.py +1203 -0
- tests/regscale/integrations/commercial/wizv2/test_reports.py +497 -0
- tests/regscale/integrations/commercial/wizv2/test_sbom.py +643 -0
- tests/regscale/integrations/commercial/wizv2/test_scanner_comprehensive.py +805 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_click_client_id.py +1 -1
- tests/regscale/integrations/commercial/wizv2/test_wiz_compliance_report.py +72 -29
- tests/regscale/integrations/commercial/wizv2/test_wiz_findings_comprehensive.py +364 -0
- tests/regscale/integrations/commercial/wizv2/test_wiz_inventory_comprehensive.py +644 -0
- tests/regscale/integrations/commercial/wizv2/test_wizv2.py +946 -78
- tests/regscale/integrations/commercial/wizv2/test_wizv2_utils.py +97 -202
- tests/regscale/integrations/commercial/wizv2/utils/__init__.py +1 -0
- tests/regscale/integrations/commercial/wizv2/utils/test_main.py +1523 -0
- tests/regscale/integrations/public/test_fedramp.py +301 -0
- tests/regscale/integrations/test_control_matcher.py +83 -0
- regscale/integrations/commercial/wizv2/policy_compliance.py +0 -3543
- tests/regscale/integrations/commercial/wizv2/test_wiz_policy_compliance.py +0 -750
- /regscale/integrations/commercial/wizv2/{wiz_auth.py → core/auth.py} +0 -0
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/LICENSE +0 -0
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/WHEEL +0 -0
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.26.0.0.dist-info → regscale_cli-6.27.0.1.dist-info}/top_level.txt +0 -0
|
@@ -14,11 +14,12 @@ logger = logging.getLogger("regscale")
|
|
|
14
14
|
class TestWizUtils(unittest.TestCase):
|
|
15
15
|
"""Test cases for Wiz utility functions."""
|
|
16
16
|
|
|
17
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
18
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
19
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
20
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
21
|
-
|
|
17
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
18
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
19
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
20
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
21
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3)
|
|
22
|
+
def test_get_report_url_and_status_completed(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
22
23
|
"""Test get_report_url_and_status with COMPLETED status."""
|
|
23
24
|
# Mock response for completed report
|
|
24
25
|
mock_response = MagicMock()
|
|
@@ -35,13 +36,17 @@ class TestWizUtils(unittest.TestCase):
|
|
|
35
36
|
self.assertEqual(result, "https://example.com/report.csv")
|
|
36
37
|
mock_download_report.assert_called_once_with({"reportId": "test-report-id"})
|
|
37
38
|
mock_rerun_report.assert_not_called()
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
41
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
42
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
43
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
44
|
-
|
|
39
|
+
mock_sleep.assert_not_called() # Should not sleep on first success
|
|
40
|
+
|
|
41
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
42
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
43
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
44
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.get_report_url_and_status")
|
|
45
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
46
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3)
|
|
47
|
+
def test_get_report_url_and_status_expired(
|
|
48
|
+
self, mock_recursive_call, mock_rerun_report, mock_download_report, mock_sleep
|
|
49
|
+
):
|
|
45
50
|
"""Test get_report_url_and_status with EXPIRED status."""
|
|
46
51
|
# Mock response for expired report
|
|
47
52
|
mock_response = MagicMock()
|
|
@@ -65,14 +70,16 @@ class TestWizUtils(unittest.TestCase):
|
|
|
65
70
|
mock_download_report.assert_called_once_with({"reportId": "test-report-id"})
|
|
66
71
|
mock_rerun_report.assert_called_once_with({"reportId": "test-report-id"})
|
|
67
72
|
mock_recursive_call.assert_called_once_with("test-report-id")
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
71
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
72
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
73
|
-
|
|
73
|
+
mock_sleep.assert_not_called() # Should not sleep on first call before recursion
|
|
74
|
+
|
|
75
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
76
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
77
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
78
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
79
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 5)
|
|
80
|
+
def test_get_report_url_and_status_rate_limit(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
74
81
|
"""Test get_report_url_and_status with rate limit error."""
|
|
75
|
-
from regscale.integrations.commercial.wizv2.constants import RATE_LIMIT_MSG
|
|
82
|
+
from regscale.integrations.commercial.wizv2.core.constants import RATE_LIMIT_MSG
|
|
76
83
|
|
|
77
84
|
# Mock response with rate limit error
|
|
78
85
|
mock_response = MagicMock()
|
|
@@ -94,21 +101,22 @@ class TestWizUtils(unittest.TestCase):
|
|
|
94
101
|
# Configure mock to return different responses on subsequent calls
|
|
95
102
|
mock_download_report.side_effect = [mock_response, mock_response2]
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
108
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
109
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
110
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
111
|
-
|
|
104
|
+
# Call the function
|
|
105
|
+
result = get_report_url_and_status("test-report-id")
|
|
106
|
+
|
|
107
|
+
# Verify the result
|
|
108
|
+
self.assertEqual(result, "https://example.com/report.csv")
|
|
109
|
+
self.assertEqual(mock_download_report.call_count, 2)
|
|
110
|
+
mock_rerun_report.assert_not_called()
|
|
111
|
+
# Sleep is called twice: once for rate limit, once for retry interval
|
|
112
|
+
self.assertEqual(mock_sleep.call_count, 2)
|
|
113
|
+
|
|
114
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
115
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
116
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
117
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
118
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3)
|
|
119
|
+
def test_get_report_url_and_status_failed_response(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
112
120
|
"""Test get_report_url_and_status with failed response."""
|
|
113
121
|
# Mock failed response
|
|
114
122
|
mock_response = MagicMock()
|
|
@@ -123,11 +131,12 @@ class TestWizUtils(unittest.TestCase):
|
|
|
123
131
|
mock_download_report.assert_called_once_with({"reportId": "test-report-id"})
|
|
124
132
|
mock_rerun_report.assert_not_called()
|
|
125
133
|
|
|
126
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
127
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
128
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
129
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
130
|
-
|
|
134
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
135
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
136
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
137
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
138
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3)
|
|
139
|
+
def test_get_report_url_and_status_none_response(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
131
140
|
"""Test get_report_url_and_status with None response."""
|
|
132
141
|
# Mock None response
|
|
133
142
|
mock_download_report.return_value = None
|
|
@@ -140,11 +149,12 @@ class TestWizUtils(unittest.TestCase):
|
|
|
140
149
|
mock_download_report.assert_called_once_with({"reportId": "test-report-id"})
|
|
141
150
|
mock_rerun_report.assert_not_called()
|
|
142
151
|
|
|
143
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
144
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
145
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
146
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
147
|
-
|
|
152
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
153
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
154
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
155
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
156
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3) # Reduce retries for faster testing
|
|
157
|
+
def test_get_report_url_and_status_other_error(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
148
158
|
"""Test get_report_url_and_status with other error in response."""
|
|
149
159
|
# Mock response with other error
|
|
150
160
|
mock_response = MagicMock()
|
|
@@ -161,11 +171,12 @@ class TestWizUtils(unittest.TestCase):
|
|
|
161
171
|
self.assertEqual(mock_download_report.call_count, 3)
|
|
162
172
|
mock_rerun_report.assert_not_called()
|
|
163
173
|
|
|
164
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
165
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
166
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
167
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
168
|
-
|
|
174
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
175
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
176
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
177
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
178
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3) # Reduce retries for faster testing
|
|
179
|
+
def test_get_report_url_and_status_unknown_status(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
169
180
|
"""Test get_report_url_and_status with unknown status."""
|
|
170
181
|
# Mock response with unknown status
|
|
171
182
|
mock_response = MagicMock()
|
|
@@ -182,11 +193,12 @@ class TestWizUtils(unittest.TestCase):
|
|
|
182
193
|
self.assertEqual(mock_download_report.call_count, 3)
|
|
183
194
|
mock_rerun_report.assert_not_called()
|
|
184
195
|
|
|
185
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
186
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
187
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
188
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
189
|
-
|
|
196
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
197
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
198
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
199
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
200
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3) # Reduce retries for faster testing
|
|
201
|
+
def test_get_report_url_and_status_missing_status(self, mock_rerun_report, mock_download_report, mock_sleep):
|
|
190
202
|
"""Test get_report_url_and_status with missing status in response."""
|
|
191
203
|
# Mock response with missing status
|
|
192
204
|
mock_response = MagicMock()
|
|
@@ -203,12 +215,13 @@ class TestWizUtils(unittest.TestCase):
|
|
|
203
215
|
self.assertEqual(mock_download_report.call_count, 3)
|
|
204
216
|
mock_rerun_report.assert_not_called()
|
|
205
217
|
|
|
206
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
207
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
208
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
209
|
-
@patch("regscale.integrations.commercial.wizv2.utils.
|
|
218
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.time.sleep")
|
|
219
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.download_report")
|
|
220
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.rerun_expired_report")
|
|
221
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
222
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.MAX_RETRIES", 3)
|
|
210
223
|
def test_get_report_url_and_status_multiple_attempts_before_completion(
|
|
211
|
-
self, mock_rerun_report, mock_download_report
|
|
224
|
+
self, mock_rerun_report, mock_download_report, mock_sleep
|
|
212
225
|
):
|
|
213
226
|
"""Test get_report_url_and_status with multiple attempts before completion."""
|
|
214
227
|
# Mock responses: first two with unknown status, third with completed
|
|
@@ -229,132 +242,14 @@ class TestWizUtils(unittest.TestCase):
|
|
|
229
242
|
# Configure mock to return different responses on subsequent calls
|
|
230
243
|
mock_download_report.side_effect = [mock_response1, mock_response2, mock_response3]
|
|
231
244
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
result = get_report_url_and_status("test-report-id")
|
|
235
|
-
|
|
236
|
-
# Verify the result
|
|
237
|
-
self.assertEqual(result, "https://example.com/report.csv")
|
|
238
|
-
self.assertEqual(mock_download_report.call_count, 3)
|
|
239
|
-
# Should sleep twice (after first and second attempts)
|
|
240
|
-
self.assertEqual(mock_sleep.call_count, 2)
|
|
241
|
-
mock_rerun_report.assert_not_called()
|
|
242
|
-
|
|
243
|
-
@patch("regscale.integrations.commercial.wizv2.utils.download_report")
|
|
244
|
-
@patch("regscale.integrations.commercial.wizv2.utils.rerun_expired_report")
|
|
245
|
-
@patch("regscale.integrations.commercial.wizv2.utils.MAX_RETRIES", 3)
|
|
246
|
-
def test_get_report_url_and_status_rate_limit(self, mock_rerun_report, mock_download_report):
|
|
247
|
-
"""Test get_report_url_and_status with rate limit error."""
|
|
248
|
-
from regscale.integrations.commercial.wizv2.constants import RATE_LIMIT_MSG
|
|
249
|
-
import time
|
|
250
|
-
|
|
251
|
-
# Mock response with rate limit error
|
|
252
|
-
mock_response = MagicMock()
|
|
253
|
-
mock_response.ok = True
|
|
254
|
-
mock_response.json.return_value = {
|
|
255
|
-
"errors": [{"message": "Rate limit exceeded", "extensions": {"retryAfter": 5}}]
|
|
256
|
-
}
|
|
257
|
-
mock_download_report.return_value = mock_response
|
|
258
|
-
|
|
259
|
-
# Mock second response for successful completion
|
|
260
|
-
mock_response2 = MagicMock()
|
|
261
|
-
mock_response2.ok = True
|
|
262
|
-
mock_response2.json.return_value = {
|
|
263
|
-
"data": {"report": {"lastRun": {"status": "COMPLETED", "url": "https://example.com/report.csv"}}}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
# Configure mock to return different responses on subsequent calls
|
|
267
|
-
mock_download_report.side_effect = [mock_response, mock_response2]
|
|
268
|
-
|
|
269
|
-
with patch("time.sleep") as mock_sleep:
|
|
270
|
-
# Call the function
|
|
271
|
-
result = get_report_url_and_status("test-report-id")
|
|
272
|
-
|
|
273
|
-
# Verify the result
|
|
274
|
-
self.assertEqual(result, "https://example.com/report.csv")
|
|
275
|
-
self.assertEqual(mock_download_report.call_count, 2)
|
|
276
|
-
# Check that time.sleep was called with the rate limit retry value (5)
|
|
277
|
-
mock_sleep.assert_any_call(5)
|
|
278
|
-
mock_rerun_report.assert_not_called()
|
|
279
|
-
|
|
280
|
-
@patch("regscale.integrations.commercial.wizv2.utils.download_report")
|
|
281
|
-
@patch("regscale.integrations.commercial.wizv2.utils.rerun_expired_report")
|
|
282
|
-
@patch("regscale.integrations.commercial.wizv2.utils.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
283
|
-
def test_get_report_url_and_status_other_error(self, mock_rerun_report, mock_download_report):
|
|
284
|
-
"""Test get_report_url_and_status with other error in response."""
|
|
285
|
-
# Mock response with other error
|
|
286
|
-
mock_response = MagicMock()
|
|
287
|
-
mock_response.ok = True
|
|
288
|
-
mock_response.json.return_value = {"errors": [{"message": "Some other error occurred"}]}
|
|
289
|
-
mock_download_report.return_value = mock_response
|
|
290
|
-
|
|
291
|
-
# Call the function and expect exception after max retries
|
|
292
|
-
with self.assertRaises(Exception) as context:
|
|
293
|
-
get_report_url_and_status("test-report-id")
|
|
294
|
-
|
|
295
|
-
self.assertIn("Download failed, exceeding the maximum number of retries", str(context.exception))
|
|
296
|
-
# Should be called MAX_RETRIES times
|
|
297
|
-
self.assertEqual(mock_download_report.call_count, 100)
|
|
298
|
-
mock_rerun_report.assert_not_called()
|
|
299
|
-
|
|
300
|
-
@patch("regscale.integrations.commercial.wizv2.utils.download_report")
|
|
301
|
-
@patch("regscale.integrations.commercial.wizv2.utils.rerun_expired_report")
|
|
302
|
-
@patch("regscale.integrations.commercial.wizv2.utils.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
303
|
-
def test_get_report_url_and_status_unknown_status(self, mock_rerun_report, mock_download_report):
|
|
304
|
-
"""Test get_report_url_and_status with unknown status."""
|
|
305
|
-
# Mock response with unknown status
|
|
306
|
-
mock_response = MagicMock()
|
|
307
|
-
mock_response.ok = True
|
|
308
|
-
mock_response.json.return_value = {"data": {"report": {"lastRun": {"status": "UNKNOWN_STATUS"}}}}
|
|
309
|
-
mock_download_report.return_value = mock_response
|
|
310
|
-
|
|
311
|
-
# Call the function and expect exception after max retries
|
|
312
|
-
with self.assertRaises(Exception) as context:
|
|
313
|
-
get_report_url_and_status("test-report-id")
|
|
314
|
-
|
|
315
|
-
self.assertIn("Download failed, exceeding the maximum number of retries", str(context.exception))
|
|
316
|
-
# Should be called MAX_RETRIES times
|
|
317
|
-
self.assertEqual(mock_download_report.call_count, 100)
|
|
318
|
-
mock_rerun_report.assert_not_called()
|
|
319
|
-
|
|
320
|
-
@patch("regscale.integrations.commercial.wizv2.utils.download_report")
|
|
321
|
-
@patch("regscale.integrations.commercial.wizv2.utils.rerun_expired_report")
|
|
322
|
-
@patch("regscale.integrations.commercial.wizv2.utils.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
323
|
-
def test_get_report_url_and_status_missing_status(self, mock_rerun_report, mock_download_report):
|
|
324
|
-
"""Test get_report_url_and_status with missing status in response."""
|
|
325
|
-
# Mock response with missing status
|
|
326
|
-
mock_response = MagicMock()
|
|
327
|
-
mock_response.ok = True
|
|
328
|
-
mock_response.json.return_value = {"data": {"report": {"lastRun": {}}}}
|
|
329
|
-
mock_download_report.return_value = mock_response
|
|
330
|
-
|
|
331
|
-
# Call the function and expect exception after max retries
|
|
332
|
-
with self.assertRaises(Exception) as context:
|
|
333
|
-
get_report_url_and_status("test-report-id")
|
|
334
|
-
|
|
335
|
-
self.assertIn("Download failed, exceeding the maximum number of retries", str(context.exception))
|
|
336
|
-
# Should be called MAX_RETRIES times
|
|
337
|
-
self.assertEqual(mock_download_report.call_count, 100)
|
|
338
|
-
mock_rerun_report.assert_not_called()
|
|
339
|
-
|
|
340
|
-
@patch("regscale.integrations.commercial.wizv2.utils.download_report")
|
|
341
|
-
@patch("regscale.integrations.commercial.wizv2.utils.rerun_expired_report")
|
|
342
|
-
@patch("regscale.integrations.commercial.wizv2.utils.CHECK_INTERVAL_FOR_DOWNLOAD_REPORT", 0.001)
|
|
343
|
-
def test_get_report_url_and_status_missing_data(self, mock_rerun_report, mock_download_report):
|
|
344
|
-
"""Test get_report_url_and_status with missing data in response."""
|
|
345
|
-
# Mock response with missing data
|
|
346
|
-
mock_response = MagicMock()
|
|
347
|
-
mock_response.ok = True
|
|
348
|
-
mock_response.json.return_value = {}
|
|
349
|
-
mock_download_report.return_value = mock_response
|
|
350
|
-
|
|
351
|
-
# Call the function and expect exception after max retries
|
|
352
|
-
with self.assertRaises(Exception) as context:
|
|
353
|
-
get_report_url_and_status("test-report-id")
|
|
245
|
+
# Call the function
|
|
246
|
+
result = get_report_url_and_status("test-report-id")
|
|
354
247
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
self.assertEqual(mock_download_report.call_count,
|
|
248
|
+
# Verify the result
|
|
249
|
+
self.assertEqual(result, "https://example.com/report.csv")
|
|
250
|
+
self.assertEqual(mock_download_report.call_count, 3)
|
|
251
|
+
# Should sleep twice (after first and second attempts)
|
|
252
|
+
self.assertEqual(mock_sleep.call_count, 2)
|
|
358
253
|
mock_rerun_report.assert_not_called()
|
|
359
254
|
|
|
360
255
|
|
|
@@ -371,8 +266,8 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
371
266
|
]
|
|
372
267
|
self.target_framework = "NIST_SP_800-53_Revision_5"
|
|
373
268
|
|
|
374
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
375
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
269
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
270
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
376
271
|
def test_get_or_create_report_id_existing_valid_report(self, mock_is_expired, mock_application):
|
|
377
272
|
"""Test returning existing report ID when report is valid (not expired)."""
|
|
378
273
|
# Mock Application
|
|
@@ -400,9 +295,9 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
400
295
|
mock_app.config.get.assert_called_once_with("wizReportAge", 15)
|
|
401
296
|
mock_is_expired.assert_called_once_with("2023-07-15T14:37:55.450532Z", 15)
|
|
402
297
|
|
|
403
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
404
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
405
|
-
@patch("regscale.integrations.commercial.wizv2.utils.create_compliance_report")
|
|
298
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
299
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
300
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.create_compliance_report")
|
|
406
301
|
def test_get_or_create_report_id_existing_expired_report(
|
|
407
302
|
self, mock_create_report, mock_is_expired, mock_application
|
|
408
303
|
):
|
|
@@ -440,8 +335,8 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
440
335
|
framework_id="framework-1",
|
|
441
336
|
)
|
|
442
337
|
|
|
443
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
444
|
-
@patch("regscale.integrations.commercial.wizv2.utils.create_compliance_report")
|
|
338
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
339
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.create_compliance_report")
|
|
445
340
|
def test_get_or_create_report_id_no_existing_report(self, mock_create_report, mock_application):
|
|
446
341
|
"""Test creating new report when no existing report is found."""
|
|
447
342
|
# Mock Application
|
|
@@ -467,8 +362,8 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
467
362
|
framework_id="framework-1",
|
|
468
363
|
)
|
|
469
364
|
|
|
470
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
471
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
365
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
366
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
472
367
|
def test_get_or_create_report_id_missing_run_at(self, mock_is_expired, mock_application):
|
|
473
368
|
"""Test behavior when existing report has no runAt timestamp."""
|
|
474
369
|
# Mock Application
|
|
@@ -497,7 +392,7 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
497
392
|
# is_report_expired should not be called when runAt is missing
|
|
498
393
|
mock_is_expired.assert_not_called()
|
|
499
394
|
|
|
500
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
395
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
501
396
|
def test_get_or_create_report_id_framework_not_found(self, mock_application):
|
|
502
397
|
"""Test ValueError when target framework is not in frameworks list."""
|
|
503
398
|
# Mock Application
|
|
@@ -518,8 +413,8 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
518
413
|
# The actual error message from list.index() is different
|
|
519
414
|
self.assertIn("is not in list", str(context.exception))
|
|
520
415
|
|
|
521
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
522
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
416
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
417
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
523
418
|
def test_get_or_create_report_id_custom_report_age(self, mock_is_expired, mock_application):
|
|
524
419
|
"""Test using custom wizReportAge configuration."""
|
|
525
420
|
# Mock Application with custom age
|
|
@@ -547,9 +442,9 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
547
442
|
mock_app.config.get.assert_called_once_with("wizReportAge", 15)
|
|
548
443
|
mock_is_expired.assert_called_once_with("2023-07-15T14:37:55.450532Z", 30)
|
|
549
444
|
|
|
550
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
551
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
552
|
-
@patch("regscale.integrations.commercial.wizv2.utils.create_compliance_report")
|
|
445
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
446
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
447
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.create_compliance_report")
|
|
553
448
|
def test_get_or_create_report_id_multiple_reports_first_match(
|
|
554
449
|
self, mock_create_report, mock_is_expired, mock_application
|
|
555
450
|
):
|
|
@@ -585,9 +480,9 @@ class TestGetOrCreateReportId(unittest.TestCase):
|
|
|
585
480
|
mock_is_expired.assert_called_once_with("2023-07-15T14:37:55.450532Z", 15)
|
|
586
481
|
mock_create_report.assert_not_called()
|
|
587
482
|
|
|
588
|
-
@patch("regscale.integrations.commercial.wizv2.utils.Application")
|
|
589
|
-
@patch("regscale.integrations.commercial.wizv2.utils.is_report_expired")
|
|
590
|
-
@patch("regscale.integrations.commercial.wizv2.utils.create_compliance_report")
|
|
483
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.Application")
|
|
484
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.is_report_expired")
|
|
485
|
+
@patch("regscale.integrations.commercial.wizv2.utils.main.create_compliance_report")
|
|
591
486
|
def test_get_or_create_report_id_different_report_names(
|
|
592
487
|
self, mock_create_report, mock_is_expired, mock_application
|
|
593
488
|
):
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Tests for Wiz V2 Utils"""
|