regscale-cli 6.16.1.0__py3-none-any.whl → 6.16.3.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/__init__.py +1 -1
- regscale/core/app/internal/login.py +1 -1
- regscale/core/app/internal/poam_editor.py +1 -1
- regscale/core/app/utils/api_handler.py +4 -11
- regscale/integrations/commercial/__init__.py +2 -2
- regscale/integrations/commercial/ad.py +1 -1
- regscale/integrations/commercial/crowdstrike.py +0 -1
- regscale/integrations/commercial/grype/__init__.py +3 -0
- regscale/integrations/commercial/grype/commands.py +72 -0
- regscale/integrations/commercial/grype/scanner.py +390 -0
- regscale/integrations/commercial/import_all/import_all_cmd.py +2 -2
- regscale/integrations/commercial/opentext/__init__.py +6 -0
- regscale/integrations/commercial/opentext/commands.py +77 -0
- regscale/integrations/commercial/opentext/scanner.py +449 -85
- regscale/integrations/commercial/qualys.py +50 -61
- regscale/integrations/commercial/servicenow.py +1 -0
- regscale/integrations/commercial/snyk.py +2 -2
- regscale/integrations/commercial/synqly/ticketing.py +29 -0
- regscale/integrations/commercial/trivy/__init__.py +5 -0
- regscale/integrations/commercial/trivy/commands.py +74 -0
- regscale/integrations/commercial/trivy/scanner.py +276 -0
- regscale/integrations/commercial/veracode.py +1 -1
- regscale/integrations/commercial/wizv2/utils.py +1 -1
- regscale/integrations/jsonl_scanner_integration.py +869 -0
- regscale/integrations/public/fedramp/fedramp_common.py +4 -4
- regscale/integrations/public/fedramp/inventory_items.py +3 -3
- regscale/integrations/scanner_integration.py +225 -59
- regscale/models/integration_models/cisa_kev_data.json +65 -7
- regscale/models/integration_models/{flat_file_importer.py → flat_file_importer/__init__.py} +29 -8
- regscale/models/integration_models/snyk.py +141 -15
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/tenable_models/integration.py +42 -7
- regscale/models/integration_models/veracode.py +91 -48
- regscale/models/regscale_models/regscale_model.py +1 -1
- regscale/models/regscale_models/user.py +3 -4
- regscale/models/regscale_models/vulnerability.py +21 -0
- regscale/utils/version.py +3 -5
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/METADATA +3 -3
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/RECORD +43 -38
- regscale/integrations/commercial/grype.py +0 -165
- regscale/integrations/commercial/opentext/click.py +0 -99
- regscale/integrations/commercial/trivy.py +0 -162
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.16.1.0.dist-info → regscale_cli-6.16.3.0.dist-info}/top_level.txt +0 -0
|
@@ -3,6 +3,7 @@ This module contains the Tenable SC Integration class that is responsible for fe
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
|
+
import re
|
|
6
7
|
from typing import Any, Iterator, List, Optional, Tuple
|
|
7
8
|
|
|
8
9
|
from regscale.core.app.utils.app_utils import epoch_to_datetime
|
|
@@ -114,14 +115,34 @@ class SCIntegration(ScannerIntegration):
|
|
|
114
115
|
|
|
115
116
|
validated_match = integration_mapping.field_map_validation(obj=vuln, model_type="asset")
|
|
116
117
|
asset_identifier = validated_match or vuln.dnsName or vuln.dns or vuln.ip
|
|
117
|
-
|
|
118
|
+
cvss_scores = self.get_cvss_scores(vuln)
|
|
118
119
|
severity = self.finding_severity_map.get(vuln.severity.name, regscale_models.IssueSeverity.Low)
|
|
119
120
|
|
|
121
|
+
installed_versions_str = ""
|
|
122
|
+
fixed_versions_str = ""
|
|
123
|
+
package_path_str = ""
|
|
124
|
+
|
|
125
|
+
if "Installed package" in vuln.pluginText:
|
|
126
|
+
installed_versions = re.findall(r"Installed package\s*:\s*(\S+)", vuln.pluginText)
|
|
127
|
+
installed_versions_str = ", ".join(installed_versions)
|
|
128
|
+
if "Fixed package" in vuln.pluginText:
|
|
129
|
+
fixed_versions = re.findall(r"Fixed package\s*:\s*(\S+)", vuln.pluginText)
|
|
130
|
+
fixed_versions_str = ", ".join(fixed_versions)
|
|
131
|
+
if "Path" in vuln.pluginText:
|
|
132
|
+
package_path = re.findall(r"Path\s*:\s*(\S+)", vuln.pluginText)
|
|
133
|
+
package_path_str = ", ".join(package_path)
|
|
134
|
+
if "Installed version" in vuln.pluginText:
|
|
135
|
+
installed_versions = re.findall(r"Installed version\s*:\s*(.+)", vuln.pluginText)
|
|
136
|
+
installed_versions_str = ", ".join(installed_versions)
|
|
137
|
+
if "Fixed version" in vuln.pluginText:
|
|
138
|
+
fixed_versions = re.findall(r"Fixed version\s*:\s*(.+)", vuln.pluginText)
|
|
139
|
+
fixed_versions_str = ", ".join(fixed_versions)
|
|
140
|
+
|
|
120
141
|
return IntegrationFinding(
|
|
121
142
|
control_labels=[], # Add an empty list for control_labels
|
|
122
143
|
category="Tenable SC Vulnerability", # Add a default category
|
|
123
144
|
dns=vuln.dnsName,
|
|
124
|
-
title=getter("title") or (vuln.synopsis or vuln.pluginName),
|
|
145
|
+
title=getter("title") or f"{cve}: {vuln.synopsis}" if cve else (vuln.synopsis or vuln.pluginName),
|
|
125
146
|
description=getter("description") or (vuln.description or vuln.pluginInfo),
|
|
126
147
|
severity=severity,
|
|
127
148
|
status=regscale_models.IssueStatus.Open, # Findings of > Low are considered as FAIL
|
|
@@ -133,8 +154,11 @@ class SCIntegration(ScannerIntegration):
|
|
|
133
154
|
date_last_updated=epoch_to_datetime(vuln.lastSeen),
|
|
134
155
|
recommendation_for_mitigation=vuln.solution,
|
|
135
156
|
cve=cve,
|
|
136
|
-
cvss_v3_score=
|
|
137
|
-
cvss_score=
|
|
157
|
+
cvss_v3_score=cvss_scores.get("cvss_v3_base_score", 0.0),
|
|
158
|
+
cvss_score=cvss_scores.get("cvss_v3_base_score", 0.0),
|
|
159
|
+
cvss_v3_vector=vuln.cvssV3Vector,
|
|
160
|
+
cvss_v2_score=cvss_scores.get("cvss_v2_base_score", 0.0),
|
|
161
|
+
cvss_v2_vector=vuln.cvssVector,
|
|
138
162
|
vpr_score=float(vuln.vprScore) if vuln.vprScore else None,
|
|
139
163
|
comments=vuln.cvssV3Vector,
|
|
140
164
|
plugin_id=vuln.pluginID,
|
|
@@ -144,9 +168,16 @@ class SCIntegration(ScannerIntegration):
|
|
|
144
168
|
basis_for_adjustment="Tenable SC import",
|
|
145
169
|
vulnerability_type="Tenable SC Vulnerability",
|
|
146
170
|
vulnerable_asset=vuln.dnsName,
|
|
171
|
+
build_version="",
|
|
172
|
+
affected_os=vuln.operatingSystem,
|
|
173
|
+
affected_packages=vuln.pluginName,
|
|
174
|
+
package_path=package_path_str,
|
|
175
|
+
installed_versions=installed_versions_str,
|
|
176
|
+
fixed_versions=fixed_versions_str,
|
|
177
|
+
fix_status="",
|
|
147
178
|
)
|
|
148
179
|
|
|
149
|
-
def
|
|
180
|
+
def get_cvss_scores(self, vuln: TenableAsset) -> dict:
|
|
150
181
|
"""
|
|
151
182
|
Returns the CVSS score for the finding
|
|
152
183
|
|
|
@@ -154,10 +185,14 @@ class SCIntegration(ScannerIntegration):
|
|
|
154
185
|
:return: The CVSS score
|
|
155
186
|
:rtype: float
|
|
156
187
|
"""
|
|
188
|
+
res = {}
|
|
157
189
|
try:
|
|
158
|
-
res = float(vuln.cvssV3BaseScore) if vuln.cvssV3BaseScore else 0.0
|
|
190
|
+
res["cvss_v3_base_score"] = float(vuln.cvssV3BaseScore) if vuln.cvssV3BaseScore else 0.0
|
|
191
|
+
res["cvss_v2_base_score"] = float(vuln.baseScore) if vuln.baseScore else 0.0
|
|
159
192
|
except (ValueError, TypeError):
|
|
160
|
-
res = 0.0
|
|
193
|
+
res["cvss_v3_base_score"] = 0.0
|
|
194
|
+
res["cvss_v2_base_score"] = 0.0
|
|
195
|
+
|
|
161
196
|
return res
|
|
162
197
|
|
|
163
198
|
def to_integration_asset(self, asset: TenableAsset, **kwargs: dict) -> IntegrationAsset:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
from typing import List, Optional
|
|
1
|
+
from typing import List, Optional, Union
|
|
2
2
|
|
|
3
3
|
from regscale.core.app.logz import create_logger
|
|
4
4
|
from regscale.core.app.utils.app_utils import get_current_datetime
|
|
5
|
-
from regscale.
|
|
5
|
+
from regscale.integrations.scanner_integration import IntegrationFinding
|
|
6
|
+
from regscale.models import Asset, Vulnerability, ImportValidater, IssueStatus
|
|
6
7
|
from regscale.models.integration_models.flat_file_importer import FlatFileImporter
|
|
7
8
|
|
|
8
9
|
APP_NAME = "@app_name"
|
|
@@ -17,26 +18,34 @@ class Veracode(FlatFileImporter):
|
|
|
17
18
|
self.vuln_title = "PROBLEM_TITLE"
|
|
18
19
|
self.fmt = "%Y-%m-%d"
|
|
19
20
|
self.dt_format = "%Y-%m-%d %H:%M:%S"
|
|
20
|
-
|
|
21
|
+
xlsx_headers = [
|
|
21
22
|
"Source",
|
|
22
23
|
]
|
|
23
24
|
xml_headers = [
|
|
24
25
|
"app_name",
|
|
25
26
|
]
|
|
27
|
+
json_headers = [
|
|
28
|
+
"findings",
|
|
29
|
+
"project_name",
|
|
30
|
+
]
|
|
26
31
|
self.mapping_file = kwargs.get("mappings_path")
|
|
27
32
|
self.disable_mapping = kwargs.get("disable_mapping")
|
|
28
33
|
file_type = kwargs.get("file_type")
|
|
29
|
-
|
|
34
|
+
xml_tag = None
|
|
35
|
+
if "xml" in file_type:
|
|
30
36
|
self.required_headers = xml_headers
|
|
31
37
|
xml_tag = "detailedreport"
|
|
38
|
+
elif "xlsx" in file_type:
|
|
39
|
+
self.required_headers = xlsx_headers
|
|
32
40
|
else:
|
|
33
|
-
self.required_headers =
|
|
34
|
-
xml_tag = None
|
|
41
|
+
self.required_headers = json_headers
|
|
35
42
|
self.validater = ImportValidater(
|
|
36
43
|
self.required_headers, kwargs.get("file_path"), self.mapping_file, self.disable_mapping, xml_tag=xml_tag
|
|
37
44
|
)
|
|
38
45
|
self.headers = self.validater.parsed_headers
|
|
39
46
|
self.mapping = self.validater.mapping
|
|
47
|
+
if file_type == ".json":
|
|
48
|
+
self.asset_identifier = self.mapping.get_value(self.validater.data, "project_name", "")
|
|
40
49
|
super().__init__(
|
|
41
50
|
logger=logger,
|
|
42
51
|
headers=self.headers,
|
|
@@ -57,10 +66,14 @@ class Veracode(FlatFileImporter):
|
|
|
57
66
|
version = None
|
|
58
67
|
# Veracode is a Web Application Security Scanner, so these will be software assets, scanning a
|
|
59
68
|
# single web application
|
|
60
|
-
if "
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
if "xml" in self.attributes.file_type:
|
|
70
|
+
detailed_report_data = dat.get("detailedreport", {})
|
|
71
|
+
name = detailed_report_data.get(APP_NAME, "")
|
|
72
|
+
account_id = detailed_report_data.get(ACCOUNT_ID, "")
|
|
73
|
+
version = detailed_report_data.get(VERSION, "")
|
|
74
|
+
elif "json" in self.attributes.file_type:
|
|
75
|
+
name = self.mapping.get_value(dat, "project_name", "")
|
|
76
|
+
account_id = self.asset_identifier
|
|
64
77
|
else:
|
|
65
78
|
name = self.mapping.get_value(dat, "Source", "")
|
|
66
79
|
account_id = str(self.mapping.get_value(dat, "ID", ""))
|
|
@@ -88,7 +101,7 @@ class Veracode(FlatFileImporter):
|
|
|
88
101
|
)
|
|
89
102
|
return [asset]
|
|
90
103
|
|
|
91
|
-
def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> List[Vulnerability]:
|
|
104
|
+
def create_vuln(self, dat: Optional[dict] = None, **kwargs) -> Union[List[Vulnerability], List[IntegrationFinding]]:
|
|
92
105
|
"""
|
|
93
106
|
Create a RegScale vulnerability from a vulnerability in the Veracode export file
|
|
94
107
|
|
|
@@ -96,30 +109,62 @@ class Veracode(FlatFileImporter):
|
|
|
96
109
|
:return: List of RegScale Vulnerability objects
|
|
97
110
|
:rtype: List[Vulnerability]
|
|
98
111
|
"""
|
|
99
|
-
import_type = "xml" if isinstance(dat, str) else "csv"
|
|
100
112
|
# Veracode is a Web Application Security Scanner, so these will be software assets,
|
|
101
113
|
# scanning a single web application
|
|
102
|
-
if
|
|
103
|
-
|
|
104
|
-
|
|
114
|
+
if "xml" in self.attributes.file_type:
|
|
115
|
+
detailed_report_data = dat.get("detailedreport", {})
|
|
116
|
+
name = detailed_report_data.get(APP_NAME, "")
|
|
117
|
+
all_sev_data = detailed_report_data.get("severity", [])
|
|
105
118
|
severity = self.severity_info(all_sev_data)[0] if all_sev_data else "low"
|
|
106
119
|
if severity_data := self.severity_info(all_sev_data):
|
|
107
|
-
if isinstance(severity_data,
|
|
120
|
+
if isinstance(severity_data, tuple) and len(severity_data) >= 2:
|
|
108
121
|
cwes = [
|
|
109
|
-
f"{c.get('cweid')} {c.get('cwename')}" for c in severity_data[1].get("cwe", [])
|
|
122
|
+
f"{c.get('@cweid')} {c.get('@cwename')}" for c in severity_data[1].get("cwe", [])
|
|
110
123
|
] # Multiple cwes per asset in official XML
|
|
111
124
|
else:
|
|
112
125
|
cwes = []
|
|
113
|
-
|
|
126
|
+
elif "xlsx" in self.attributes.file_type:
|
|
114
127
|
name = self.mapping.get_value(dat, "Source", "")
|
|
115
128
|
severity = self.mapping.get_value(dat, "Sev", "").lower()
|
|
116
129
|
cwes = [self.mapping.get_value(dat, "CWE ID & Name", [])] # Coalfire should flatten data for asset -> cwes
|
|
130
|
+
elif "json" in self.attributes.file_type:
|
|
131
|
+
return self._parse_json_findings(**kwargs)
|
|
117
132
|
|
|
118
|
-
return self.
|
|
133
|
+
return self.process_vuln_data(name, cwes, severity)
|
|
119
134
|
|
|
120
|
-
def
|
|
135
|
+
def _parse_json_findings(self, **kwargs) -> List[IntegrationFinding]:
|
|
121
136
|
"""
|
|
122
|
-
|
|
137
|
+
Parse the JSON findings from the Veracode .json export file
|
|
138
|
+
|
|
139
|
+
:return: List of IntegrationFinding objects
|
|
140
|
+
:rtype: List[IntegrationFinding]
|
|
141
|
+
"""
|
|
142
|
+
findings: List[IntegrationFinding] = []
|
|
143
|
+
for vuln in self.mapping.get_value(kwargs.get("data", self.validater.data), "findings", []):
|
|
144
|
+
if title := vuln.get("issue_type", vuln.get("title", "")):
|
|
145
|
+
findings.append(
|
|
146
|
+
IntegrationFinding(
|
|
147
|
+
title=title,
|
|
148
|
+
description=vuln.get("display_text", "No description available"),
|
|
149
|
+
severity=self.finding_severity_map.get(self.hit_mapping().get(vuln.get("severity", 0)), "Low"),
|
|
150
|
+
status=IssueStatus.Open,
|
|
151
|
+
plugin_name=vuln.get(title, self.name),
|
|
152
|
+
plugin_id=vuln.get("cwe_id", vuln.get("issue_id", "")),
|
|
153
|
+
plugin_text=vuln.get("issue_type", ""),
|
|
154
|
+
asset_identifier=self.asset_identifier,
|
|
155
|
+
first_seen=self.scan_date,
|
|
156
|
+
last_seen=self.scan_date,
|
|
157
|
+
scan_date=self.scan_date,
|
|
158
|
+
category="Software",
|
|
159
|
+
is_cwe=True,
|
|
160
|
+
control_labels=[],
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
return findings
|
|
164
|
+
|
|
165
|
+
def process_vuln_data(self, hostname: str, cwes: List[str], severity: str) -> List[Vulnerability]:
|
|
166
|
+
"""
|
|
167
|
+
Process the vulnerability data to create a list of vulnerabilities
|
|
123
168
|
|
|
124
169
|
:param str hostname: The hostname
|
|
125
170
|
:param List[str] cwes: The CWEs
|
|
@@ -137,7 +182,7 @@ class Veracode(FlatFileImporter):
|
|
|
137
182
|
|
|
138
183
|
def create_vulnerability_object(
|
|
139
184
|
self, asset: Asset, hostname: str, cwe: str, severity: str, description: str
|
|
140
|
-
) ->
|
|
185
|
+
) -> IntegrationFinding:
|
|
141
186
|
"""
|
|
142
187
|
Create a vulnerability from a row in the Veracode file
|
|
143
188
|
|
|
@@ -146,33 +191,25 @@ class Veracode(FlatFileImporter):
|
|
|
146
191
|
:param str cwe: The CWE
|
|
147
192
|
:param str severity: The severity
|
|
148
193
|
:param str description: The description
|
|
149
|
-
:return: The
|
|
150
|
-
:rtype:
|
|
151
|
-
"""
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return Vulnerability( # type: ignore
|
|
155
|
-
id=0,
|
|
156
|
-
scanId=0,
|
|
157
|
-
parentId=asset.id,
|
|
158
|
-
parentModule="assets",
|
|
159
|
-
ipAddress="0.0.0.0",
|
|
160
|
-
lastSeen=get_current_datetime(), # No timestamp on Veracode
|
|
161
|
-
firstSeen=get_current_datetime(), # No timestamp on Veracode
|
|
162
|
-
daysOpen=None,
|
|
163
|
-
dns=hostname,
|
|
164
|
-
mitigated=None,
|
|
165
|
-
operatingSystem=asset.operatingSystem,
|
|
166
|
-
severity=severity,
|
|
167
|
-
plugInName=cwe,
|
|
168
|
-
cve="",
|
|
169
|
-
tenantsId=0,
|
|
194
|
+
:return: The equivalent IntegrationFinding object
|
|
195
|
+
:rtype: IntegrationFinding
|
|
196
|
+
"""
|
|
197
|
+
return IntegrationFinding(
|
|
170
198
|
title=f"{cwe} on asset {asset.name}",
|
|
171
|
-
description=
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
199
|
+
description=description,
|
|
200
|
+
status=IssueStatus.Open,
|
|
201
|
+
dns=hostname,
|
|
202
|
+
first_seen=self.scan_date,
|
|
203
|
+
last_seen=self.scan_date,
|
|
204
|
+
scan_date=self.scan_date,
|
|
205
|
+
category="Software",
|
|
206
|
+
is_cwe=True,
|
|
207
|
+
severity=self.finding_severity_map.get(self.hit_mapping().get(severity.title(), "Low")),
|
|
208
|
+
plugin_name=cwe,
|
|
209
|
+
plugin_id=cwe,
|
|
210
|
+
plugin_text=description,
|
|
211
|
+
asset_identifier=hostname,
|
|
212
|
+
control_labels=[],
|
|
176
213
|
)
|
|
177
214
|
|
|
178
215
|
def get_asset(self, hostname: str) -> Optional[Asset]:
|
|
@@ -214,4 +251,10 @@ class Veracode(FlatFileImporter):
|
|
|
214
251
|
"2": "low",
|
|
215
252
|
"1": "low",
|
|
216
253
|
"0": "info",
|
|
254
|
+
5: "Critical",
|
|
255
|
+
4: "High",
|
|
256
|
+
3: "Medium",
|
|
257
|
+
2: "Low",
|
|
258
|
+
1: "Low",
|
|
259
|
+
0: "Low",
|
|
217
260
|
}
|
|
@@ -1503,7 +1503,7 @@ class RegScaleModel(BaseModel, ABC):
|
|
|
1503
1503
|
:rtype: Optional[T]
|
|
1504
1504
|
"""
|
|
1505
1505
|
if response and response.ok:
|
|
1506
|
-
logger.
|
|
1506
|
+
logger.debug(json.dumps(response.json(), indent=4))
|
|
1507
1507
|
return cast(T, cls(**response.json()))
|
|
1508
1508
|
else:
|
|
1509
1509
|
cls.log_response_error(response=response, suppress_error=suppress_error)
|
|
@@ -75,11 +75,10 @@ class User(RegScaleModel):
|
|
|
75
75
|
:param str v: homePageUrl value
|
|
76
76
|
:return: The homePageUrl if the RegScale version is compatible, None otherwise
|
|
77
77
|
"""
|
|
78
|
-
from
|
|
78
|
+
from regscale.utils.version import RegscaleVersion
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if len(regscale_version) >= 10 or Version(regscale_version) >= Version("6.14.0.0"):
|
|
80
|
+
rv = RegscaleVersion()
|
|
81
|
+
if rv.meets_minimum_version("6.14.0.0"):
|
|
83
82
|
return v
|
|
84
83
|
else:
|
|
85
84
|
return None
|
|
@@ -87,6 +87,17 @@ class Vulnerability(RegScaleModel):
|
|
|
87
87
|
isPublic: bool = Field(default=False)
|
|
88
88
|
dateClosed: Optional[str] = None
|
|
89
89
|
status: Optional[VulnerabilityStatus] = VulnerabilityStatus.Open
|
|
90
|
+
buildVersion: Optional[str] = None
|
|
91
|
+
cvsSv3BaseVector: Optional[str] = None
|
|
92
|
+
cvsSv2BaseVector: Optional[str] = None
|
|
93
|
+
cvsSv2BaseScore: Optional[Union[float, int]] = None
|
|
94
|
+
affectedOS: Optional[str] = None
|
|
95
|
+
packagePath: Optional[str] = None
|
|
96
|
+
imageDigest: Optional[str] = None
|
|
97
|
+
affectedPackages: Optional[str] = None
|
|
98
|
+
installedVersions: Optional[str] = None
|
|
99
|
+
fixedVersions: Optional[str] = None
|
|
100
|
+
fixStatus: Optional[str] = None
|
|
90
101
|
|
|
91
102
|
@field_validator("plugInId")
|
|
92
103
|
def validate_regscale_version_and_plugin_id_type(cls, v: Union[int, str]) -> Union[int, str, None]:
|
|
@@ -153,6 +164,16 @@ class Vulnerability(RegScaleModel):
|
|
|
153
164
|
"tenants_id": "tenantsId",
|
|
154
165
|
"is_public": "isPublic",
|
|
155
166
|
"date_closed": "dateClosed",
|
|
167
|
+
"build_version": "buildVersion",
|
|
168
|
+
"cvss_v3_vector": "cvsSv3BaseVector",
|
|
169
|
+
"cvss_v2_score": "cvsSv2BaseScore",
|
|
170
|
+
"cvss_v2_vector": "cvsSv2BaseVector",
|
|
171
|
+
"affected_os": "affectedOS",
|
|
172
|
+
"image_digest": "imageDigest",
|
|
173
|
+
"affected_packages": "affectedPackages",
|
|
174
|
+
"installed_versions": "installedVersions",
|
|
175
|
+
"fixed_versions": "fixedVersions",
|
|
176
|
+
"fix_status": "fixStatus",
|
|
156
177
|
}
|
|
157
178
|
|
|
158
179
|
# Convert snake_case keys to camelCase
|
regscale/utils/version.py
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import re
|
|
5
|
-
from typing import Optional
|
|
6
5
|
from functools import lru_cache
|
|
7
6
|
|
|
8
7
|
from packaging.version import Version
|
|
9
8
|
|
|
10
9
|
from regscale.core.app.utils.api_handler import APIHandler
|
|
11
|
-
from regscale.utils.decorators import classproperty
|
|
12
10
|
|
|
13
11
|
logger = logging.getLogger(__name__)
|
|
14
12
|
|
|
@@ -32,15 +30,15 @@ class RegscaleVersion:
|
|
|
32
30
|
try:
|
|
33
31
|
api_handler = APIHandler()
|
|
34
32
|
response = api_handler.get("/assets/json/version.json")
|
|
35
|
-
if response.status_code == 200:
|
|
33
|
+
if response.ok and response.status_code == 200:
|
|
36
34
|
version_data = response.json()
|
|
37
35
|
return version_data.get("version", "Unknown")
|
|
38
36
|
else:
|
|
39
37
|
logger.error(f"Failed to fetch version. Status code: {response.status_code}")
|
|
40
|
-
return "
|
|
38
|
+
return "Unknown"
|
|
41
39
|
except Exception as e:
|
|
42
40
|
logger.error(f"Error fetching version: {e}", exc_info=True)
|
|
43
|
-
return "
|
|
41
|
+
return "Unknown"
|
|
44
42
|
|
|
45
43
|
@staticmethod
|
|
46
44
|
def is_valid_version(version: str) -> bool:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: regscale-cli
|
|
3
|
-
Version: 6.16.
|
|
3
|
+
Version: 6.16.3.0
|
|
4
4
|
Summary: Command Line Interface (CLI) for bulk processing/loading data into RegScale
|
|
5
5
|
Home-page: https://github.com/RegScale/regscale-cli
|
|
6
6
|
Author: Travis Howerton
|
|
@@ -579,7 +579,7 @@ See [full documentation on regscale.readme.io](https://regscale.readme.io/docs/o
|
|
|
579
579
|
|
|
580
580
|
Create a virtual environment and install required Python libraries.
|
|
581
581
|
|
|
582
|
-
###
|
|
582
|
+
### MacOS/Linux
|
|
583
583
|
```shell
|
|
584
584
|
# create and activate python virtual environment
|
|
585
585
|
python -m venv venv
|
|
@@ -597,7 +597,7 @@ pip install regscale-cli
|
|
|
597
597
|
pip install "regscale-cli[server]"
|
|
598
598
|
```
|
|
599
599
|
|
|
600
|
-
###
|
|
600
|
+
### Windows
|
|
601
601
|
```PowerShell
|
|
602
602
|
# create and activate python virtual environment
|
|
603
603
|
python -m venv venv
|