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
|
@@ -10,10 +10,12 @@ from regscale.core.app.application import Application
|
|
|
10
10
|
from regscale.core.app.logz import create_logger
|
|
11
11
|
from regscale.core.app.utils.app_utils import get_current_datetime, is_valid_fqdn
|
|
12
12
|
from regscale.core.utils.date import datetime_str
|
|
13
|
+
from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
|
|
14
|
+
from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
|
|
13
15
|
from regscale.models.app_models import ImportValidater
|
|
14
16
|
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
15
|
-
from regscale.models.regscale_models
|
|
16
|
-
from regscale.models.regscale_models
|
|
17
|
+
from regscale.models.regscale_models import AssetStatus, IssueSeverity, IssueStatus
|
|
18
|
+
from regscale.models.regscale_models import AssetStatus, IssueSeverity, IssueStatus
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class Aqua(FlatFileImporter):
|
|
@@ -36,6 +38,7 @@ class Aqua(FlatFileImporter):
|
|
|
36
38
|
self.vendor_cvss_v2_severity = "Vendor CVSS v2 Severity"
|
|
37
39
|
self.vendor_cvss_v3_severity = "Vendor CVSS v3 Severity"
|
|
38
40
|
self.vendor_cvss_v3_score = "Vendor CVSS v3 Score"
|
|
41
|
+
self.vendor_cvss_v2_score = "Vendor CVSS v2 Score"
|
|
39
42
|
self.nvd_cvss_v2_severity = "NVD CVSS v2 Severity"
|
|
40
43
|
self.nvd_cvss_v3_severity = "NVD CVSS v3 Severity"
|
|
41
44
|
self.required_headers = [
|
|
@@ -63,40 +66,32 @@ class Aqua(FlatFileImporter):
|
|
|
63
66
|
**kwargs,
|
|
64
67
|
)
|
|
65
68
|
|
|
66
|
-
def create_asset(self, dat: Optional[dict] = None) -> Optional[
|
|
69
|
+
def create_asset(self, dat: Optional[dict] = None) -> Optional[IntegrationAsset]:
|
|
67
70
|
"""
|
|
68
|
-
Create an
|
|
71
|
+
Create an IntegrationAsset from a row in the Aqua file
|
|
69
72
|
|
|
70
73
|
:param Optional[dict] dat: Data row from CSV file, defaults to None
|
|
71
|
-
:return: RegScale
|
|
72
|
-
:rtype: Optional[
|
|
74
|
+
:return: RegScale IntegrationAsset object or None
|
|
75
|
+
:rtype: Optional[IntegrationAsset]
|
|
73
76
|
"""
|
|
74
77
|
name = self.mapping.get_value(dat, self.image_name)
|
|
75
78
|
if not name:
|
|
76
79
|
return None
|
|
77
80
|
os = self.mapping.get_value(dat, self.OS)
|
|
78
|
-
return
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"assetOwnerId": self.config["userId"],
|
|
93
|
-
"assetType": "Other",
|
|
94
|
-
"fqdn": name if is_valid_fqdn(name) else None,
|
|
95
|
-
"systemAdministratorId": self.config["userId"],
|
|
96
|
-
"parentId": self.attributes.parent_id,
|
|
97
|
-
"parentModule": self.attributes.parent_module,
|
|
98
|
-
"extra_data": {"software_inventory": self.generate_software_inventory(name)},
|
|
99
|
-
}
|
|
81
|
+
return IntegrationAsset(
|
|
82
|
+
identifier=name,
|
|
83
|
+
name=name,
|
|
84
|
+
ip_address="0.0.0.0",
|
|
85
|
+
cpu=0,
|
|
86
|
+
ram=0,
|
|
87
|
+
status=AssetStatus.Active.value,
|
|
88
|
+
asset_type="Other",
|
|
89
|
+
asset_category="Hardware",
|
|
90
|
+
scanning_tool=self.name,
|
|
91
|
+
fqdn=name if is_valid_fqdn(name) else None,
|
|
92
|
+
operating_system=os,
|
|
93
|
+
other_tracking_number=name,
|
|
94
|
+
software_inventory=self.generate_software_inventory(name),
|
|
100
95
|
)
|
|
101
96
|
|
|
102
97
|
def generate_software_inventory(self, name: str) -> List[dict]:
|
|
@@ -137,64 +132,83 @@ class Aqua(FlatFileImporter):
|
|
|
137
132
|
:rtype: str
|
|
138
133
|
"""
|
|
139
134
|
self.logger.info(f"Unable to determine date for the '{field}' field, falling back to current date and time.")
|
|
140
|
-
return
|
|
135
|
+
return self.scan_date
|
|
136
|
+
|
|
137
|
+
def determine_first_seen(self, dat: dict) -> str:
|
|
138
|
+
"""
|
|
139
|
+
Determine the first seen date and time of the vulnerability
|
|
140
|
+
|
|
141
|
+
:param dict dat: Data row from CSV file
|
|
142
|
+
:return: The first seen date and time
|
|
143
|
+
:rtype: str
|
|
144
|
+
"""
|
|
145
|
+
first_detected = datetime_str(
|
|
146
|
+
self.mapping.get_value(dat, self.integration_mapping.load("aqua", "dateFirstDetected"))
|
|
147
|
+
)
|
|
148
|
+
ffi = datetime_str(self.mapping.get_value(dat, self.ffi)) or self.current_datetime_w_log(self.ffi)
|
|
149
|
+
if first_detected and first_detected != ffi:
|
|
150
|
+
ffi = first_detected
|
|
151
|
+
return ffi
|
|
141
152
|
|
|
142
|
-
def create_vuln(self, dat: Optional[dict] = None, **kwargs: dict) -> Optional[
|
|
153
|
+
def create_vuln(self, dat: Optional[dict] = None, **kwargs: dict) -> Optional[IntegrationFinding]:
|
|
143
154
|
"""
|
|
144
|
-
Create a
|
|
155
|
+
Create a IntegrationFinding from a row in the Aqua csv file
|
|
145
156
|
|
|
146
157
|
:param Optional[dict] dat: Data row from CSV file, defaults to None
|
|
147
158
|
:param dict **kwargs: Additional keyword arguments
|
|
148
|
-
:return: RegScale
|
|
149
|
-
:rtype: Optional[
|
|
159
|
+
:return: RegScale IntegrationFinding object or None
|
|
160
|
+
:rtype: Optional[IntegrationFinding]
|
|
150
161
|
"""
|
|
151
162
|
|
|
152
|
-
|
|
163
|
+
try:
|
|
164
|
+
hostname = self.mapping.get_value(dat, self.image_name)
|
|
153
165
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
161
|
-
title = self.mapping.get_value(dat, self.integration_mapping.load("aqua", "title")) or (
|
|
162
|
-
description[:255] if description else f"Vulnerability on {hostname}"
|
|
163
|
-
) # OLDTODO: BMC Would like the CVE here
|
|
164
|
-
|
|
165
|
-
regscale_vuln = None
|
|
166
|
-
severity = self.determine_cvss_severity(dat)
|
|
167
|
-
config = self.attributes.app.config
|
|
168
|
-
asset_match = [asset for asset in self.data["assets"] if asset.name == hostname]
|
|
169
|
-
asset = asset_match[0] if asset_match else None
|
|
170
|
-
if asset_match and self.validate(ix=kwargs.get("index"), dat=dat):
|
|
171
|
-
regscale_vuln = Vulnerability(
|
|
172
|
-
id=0,
|
|
173
|
-
scanId=0,
|
|
174
|
-
parentId=asset.id,
|
|
175
|
-
parentModule="assets",
|
|
176
|
-
ipAddress="0.0.0.0",
|
|
177
|
-
lastSeen=datetime_str(self.mapping.get_value(dat, self.last_image_scan))
|
|
178
|
-
or self.current_datetime_w_log(self.last_image_scan),
|
|
179
|
-
firstSeen=datetime_str(self.mapping.get_value(dat, self.ffi)) or self.current_datetime_w_log(self.ffi),
|
|
180
|
-
daysOpen=None,
|
|
181
|
-
dns=hostname,
|
|
182
|
-
mitigated=None,
|
|
183
|
-
operatingSystem=asset.operatingSystem,
|
|
184
|
-
severity=severity,
|
|
185
|
-
plugInName=description,
|
|
186
|
-
cve=self.mapping.get_value(dat, self.vuln_title),
|
|
187
|
-
cvsSv3BaseScore=self.mapping.get_value(dat, self.vendor_cvss_v3_score, 0.0),
|
|
188
|
-
tenantsId=0,
|
|
189
|
-
title=title,
|
|
190
|
-
description=description,
|
|
191
|
-
plugInText=self.mapping.get_value(dat, self.vuln_title),
|
|
192
|
-
createdById=config["userId"],
|
|
193
|
-
lastUpdatedById=config["userId"],
|
|
194
|
-
dateCreated=get_current_datetime(),
|
|
195
|
-
extra_data={"solution": remediation},
|
|
166
|
+
# Custom Integration Mapping fields
|
|
167
|
+
remediation = self.mapping.get_value(dat, self.integration_mapping.load("aqua", "remediation")) or (
|
|
168
|
+
self.mapping.get_value(dat, self.description) or "Upgrade affected package"
|
|
169
|
+
) # OLDTODO: BMC would like this to use "Solution" column
|
|
170
|
+
description = self.mapping.get_value(dat, self.integration_mapping.load("aqua", "description")) or (
|
|
171
|
+
self.mapping.get_value(dat, self.description)
|
|
196
172
|
)
|
|
197
|
-
|
|
173
|
+
title = self.mapping.get_value(dat, self.integration_mapping.load("aqua", "title")) or (
|
|
174
|
+
description[:255] if description else f"Vulnerability on {hostname}"
|
|
175
|
+
) # OLDTODO: BMC Would like the CVE here
|
|
176
|
+
|
|
177
|
+
cvss3_score = self.mapping.get_value(dat, self.vendor_cvss_v3_score) or 0.0
|
|
178
|
+
cvss_v2_score = self.mapping.get_value(dat, self.vendor_cvss_v2_score) or 0.0
|
|
179
|
+
|
|
180
|
+
regscale_finding = None
|
|
181
|
+
severity = self.determine_cvss_severity(dat)
|
|
182
|
+
# Create IntegrationFinding if we have valid data and asset match
|
|
183
|
+
|
|
184
|
+
if dat:
|
|
185
|
+
return IntegrationFinding(
|
|
186
|
+
control_labels=[], # Add an empty list for control_labels
|
|
187
|
+
title=title,
|
|
188
|
+
description=description,
|
|
189
|
+
ip_address="0.0.0.0",
|
|
190
|
+
cve=self.mapping.get_value(dat, self.vuln_title, "").upper(),
|
|
191
|
+
severity=severity,
|
|
192
|
+
asset_identifier=hostname,
|
|
193
|
+
plugin_name=description,
|
|
194
|
+
plugin_id=self.mapping.get_value(dat, self.vuln_title),
|
|
195
|
+
cvss_score=cvss_v2_score or 0.0,
|
|
196
|
+
cvss_v3_score=cvss3_score or 0.0,
|
|
197
|
+
cvss_v2_score=cvss_v2_score or 0.0,
|
|
198
|
+
plugin_text=self.mapping.get_value(dat, self.vuln_title),
|
|
199
|
+
remediation=remediation,
|
|
200
|
+
category="Hardware",
|
|
201
|
+
status=IssueStatus.Open,
|
|
202
|
+
first_seen=self.determine_first_seen(dat),
|
|
203
|
+
last_seen=datetime_str(self.mapping.get_value(dat, self.last_image_scan))
|
|
204
|
+
or self.current_datetime_w_log(self.last_image_scan),
|
|
205
|
+
vulnerability_type="Vulnerability Scan",
|
|
206
|
+
baseline=f"{self.name} Host",
|
|
207
|
+
)
|
|
208
|
+
return regscale_finding
|
|
209
|
+
except AttributeError as e:
|
|
210
|
+
self.logger.error(f"Error creating finding: {e}")
|
|
211
|
+
return None
|
|
198
212
|
|
|
199
213
|
def determine_cvss_severity(self, dat: dict) -> str:
|
|
200
214
|
"""
|
|
@@ -217,7 +231,7 @@ class Aqua(FlatFileImporter):
|
|
|
217
231
|
severity = self.mapping.get_value(dat, key).lower()
|
|
218
232
|
break
|
|
219
233
|
|
|
220
|
-
return severity
|
|
234
|
+
return self.determine_severity(severity)
|
|
221
235
|
|
|
222
236
|
def validate(self, ix: Optional[int], dat: dict) -> bool:
|
|
223
237
|
"""
|
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "CISA Catalog of Known Exploited Vulnerabilities",
|
|
3
|
-
"catalogVersion": "2025.
|
|
4
|
-
"dateReleased": "2025-
|
|
5
|
-
"count":
|
|
3
|
+
"catalogVersion": "2025.08.05",
|
|
4
|
+
"dateReleased": "2025-08-05T18:03:16.7522Z",
|
|
5
|
+
"count": 1394,
|
|
6
6
|
"vulnerabilities": [
|
|
7
|
+
{
|
|
8
|
+
"cveID": "CVE-2020-25078",
|
|
9
|
+
"vendorProject": "D-Link",
|
|
10
|
+
"product": "DCS-2530L and DCS-2670L Devices",
|
|
11
|
+
"vulnerabilityName": "D-Link DCS-2530L and DCS-2670L Devices Unspecified Vulnerability",
|
|
12
|
+
"dateAdded": "2025-08-05",
|
|
13
|
+
"shortDescription": "D-Link DCS-2530L and DCS-2670L devices contains an unspecified vulnerability that could allow for remote administrator password disclosure. The impacted products could be end-of-life (EoL) and\/or end-of-service (EoS). Users should discontinue product utilization.",
|
|
14
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
15
|
+
"dueDate": "2025-08-26",
|
|
16
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
17
|
+
"notes": "https:\/\/support.dlink.com\/productinfo.aspx?m=DCS-2530L ; https:\/\/supportannouncement.us.dlink.com\/announcement\/publication.aspx?name=SAP10180 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-25078",
|
|
18
|
+
"cwes": []
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"cveID": "CVE-2020-25079",
|
|
22
|
+
"vendorProject": "D-Link",
|
|
23
|
+
"product": "DCS-2530L and DCS-2670L Devices",
|
|
24
|
+
"vulnerabilityName": "D-Link DCS-2530L and DCS-2670L Command Injection Vulnerability",
|
|
25
|
+
"dateAdded": "2025-08-05",
|
|
26
|
+
"shortDescription": "D-Link DCS-2530L and DCS-2670L devices contains a command injection vulnerability in the cgi-bin\/ddns_enc.cgi. The impacted products could be end-of-life (EoL) and\/or end-of-service (EoS). Users should discontinue product utilization.",
|
|
27
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
28
|
+
"dueDate": "2025-08-26",
|
|
29
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
30
|
+
"notes": "https:\/\/support.dlink.com\/productinfo.aspx?m=DCS-2530L ; https:\/\/supportannouncement.us.dlink.com\/announcement\/publication.aspx?name=SAP10180 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2020-25079",
|
|
31
|
+
"cwes": [
|
|
32
|
+
"CWE-77"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"cveID": "CVE-2022-40799",
|
|
37
|
+
"vendorProject": "D-Link",
|
|
38
|
+
"product": "DNR-322L",
|
|
39
|
+
"vulnerabilityName": "D-Link DNR-322L Download of Code Without Integrity Check Vulnerability",
|
|
40
|
+
"dateAdded": "2025-08-05",
|
|
41
|
+
"shortDescription": "D-Link DNR-322L contains a download of code without integrity check vulnerability that could allow an authenticated attacker to execute OS level commands on the device. The impacted products could be end-of-life (EoL) and\/or end-of-service (EoS). Users should discontinue product utilization.",
|
|
42
|
+
"requiredAction": "Apply mitigations per vendor instructions, follow applicable BOD 22-01 guidance for cloud services, or discontinue use of the product if mitigations are unavailable.",
|
|
43
|
+
"dueDate": "2025-08-26",
|
|
44
|
+
"knownRansomwareCampaignUse": "Unknown",
|
|
45
|
+
"notes": "https:\/\/www.dlink.com\/uk\/en\/products\/dnr-322l-cloud-network-video-recorder ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2022-40799",
|
|
46
|
+
"cwes": [
|
|
47
|
+
"CWE-494"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
7
50
|
{
|
|
8
51
|
"cveID": "CVE-2023-2533",
|
|
9
52
|
"vendorProject": "PaperCut",
|
|
@@ -148,7 +191,7 @@
|
|
|
148
191
|
"shortDescription": "Microsoft SharePoint Server on-premises contains a deserialization of untrusted data vulnerability that could allow an unauthorized attacker to execute code over a network. This vulnerability could be chained with CVE-2025-53771. CVE-2025-53770 is a patch bypass for CVE-2025-49704, and the updates for CVE-2025-53770 include more robust protection than those for CVE-2025-49704.",
|
|
149
192
|
"requiredAction": "Disconnect public-facing versions of SharePoint Server that have reached their end-of-life (EOL) or end-of-service (EOS) to include SharePoint Server 2013 and earlier versions. For supported versions, please follow the mitigations according to CISA (URL listed below in Notes) and vendor instructions (URL listed below in Notes). Adhere to the applicable BOD 22-01 guidance for cloud services or discontinue use of the product if mitigations are not available.",
|
|
150
193
|
"dueDate": "2025-07-21",
|
|
151
|
-
"knownRansomwareCampaignUse": "
|
|
194
|
+
"knownRansomwareCampaignUse": "Known",
|
|
152
195
|
"notes": "CISA Mitigation Instructions: https:\/\/www.cisa.gov\/news-events\/alerts\/2025\/07\/20\/microsoft-releases-guidance-exploitation-sharepoint-vulnerability-cve-2025-53770; https:\/\/www.microsoft.com\/en-us\/security\/blog\/2025\/07\/22\/disrupting-active-exploitation-of-on-premises-sharepoint-vulnerabilities\/ ; https:\/\/msrc.microsoft.com\/update-guide\/vulnerability\/CVE-2025-53770 ; https:\/\/nvd.nist.gov\/vuln\/detail\/CVE-2025-53770",
|
|
153
196
|
"cwes": [
|
|
154
197
|
"CWE-502"
|
|
@@ -3,13 +3,14 @@ Integration model to import data from Defender .csv export
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
|
-
from typing import Optional
|
|
6
|
+
from typing import Iterator, List, Optional
|
|
7
7
|
|
|
8
8
|
from regscale.core.app.application import Application
|
|
9
9
|
from regscale.core.app.logz import create_logger
|
|
10
|
-
from regscale.core.app.utils.app_utils import
|
|
10
|
+
from regscale.core.app.utils.app_utils import is_valid_fqdn
|
|
11
11
|
from regscale.core.utils.date import datetime_obj, datetime_str
|
|
12
|
-
from regscale.
|
|
12
|
+
from regscale.integrations.scanner_integration import IntegrationAsset, IntegrationFinding
|
|
13
|
+
from regscale.models import Asset, ImportValidater, IssueSeverity, IssueStatus
|
|
13
14
|
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
14
15
|
|
|
15
16
|
|
|
@@ -60,7 +61,7 @@ class DefenderImport(FlatFileImporter):
|
|
|
60
61
|
|
|
61
62
|
return datetime_str(dt_object, self.dt_format)
|
|
62
63
|
|
|
63
|
-
def create_asset(self, dat: Optional[dict] = None) ->
|
|
64
|
+
def create_asset(self, dat: Optional[dict] = None) -> IntegrationAsset:
|
|
64
65
|
"""
|
|
65
66
|
Create an asset from a row in the Snyk file
|
|
66
67
|
|
|
@@ -72,72 +73,76 @@ class DefenderImport(FlatFileImporter):
|
|
|
72
73
|
os = Asset.find_os(additional_data.get("imageDetails", {}).get("osDetails", ""))
|
|
73
74
|
name = additional_data.get("repositoryName", "")
|
|
74
75
|
valid_name = is_valid_fqdn(name)
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"scanningTool": self.name,
|
|
86
|
-
"assetOwnerId": self.config["userId"],
|
|
87
|
-
"assetType": "Other",
|
|
88
|
-
"fqdn": name if valid_name else None,
|
|
89
|
-
"systemAdministratorId": self.config["userId"],
|
|
90
|
-
"parentId": self.attributes.parent_id,
|
|
91
|
-
"parentModule": self.attributes.parent_module,
|
|
92
|
-
"operatingSystem": os,
|
|
93
|
-
}
|
|
76
|
+
return IntegrationAsset(
|
|
77
|
+
identifier=name,
|
|
78
|
+
name=name,
|
|
79
|
+
ip_address="0.0.0.0",
|
|
80
|
+
status="Active (On Network)",
|
|
81
|
+
asset_category="Software",
|
|
82
|
+
scanning_tool=self.name,
|
|
83
|
+
asset_type="Other",
|
|
84
|
+
fqdn=name if valid_name else None,
|
|
85
|
+
operating_system=os,
|
|
94
86
|
)
|
|
95
87
|
|
|
96
|
-
def create_vuln(self, dat: Optional[dict] = None, **kwargs: dict) ->
|
|
88
|
+
def create_vuln(self, dat: Optional[dict] = None, **kwargs: dict) -> Iterator[IntegrationFinding]:
|
|
97
89
|
"""
|
|
98
90
|
Create a vulnerability from a row in the Snyk csv file
|
|
99
91
|
|
|
100
92
|
:param Optional[dict] dat: Data row from CSV file, defaults to None
|
|
101
93
|
:param dict **kwargs: Additional keyword arguments
|
|
102
|
-
:return: RegScale
|
|
103
|
-
:rtype:
|
|
94
|
+
:return: RegScale Iterator of findings
|
|
95
|
+
:rtype: Iterator[IntegrationFinding]
|
|
104
96
|
"""
|
|
105
|
-
|
|
106
|
-
severity = self.mapping.get_value(dat, "SEVERITY", "").lower()
|
|
97
|
+
regscale_findings: List[IntegrationFinding] = []
|
|
98
|
+
severity = self.determine_severity(self.mapping.get_value(dat, "SEVERITY", "").lower())
|
|
107
99
|
additional_data = json.loads(self.mapping.get_value(dat, "ADDITIONALDATA", {}))
|
|
108
100
|
hostname = additional_data.get("repositoryName", "")
|
|
109
101
|
description = self.mapping.get_value(dat, self.vuln_title)
|
|
110
102
|
solution = self.mapping.get_value(dat, self.vuln_id)
|
|
111
|
-
config = self.attributes.app.config
|
|
112
|
-
asset_match = [asset for asset in self.data["assets"] if asset.name == hostname]
|
|
113
|
-
asset = asset_match[0] if asset_match else None
|
|
114
103
|
cves = [cve.get("title", "") for cve in additional_data.get("cve", [])]
|
|
115
104
|
cvss_v3_score = float(additional_data.get("cvssV30Score", 0))
|
|
116
|
-
if dat
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
105
|
+
if dat:
|
|
106
|
+
if cves and isinstance(cves, list):
|
|
107
|
+
for cve in cves:
|
|
108
|
+
regscale_finding = IntegrationFinding(
|
|
109
|
+
title=f"{description} on asset {hostname}",
|
|
110
|
+
asset_identifier=hostname,
|
|
111
|
+
description=description,
|
|
112
|
+
severity=severity,
|
|
113
|
+
status=IssueStatus.Open.value,
|
|
114
|
+
cvss_v3_score=cvss_v3_score,
|
|
115
|
+
cvss_v3_base_score=cvss_v3_score,
|
|
116
|
+
plugin_name=description,
|
|
117
|
+
plugin_text=self.mapping.get_value(dat, self.vuln_title),
|
|
118
|
+
cve=cve,
|
|
119
|
+
recommendation_for_mitigation=solution,
|
|
120
|
+
first_seen=self.determine_first_seen(dat),
|
|
121
|
+
last_seen=self.scan_date,
|
|
122
|
+
scan_date=self.scan_date,
|
|
123
|
+
category="Software",
|
|
124
|
+
control_labels=[],
|
|
125
|
+
)
|
|
126
|
+
regscale_findings.append(regscale_finding)
|
|
127
|
+
else:
|
|
128
|
+
regscale_finding = IntegrationFinding(
|
|
129
|
+
title=f"{description} on asset {hostname}",
|
|
130
|
+
description=description,
|
|
131
|
+
severity=severity,
|
|
132
|
+
status=IssueStatus.Open.value,
|
|
133
|
+
cvss_v3_score=cvss_v3_score,
|
|
134
|
+
cvss_v3_base_score=cvss_v3_score,
|
|
135
|
+
plugin_name=description,
|
|
136
|
+
plugin_text=self.mapping.get_value(dat, self.vuln_title),
|
|
137
|
+
asset_identifier=hostname,
|
|
138
|
+
cve=self.mapping.get_value(dat, self.vuln_title),
|
|
139
|
+
recommendation_for_mitigation=solution,
|
|
140
|
+
first_seen=self.determine_first_seen(dat),
|
|
141
|
+
last_seen=self.scan_date,
|
|
142
|
+
scan_date=self.scan_date,
|
|
143
|
+
category="Software",
|
|
144
|
+
control_labels=[],
|
|
145
|
+
)
|
|
146
|
+
regscale_findings.append(regscale_finding)
|
|
147
|
+
|
|
148
|
+
yield from regscale_findings
|