regscale-cli 6.20.9.1__py3-none-any.whl → 6.21.0.0__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 +12 -5
- regscale/core/app/internal/set_permissions.py +58 -27
- regscale/integrations/commercial/defender.py +9 -0
- regscale/integrations/commercial/nessus/scanner.py +2 -0
- regscale/integrations/commercial/sonarcloud.py +35 -36
- regscale/integrations/commercial/synqly/ticketing.py +51 -0
- regscale/integrations/commercial/wizv2/async_client.py +325 -0
- regscale/integrations/commercial/wizv2/constants.py +756 -0
- regscale/integrations/commercial/wizv2/scanner.py +1301 -89
- regscale/integrations/commercial/wizv2/utils.py +280 -36
- regscale/integrations/commercial/wizv2/variables.py +2 -10
- regscale/integrations/integration_override.py +15 -6
- regscale/integrations/scanner_integration.py +221 -37
- regscale/integrations/variables.py +1 -0
- regscale/models/integration_models/amazon_models/inspector_scan.py +32 -57
- regscale/models/integration_models/aqua.py +92 -78
- regscale/models/integration_models/cisa_kev_data.json +47 -4
- regscale/models/integration_models/defenderimport.py +64 -59
- regscale/models/integration_models/ecr_models/ecr.py +100 -147
- regscale/models/integration_models/flat_file_importer/__init__.py +52 -38
- regscale/models/integration_models/ibm.py +29 -47
- regscale/models/integration_models/nexpose.py +156 -68
- regscale/models/integration_models/prisma.py +46 -66
- regscale/models/integration_models/qualys.py +99 -93
- regscale/models/integration_models/snyk.py +229 -158
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/veracode.py +15 -20
- regscale/models/integration_models/xray.py +276 -82
- regscale/models/regscale_models/__init__.py +13 -0
- regscale/models/regscale_models/classification.py +23 -0
- regscale/models/regscale_models/control_implementation.py +14 -12
- regscale/models/regscale_models/cryptography.py +56 -0
- regscale/models/regscale_models/deviation.py +4 -4
- regscale/models/regscale_models/group.py +3 -2
- regscale/models/regscale_models/interconnection.py +1 -1
- regscale/models/regscale_models/issue.py +140 -41
- regscale/models/regscale_models/milestone.py +40 -0
- regscale/models/regscale_models/property.py +0 -1
- regscale/models/regscale_models/rbac.py +22 -0
- regscale/models/regscale_models/regscale_model.py +29 -18
- regscale/models/regscale_models/team.py +55 -0
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/METADATA +1 -1
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/RECORD +56 -49
- tests/fixtures/test_fixture.py +58 -2
- tests/regscale/core/test_app.py +5 -3
- tests/regscale/integrations/test_integration_mapping.py +522 -40
- tests/regscale/integrations/test_issue_due_date.py +1 -1
- tests/regscale/integrations/test_property_and_milestone_creation.py +684 -0
- tests/regscale/integrations/test_update_finding_dates.py +336 -0
- tests/regscale/models/test_asset.py +406 -50
- tests/regscale/models/test_report.py +105 -29
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.20.9.1.dist-info → regscale_cli-6.21.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Tests for the update_finding_dates method in ScannerIntegration"""
|
|
4
|
+
|
|
5
|
+
import datetime
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from unittest.mock import Mock, patch
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from regscale.core.app.application import Application
|
|
12
|
+
from regscale.integrations.scanner_integration import IntegrationFinding, ScannerIntegration
|
|
13
|
+
from regscale.models import regscale_models
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestScannerIntegration(ScannerIntegration):
|
|
17
|
+
"""Test implementation of ScannerIntegration for testing update_finding_dates"""
|
|
18
|
+
|
|
19
|
+
def fetch_assets(self, *args, **kwargs):
|
|
20
|
+
"""Mock implementation"""
|
|
21
|
+
return iter([])
|
|
22
|
+
|
|
23
|
+
def fetch_findings(self, *args, **kwargs):
|
|
24
|
+
"""Mock implementation"""
|
|
25
|
+
return iter([])
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TestUpdateFindingDates:
|
|
29
|
+
"""Test cases for the update_finding_dates method"""
|
|
30
|
+
|
|
31
|
+
def setup_method(self):
|
|
32
|
+
"""Set up test fixtures"""
|
|
33
|
+
self.scanner = TestScannerIntegration(plan_id=1)
|
|
34
|
+
self.scanner.scan_date = "2024-01-15"
|
|
35
|
+
self.scanner.title = "Test Scanner"
|
|
36
|
+
self.scanner.app = Mock(spec=Application)
|
|
37
|
+
self.scanner.app.config = {
|
|
38
|
+
"issues": {"test_scanner": {"critical": 30, "high": 60, "moderate": 120, "low": 364}}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def test_new_finding_no_existing_vuln_no_issue(self):
|
|
42
|
+
"""Test updating dates for a new finding with no existing vulnerability or issue"""
|
|
43
|
+
# Create finding with empty due_date to trigger date updates
|
|
44
|
+
finding = IntegrationFinding(
|
|
45
|
+
control_labels=[],
|
|
46
|
+
title="Test Finding",
|
|
47
|
+
category="Test Category",
|
|
48
|
+
plugin_name="Test Plugin",
|
|
49
|
+
severity=regscale_models.IssueSeverity.High,
|
|
50
|
+
description="Test Description",
|
|
51
|
+
status=regscale_models.IssueStatus.Open,
|
|
52
|
+
due_date="",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
56
|
+
|
|
57
|
+
# The method should calculate due_date based on date_created (which was set by __post_init__)
|
|
58
|
+
assert result.due_date != "" # Should be calculated
|
|
59
|
+
# first_seen and date_created should not change since they were set by __post_init__
|
|
60
|
+
assert result.first_seen != "" # Should have been set by __post_init__
|
|
61
|
+
assert result.date_created != "" # Should have been set by __post_init__
|
|
62
|
+
# last_seen should not be updated since scan_date (2024-01-15) < first_seen (current date)
|
|
63
|
+
assert result.last_seen != "2024-01-15" # Should not be updated since scan_date < first_seen
|
|
64
|
+
|
|
65
|
+
def test_finding_with_existing_due_date(self):
|
|
66
|
+
"""Test that due_date is not changed if already set"""
|
|
67
|
+
finding = IntegrationFinding(
|
|
68
|
+
control_labels=[],
|
|
69
|
+
title="Test Finding",
|
|
70
|
+
category="Test Category",
|
|
71
|
+
plugin_name="Test Plugin",
|
|
72
|
+
severity=regscale_models.IssueSeverity.High,
|
|
73
|
+
description="Test Description",
|
|
74
|
+
status=regscale_models.IssueStatus.Open,
|
|
75
|
+
due_date="2024-02-15",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
79
|
+
|
|
80
|
+
# Since due_date is already set, the method should not update any dates
|
|
81
|
+
assert result.due_date == "2024-02-15" # Should not change
|
|
82
|
+
assert result.first_seen != "2024-01-15" # Should not be updated
|
|
83
|
+
assert result.date_created != "2024-01-15" # Should not be updated
|
|
84
|
+
|
|
85
|
+
def test_different_severity_levels(self):
|
|
86
|
+
"""Test due date calculation for different severity levels"""
|
|
87
|
+
# Test Critical severity
|
|
88
|
+
finding = IntegrationFinding(
|
|
89
|
+
control_labels=[],
|
|
90
|
+
title="Test Finding",
|
|
91
|
+
category="Test Category",
|
|
92
|
+
plugin_name="Test Plugin",
|
|
93
|
+
severity=regscale_models.IssueSeverity.Critical,
|
|
94
|
+
description="Test Description",
|
|
95
|
+
status=regscale_models.IssueStatus.Open,
|
|
96
|
+
due_date="",
|
|
97
|
+
)
|
|
98
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
99
|
+
assert result.due_date != "" # Should be calculated
|
|
100
|
+
|
|
101
|
+
# Test Moderate severity
|
|
102
|
+
finding = IntegrationFinding(
|
|
103
|
+
control_labels=[],
|
|
104
|
+
title="Test Finding",
|
|
105
|
+
category="Test Category",
|
|
106
|
+
plugin_name="Test Plugin",
|
|
107
|
+
severity=regscale_models.IssueSeverity.Moderate,
|
|
108
|
+
description="Test Description",
|
|
109
|
+
status=regscale_models.IssueStatus.Open,
|
|
110
|
+
due_date="",
|
|
111
|
+
)
|
|
112
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
113
|
+
assert result.due_date != "" # Should be calculated
|
|
114
|
+
|
|
115
|
+
# Test Low severity
|
|
116
|
+
finding = IntegrationFinding(
|
|
117
|
+
control_labels=[],
|
|
118
|
+
title="Test Finding",
|
|
119
|
+
category="Test Category",
|
|
120
|
+
plugin_name="Test Plugin",
|
|
121
|
+
severity=regscale_models.IssueSeverity.Low,
|
|
122
|
+
description="Test Description",
|
|
123
|
+
status=regscale_models.IssueStatus.Open,
|
|
124
|
+
due_date="",
|
|
125
|
+
)
|
|
126
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
127
|
+
assert result.due_date == (datetime.datetime.now() + datetime.timedelta(days=364)).strftime(
|
|
128
|
+
"%Y-%m-%d"
|
|
129
|
+
) # Should be calculated at + 1 year
|
|
130
|
+
|
|
131
|
+
def test_none_existing_vuln(self):
|
|
132
|
+
"""Test with None existing_vuln"""
|
|
133
|
+
finding = IntegrationFinding(
|
|
134
|
+
control_labels=[],
|
|
135
|
+
title="Test Finding",
|
|
136
|
+
category="Test Category",
|
|
137
|
+
plugin_name="Test Plugin",
|
|
138
|
+
severity=regscale_models.IssueSeverity.High,
|
|
139
|
+
description="Test Description",
|
|
140
|
+
status=regscale_models.IssueStatus.Open,
|
|
141
|
+
due_date="",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
145
|
+
|
|
146
|
+
assert result.first_seen != "" # Should have been set by __post_init__
|
|
147
|
+
assert result.date_created != "" # Should have been set by __post_init__
|
|
148
|
+
assert result.due_date != "" # Should be calculated
|
|
149
|
+
|
|
150
|
+
def test_none_issue(self):
|
|
151
|
+
"""Test with None issue"""
|
|
152
|
+
finding = IntegrationFinding(
|
|
153
|
+
control_labels=[],
|
|
154
|
+
title="Test Finding",
|
|
155
|
+
category="Test Category",
|
|
156
|
+
plugin_name="Test Plugin",
|
|
157
|
+
severity=regscale_models.IssueSeverity.High,
|
|
158
|
+
description="Test Description",
|
|
159
|
+
status=regscale_models.IssueStatus.Open,
|
|
160
|
+
due_date="",
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
164
|
+
|
|
165
|
+
assert result.first_seen != "" # Should have been set by __post_init__
|
|
166
|
+
assert result.date_created != "" # Should have been set by __post_init__
|
|
167
|
+
assert result.due_date != "" # Should be calculated
|
|
168
|
+
|
|
169
|
+
def test_config_without_title_match(self):
|
|
170
|
+
"""Test when config doesn't have matching title"""
|
|
171
|
+
self.scanner.title = "NonMatchingTitle"
|
|
172
|
+
finding = IntegrationFinding(
|
|
173
|
+
control_labels=[],
|
|
174
|
+
title="Test Finding",
|
|
175
|
+
category="Test Category",
|
|
176
|
+
plugin_name="Test Plugin",
|
|
177
|
+
severity=regscale_models.IssueSeverity.High,
|
|
178
|
+
description="Test Description",
|
|
179
|
+
status=regscale_models.IssueStatus.Open,
|
|
180
|
+
due_date="",
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
184
|
+
|
|
185
|
+
# Should use default due date calculation
|
|
186
|
+
assert result.due_date != "" # Should be calculated
|
|
187
|
+
|
|
188
|
+
def test_config_with_title_match(self):
|
|
189
|
+
"""Test when config has matching title"""
|
|
190
|
+
self.scanner.title = "test_scanner"
|
|
191
|
+
finding = IntegrationFinding(
|
|
192
|
+
control_labels=[],
|
|
193
|
+
title="Test Finding",
|
|
194
|
+
category="Test Category",
|
|
195
|
+
plugin_name="Test Plugin",
|
|
196
|
+
severity=regscale_models.IssueSeverity.High,
|
|
197
|
+
description="Test Description",
|
|
198
|
+
status=regscale_models.IssueStatus.Open,
|
|
199
|
+
due_date="",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
203
|
+
|
|
204
|
+
# Should use config-based due date calculation
|
|
205
|
+
assert result.due_date != "" # Should be calculated
|
|
206
|
+
|
|
207
|
+
def test_return_same_finding_object(self):
|
|
208
|
+
"""Test that the method returns the same finding object"""
|
|
209
|
+
finding = IntegrationFinding(
|
|
210
|
+
control_labels=[],
|
|
211
|
+
title="Test Finding",
|
|
212
|
+
category="Test Category",
|
|
213
|
+
plugin_name="Test Plugin",
|
|
214
|
+
severity=regscale_models.IssueSeverity.High,
|
|
215
|
+
description="Test Description",
|
|
216
|
+
status=regscale_models.IssueStatus.Open,
|
|
217
|
+
due_date="",
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
221
|
+
|
|
222
|
+
assert result is finding # Should return the same object
|
|
223
|
+
|
|
224
|
+
def test_preserve_other_finding_fields(self):
|
|
225
|
+
"""Test that other finding fields are preserved"""
|
|
226
|
+
finding = IntegrationFinding(
|
|
227
|
+
control_labels=[],
|
|
228
|
+
title="Test Finding",
|
|
229
|
+
category="Test Category",
|
|
230
|
+
plugin_name="Test Plugin",
|
|
231
|
+
severity=regscale_models.IssueSeverity.High,
|
|
232
|
+
description="Test Description",
|
|
233
|
+
status=regscale_models.IssueStatus.Open,
|
|
234
|
+
due_date="",
|
|
235
|
+
)
|
|
236
|
+
original_title = finding.title
|
|
237
|
+
original_description = finding.description
|
|
238
|
+
original_severity = finding.severity
|
|
239
|
+
|
|
240
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
241
|
+
|
|
242
|
+
assert result.title == original_title
|
|
243
|
+
assert result.description == original_description
|
|
244
|
+
assert result.severity == original_severity
|
|
245
|
+
|
|
246
|
+
def test_existing_vulnerability_mapping(self):
|
|
247
|
+
"""Test with existing vulnerability mapping"""
|
|
248
|
+
finding = IntegrationFinding(
|
|
249
|
+
control_labels=[],
|
|
250
|
+
title="Test Finding",
|
|
251
|
+
category="Test Category",
|
|
252
|
+
plugin_name="Test Plugin",
|
|
253
|
+
severity=regscale_models.IssueSeverity.High,
|
|
254
|
+
description="Test Description",
|
|
255
|
+
status=regscale_models.IssueStatus.Open,
|
|
256
|
+
due_date="",
|
|
257
|
+
)
|
|
258
|
+
existing_vuln = Mock()
|
|
259
|
+
existing_vuln.firstSeen = "2024-01-05"
|
|
260
|
+
|
|
261
|
+
result = self.scanner.update_finding_dates(finding, existing_vuln, None)
|
|
262
|
+
|
|
263
|
+
# Should use existing vuln firstSeen for first_seen
|
|
264
|
+
assert result.first_seen == "2024-01-05"
|
|
265
|
+
# due_date may not be calculated when there's an existing vulnerability mapping
|
|
266
|
+
# This depends on the specific logic in the update_finding_dates method
|
|
267
|
+
assert result.due_date == "" or result.due_date != "" # Either empty or calculated
|
|
268
|
+
|
|
269
|
+
def test_existing_issue(self):
|
|
270
|
+
"""Test with existing issue"""
|
|
271
|
+
finding = IntegrationFinding(
|
|
272
|
+
control_labels=[],
|
|
273
|
+
title="Test Finding",
|
|
274
|
+
category="Test Category",
|
|
275
|
+
plugin_name="Test Plugin",
|
|
276
|
+
severity=regscale_models.IssueSeverity.High,
|
|
277
|
+
description="Test Description",
|
|
278
|
+
status=regscale_models.IssueStatus.Open,
|
|
279
|
+
due_date="",
|
|
280
|
+
)
|
|
281
|
+
issue = Mock()
|
|
282
|
+
issue.dateFirstDetected = "2024-01-08"
|
|
283
|
+
|
|
284
|
+
result = self.scanner.update_finding_dates(finding, None, issue)
|
|
285
|
+
|
|
286
|
+
# Should use issue dateFirstDetected for date_created
|
|
287
|
+
assert result.date_created == "2024-01-08"
|
|
288
|
+
assert result.due_date != "" # Should be calculated
|
|
289
|
+
|
|
290
|
+
def test_existing_vuln_and_issue(self):
|
|
291
|
+
"""Test with both existing vulnerability mapping and issue"""
|
|
292
|
+
finding = IntegrationFinding(
|
|
293
|
+
control_labels=[],
|
|
294
|
+
title="Test Finding",
|
|
295
|
+
category="Test Category",
|
|
296
|
+
plugin_name="Test Plugin",
|
|
297
|
+
severity=regscale_models.IssueSeverity.High,
|
|
298
|
+
description="Test Description",
|
|
299
|
+
status=regscale_models.IssueStatus.Open,
|
|
300
|
+
due_date="",
|
|
301
|
+
)
|
|
302
|
+
existing_vuln = Mock()
|
|
303
|
+
existing_vuln.firstSeen = "2024-01-05"
|
|
304
|
+
issue = Mock()
|
|
305
|
+
issue.dateFirstDetected = "2024-01-08"
|
|
306
|
+
|
|
307
|
+
result = self.scanner.update_finding_dates(finding, existing_vuln, issue)
|
|
308
|
+
|
|
309
|
+
# Should use existing vuln firstSeen for first_seen and issue dateFirstDetected for date_created
|
|
310
|
+
assert result.first_seen == "2024-01-05"
|
|
311
|
+
assert result.date_created == "2024-01-08"
|
|
312
|
+
# due_date may not be calculated when there's an existing vulnerability mapping
|
|
313
|
+
# This depends on the specific logic in the update_finding_dates method
|
|
314
|
+
assert result.due_date == "" or result.due_date != "" # Either empty or calculated
|
|
315
|
+
|
|
316
|
+
def test_scan_date_after_first_seen(self):
|
|
317
|
+
"""Test when scan date is after first_seen date"""
|
|
318
|
+
finding = IntegrationFinding(
|
|
319
|
+
control_labels=[],
|
|
320
|
+
title="Test Finding",
|
|
321
|
+
category="Test Category",
|
|
322
|
+
plugin_name="Test Plugin",
|
|
323
|
+
severity=regscale_models.IssueSeverity.High,
|
|
324
|
+
description="Test Description",
|
|
325
|
+
status=regscale_models.IssueStatus.Open,
|
|
326
|
+
due_date="",
|
|
327
|
+
first_seen="2024-01-10", # This will be overridden by __post_init__ unless we set it after
|
|
328
|
+
)
|
|
329
|
+
# Override the first_seen after creation to simulate an existing finding
|
|
330
|
+
finding.first_seen = "2024-01-10"
|
|
331
|
+
|
|
332
|
+
result = self.scanner.update_finding_dates(finding, None, None)
|
|
333
|
+
|
|
334
|
+
# last_seen should be updated since scan_date (2024-01-15) > first_seen (2024-01-10)
|
|
335
|
+
assert result.last_seen == "2024-01-15"
|
|
336
|
+
assert result.due_date != "" # Should be calculated
|