scanoss 1.22.0__py3-none-any.whl → 1.24.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.
- scanoss/__init__.py +1 -1
- scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py +49 -0
- scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py +142 -0
- scanoss/cli.py +206 -40
- scanoss/components.py +21 -11
- scanoss/constants.py +2 -0
- scanoss/cryptography.py +274 -0
- scanoss/data/build_date.txt +1 -1
- scanoss/scanners/scanner_hfh.py +2 -1
- scanoss/scanossgrpc.py +115 -47
- scanoss/utils/file.py +2 -2
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/METADATA +1 -1
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/RECORD +19 -18
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/WHEEL +1 -1
- scanoss/api/provenance/v2/scanoss_provenance_pb2.py +0 -41
- scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py +0 -108
- /scanoss/api/{provenance → geoprovenance}/__init__.py +0 -0
- /scanoss/api/{provenance → geoprovenance}/v2/__init__.py +0 -0
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/entry_points.txt +0 -0
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/licenses/LICENSE +0 -0
- {scanoss-1.22.0.dist-info → scanoss-1.24.0.dist-info}/top_level.txt +0 -0
scanoss/cryptography.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from scanoss.scanossbase import ScanossBase
|
|
6
|
+
from scanoss.scanossgrpc import ScanossGrpc
|
|
7
|
+
from scanoss.utils.abstract_presenter import AbstractPresenter
|
|
8
|
+
from scanoss.utils.file import validate_json_file
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ScanossCryptographyError(Exception):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
MIN_SPLIT_PARTS = 2
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class CryptographyConfig:
|
|
20
|
+
purl: List[str]
|
|
21
|
+
input_file: Optional[str] = None
|
|
22
|
+
output_file: Optional[str] = None
|
|
23
|
+
header: Optional[str] = None
|
|
24
|
+
debug: bool = False
|
|
25
|
+
trace: bool = False
|
|
26
|
+
quiet: bool = False
|
|
27
|
+
with_range: bool = False
|
|
28
|
+
|
|
29
|
+
def __post_init__(self):
|
|
30
|
+
"""
|
|
31
|
+
Validate that the configuration is valid.
|
|
32
|
+
"""
|
|
33
|
+
if self.purl:
|
|
34
|
+
if self.with_range:
|
|
35
|
+
for purl in self.purl:
|
|
36
|
+
parts = purl.split('@')
|
|
37
|
+
if not (len(parts) >= MIN_SPLIT_PARTS and parts[1]):
|
|
38
|
+
raise ScanossCryptographyError(
|
|
39
|
+
f'Invalid PURL format: "{purl}".' f'It must include a version (e.g., pkg:type/name@version)'
|
|
40
|
+
)
|
|
41
|
+
if self.input_file:
|
|
42
|
+
input_file_validation = validate_json_file(self.input_file)
|
|
43
|
+
if not input_file_validation.is_valid:
|
|
44
|
+
raise ScanossCryptographyError(
|
|
45
|
+
f'There was a problem with the purl input file. {input_file_validation.error}'
|
|
46
|
+
)
|
|
47
|
+
if (
|
|
48
|
+
not isinstance(input_file_validation.data, dict)
|
|
49
|
+
or 'purls' not in input_file_validation.data
|
|
50
|
+
or not isinstance(input_file_validation.data['purls'], list)
|
|
51
|
+
or not all(isinstance(p, dict) and 'purl' in p for p in input_file_validation.data['purls'])
|
|
52
|
+
):
|
|
53
|
+
raise ScanossCryptographyError('The supplied input file is not in the correct PurlRequest format.')
|
|
54
|
+
purls = input_file_validation.data['purls']
|
|
55
|
+
purls_with_requirement = []
|
|
56
|
+
if self.with_range:
|
|
57
|
+
if any('requirement' not in p for p in purls):
|
|
58
|
+
raise ScanossCryptographyError(
|
|
59
|
+
f'One or more PURLs in "{self.input_file}" are missing the "requirement" field.'
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
for purl in purls:
|
|
63
|
+
purls_with_requirement.append(f'{purl["purl"]}@{purl["requirement"]}')
|
|
64
|
+
else:
|
|
65
|
+
purls_with_requirement = purls
|
|
66
|
+
self.purl = purls_with_requirement
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def create_cryptography_config_from_args(args) -> CryptographyConfig:
|
|
70
|
+
return CryptographyConfig(
|
|
71
|
+
debug=getattr(args, 'debug', False),
|
|
72
|
+
trace=getattr(args, 'trace', False),
|
|
73
|
+
quiet=getattr(args, 'quiet', False),
|
|
74
|
+
with_range=getattr(args, 'with_range', False),
|
|
75
|
+
purl=getattr(args, 'purl', []),
|
|
76
|
+
input_file=getattr(args, 'input', None),
|
|
77
|
+
output_file=getattr(args, 'output', None),
|
|
78
|
+
header=getattr(args, 'header', None),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Cryptography:
|
|
83
|
+
"""
|
|
84
|
+
Cryptography Class
|
|
85
|
+
|
|
86
|
+
This class is used to decorate purls with cryptography information.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
def __init__(
|
|
90
|
+
self,
|
|
91
|
+
config: CryptographyConfig,
|
|
92
|
+
client: ScanossGrpc,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Initialize the Cryptography.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
config (CryptographyConfig): Configuration parameters for the cryptography.
|
|
99
|
+
client (ScanossGrpc): gRPC client for communicating with the scanning service.
|
|
100
|
+
"""
|
|
101
|
+
self.base = ScanossBase(
|
|
102
|
+
debug=config.debug,
|
|
103
|
+
trace=config.trace,
|
|
104
|
+
quiet=config.quiet,
|
|
105
|
+
)
|
|
106
|
+
self.presenter = CryptographyPresenter(
|
|
107
|
+
self,
|
|
108
|
+
debug=config.debug,
|
|
109
|
+
trace=config.trace,
|
|
110
|
+
quiet=config.quiet,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
self.client = client
|
|
114
|
+
self.config = config
|
|
115
|
+
self.purls_request = self._build_purls_request()
|
|
116
|
+
self.results = None
|
|
117
|
+
|
|
118
|
+
def get_algorithms(self) -> Optional[Dict]:
|
|
119
|
+
"""
|
|
120
|
+
Get the cryptographic algorithms for the provided purl or input file.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Optional[Dict]: The folder hash response from the gRPC client, or None if an error occurs.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
if not self.purls_request:
|
|
127
|
+
raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
|
|
128
|
+
self.base.print_stderr(
|
|
129
|
+
f'Getting cryptographic algorithms for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
|
|
130
|
+
)
|
|
131
|
+
if self.config.with_range:
|
|
132
|
+
response = self.client.get_crypto_algorithms_in_range_for_purl(self.purls_request)
|
|
133
|
+
else:
|
|
134
|
+
response = self.client.get_crypto_algorithms_for_purl(self.purls_request)
|
|
135
|
+
if response:
|
|
136
|
+
self.results = response
|
|
137
|
+
|
|
138
|
+
return self.results
|
|
139
|
+
|
|
140
|
+
def get_encryption_hints(self) -> Optional[Dict]:
|
|
141
|
+
"""
|
|
142
|
+
Get the encryption hints for the provided purl or input file.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Optional[Dict]: The encryption hints response from the gRPC client, or None if an error occurs.
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
if not self.purls_request:
|
|
149
|
+
raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
|
|
150
|
+
self.base.print_stderr(
|
|
151
|
+
f'Getting encryption hints '
|
|
152
|
+
f'{"in range" if self.config.with_range else ""} '
|
|
153
|
+
f'for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
|
|
154
|
+
)
|
|
155
|
+
if self.config.with_range:
|
|
156
|
+
response = self.client.get_encryption_hints_in_range_for_purl(self.purls_request)
|
|
157
|
+
else:
|
|
158
|
+
response = self.client.get_encryption_hints_for_purl(self.purls_request)
|
|
159
|
+
if response:
|
|
160
|
+
self.results = response
|
|
161
|
+
|
|
162
|
+
return self.results
|
|
163
|
+
|
|
164
|
+
def get_versions_in_range(self) -> Optional[Dict]:
|
|
165
|
+
"""
|
|
166
|
+
Given a list of PURLS and version ranges, get a list of versions that do/do not contain cryptographic algorithms
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Optional[Dict]: The versions in range response from the gRPC client, or None if an error occurs.
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
if not self.purls_request:
|
|
173
|
+
raise ScanossCryptographyError('No PURLs supplied. Provide --purl or --input.')
|
|
174
|
+
|
|
175
|
+
self.base.print_stderr(
|
|
176
|
+
f'Getting versions in range for {", ".join([p["purl"] for p in self.purls_request["purls"]])}'
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
response = self.client.get_versions_in_range_for_purl(self.purls_request)
|
|
180
|
+
if response:
|
|
181
|
+
self.results = response
|
|
182
|
+
|
|
183
|
+
return self.results
|
|
184
|
+
|
|
185
|
+
def _build_purls_request(
|
|
186
|
+
self,
|
|
187
|
+
) -> Optional[dict]:
|
|
188
|
+
"""
|
|
189
|
+
Load the specified purls from a JSON file or a list of PURLs and return a dictionary
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
json_file (Optional[str], optional): The JSON file containing the PURLs. Defaults to None.
|
|
193
|
+
purls (Optional[List[str]], optional): The list of PURLs. Defaults to None.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
Optional[dict]: The dictionary containing the PURLs
|
|
197
|
+
"""
|
|
198
|
+
return {
|
|
199
|
+
'purls': [
|
|
200
|
+
{
|
|
201
|
+
'purl': p,
|
|
202
|
+
'requirement': self._extract_version_from_purl(p),
|
|
203
|
+
}
|
|
204
|
+
for p in self.config.purl
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
def _extract_version_from_purl(self, purl: str) -> str:
|
|
209
|
+
"""
|
|
210
|
+
Extract version from purl
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
purl (str): The purl string to extract the version from
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
str: The extracted version
|
|
217
|
+
|
|
218
|
+
Raises:
|
|
219
|
+
ScanossCryptographyError: If the purl is not in the correct format
|
|
220
|
+
"""
|
|
221
|
+
try:
|
|
222
|
+
return purl.split('@')[-1]
|
|
223
|
+
except IndexError:
|
|
224
|
+
raise ScanossCryptographyError(f'Invalid purl format: {purl}')
|
|
225
|
+
|
|
226
|
+
def present(
|
|
227
|
+
self,
|
|
228
|
+
output_format: Optional[str] = None,
|
|
229
|
+
output_file: Optional[str] = None,
|
|
230
|
+
):
|
|
231
|
+
"""Present the results in the selected format"""
|
|
232
|
+
self.presenter.present(output_format=output_format, output_file=output_file)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class CryptographyPresenter(AbstractPresenter):
|
|
236
|
+
"""
|
|
237
|
+
Cryptography presenter class
|
|
238
|
+
Handles the presentation of the cryptography results
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def __init__(self, cryptography: Cryptography, **kwargs):
|
|
242
|
+
super().__init__(**kwargs)
|
|
243
|
+
self.cryptography = cryptography
|
|
244
|
+
|
|
245
|
+
def _format_json_output(self) -> str:
|
|
246
|
+
"""
|
|
247
|
+
Format the scan output data into a JSON object
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
str: The formatted JSON string
|
|
251
|
+
"""
|
|
252
|
+
return json.dumps(self.cryptography.results, indent=2)
|
|
253
|
+
|
|
254
|
+
def _format_plain_output(self) -> str:
|
|
255
|
+
"""
|
|
256
|
+
Format the scan output data into a plain text string
|
|
257
|
+
"""
|
|
258
|
+
return (
|
|
259
|
+
json.dumps(self.cryptography.results, indent=2)
|
|
260
|
+
if isinstance(self.cryptography.results, dict)
|
|
261
|
+
else str(self.cryptography.results)
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def _format_cyclonedx_output(self) -> str:
|
|
265
|
+
raise NotImplementedError('CycloneDX output is not implemented')
|
|
266
|
+
|
|
267
|
+
def _format_spdxlite_output(self) -> str:
|
|
268
|
+
raise NotImplementedError('SPDXlite output is not implemented')
|
|
269
|
+
|
|
270
|
+
def _format_csv_output(self) -> str:
|
|
271
|
+
raise NotImplementedError('CSV output is not implemented')
|
|
272
|
+
|
|
273
|
+
def _format_raw_output(self) -> str:
|
|
274
|
+
raise NotImplementedError('Raw output is not implemented')
|
scanoss/data/build_date.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
date:
|
|
1
|
+
date: 20250528081438, utime: 1748420078
|
scanoss/scanners/scanner_hfh.py
CHANGED
scanoss/scanossgrpc.py
CHANGED
|
@@ -36,7 +36,6 @@ from google.protobuf.json_format import MessageToDict, ParseDict
|
|
|
36
36
|
from pypac.parser import PACFile
|
|
37
37
|
from pypac.resolver import ProxyResolver
|
|
38
38
|
|
|
39
|
-
from scanoss.api.provenance.v2.scanoss_provenance_pb2_grpc import ProvenanceStub
|
|
40
39
|
from scanoss.api.scanning.v2.scanoss_scanning_pb2_grpc import ScanningStub
|
|
41
40
|
from scanoss.constants import DEFAULT_TIMEOUT
|
|
42
41
|
|
|
@@ -55,11 +54,11 @@ from .api.components.v2.scanoss_components_pb2 import (
|
|
|
55
54
|
CompVersionResponse,
|
|
56
55
|
)
|
|
57
56
|
from .api.components.v2.scanoss_components_pb2_grpc import ComponentsStub
|
|
58
|
-
from .api.cryptography.v2.scanoss_cryptography_pb2 import AlgorithmResponse
|
|
59
57
|
from .api.cryptography.v2.scanoss_cryptography_pb2_grpc import CryptographyStub
|
|
60
58
|
from .api.dependencies.v2.scanoss_dependencies_pb2 import DependencyRequest
|
|
61
59
|
from .api.dependencies.v2.scanoss_dependencies_pb2_grpc import DependenciesStub
|
|
62
|
-
from .api.
|
|
60
|
+
from .api.geoprovenance.v2.scanoss_geoprovenance_pb2 import ContributorResponse
|
|
61
|
+
from .api.geoprovenance.v2.scanoss_geoprovenance_pb2_grpc import GeoProvenanceStub
|
|
63
62
|
from .api.scanning.v2.scanoss_scanning_pb2 import HFHRequest
|
|
64
63
|
from .api.semgrep.v2.scanoss_semgrep_pb2 import SemgrepResponse
|
|
65
64
|
from .api.semgrep.v2.scanoss_semgrep_pb2_grpc import SemgrepStub
|
|
@@ -169,7 +168,7 @@ class ScanossGrpc(ScanossBase):
|
|
|
169
168
|
self.dependencies_stub = DependenciesStub(grpc.insecure_channel(self.url))
|
|
170
169
|
self.semgrep_stub = SemgrepStub(grpc.insecure_channel(self.url))
|
|
171
170
|
self.vuln_stub = VulnerabilitiesStub(grpc.insecure_channel(self.url))
|
|
172
|
-
self.provenance_stub =
|
|
171
|
+
self.provenance_stub = GeoProvenanceStub(grpc.insecure_channel(self.url))
|
|
173
172
|
self.scanning_stub = ScanningStub(grpc.insecure_channel(self.url))
|
|
174
173
|
else:
|
|
175
174
|
if ca_cert is not None:
|
|
@@ -181,7 +180,7 @@ class ScanossGrpc(ScanossBase):
|
|
|
181
180
|
self.dependencies_stub = DependenciesStub(grpc.secure_channel(self.url, credentials))
|
|
182
181
|
self.semgrep_stub = SemgrepStub(grpc.secure_channel(self.url, credentials))
|
|
183
182
|
self.vuln_stub = VulnerabilitiesStub(grpc.secure_channel(self.url, credentials))
|
|
184
|
-
self.provenance_stub =
|
|
183
|
+
self.provenance_stub = GeoProvenanceStub(grpc.secure_channel(self.url, credentials))
|
|
185
184
|
self.scanning_stub = ScanningStub(grpc.secure_channel(self.url, credentials))
|
|
186
185
|
|
|
187
186
|
@classmethod
|
|
@@ -312,36 +311,6 @@ class ScanossGrpc(ScanossBase):
|
|
|
312
311
|
merged_response['status'] = response['status']
|
|
313
312
|
return merged_response
|
|
314
313
|
|
|
315
|
-
def get_crypto_json(self, purls: dict) -> dict:
|
|
316
|
-
"""
|
|
317
|
-
Client function to call the rpc for Cryptography GetAlgorithms
|
|
318
|
-
:param purls: Message to send to the service
|
|
319
|
-
:return: Server response or None
|
|
320
|
-
"""
|
|
321
|
-
if not purls:
|
|
322
|
-
self.print_stderr('ERROR: No message supplied to send to gRPC service.')
|
|
323
|
-
return None
|
|
324
|
-
request_id = str(uuid.uuid4())
|
|
325
|
-
resp: AlgorithmResponse
|
|
326
|
-
try:
|
|
327
|
-
request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
|
|
328
|
-
metadata = self.metadata[:]
|
|
329
|
-
metadata.append(('x-request-id', request_id)) # Set a Request ID
|
|
330
|
-
self.print_debug(f'Sending crypto data for decoration (rqId: {request_id})...')
|
|
331
|
-
resp = self.crypto_stub.GetAlgorithms(request, metadata=metadata, timeout=self.timeout)
|
|
332
|
-
except Exception as e:
|
|
333
|
-
self.print_stderr(
|
|
334
|
-
f'ERROR: {e.__class__.__name__} Problem encountered sending gRPC message (rqId: {request_id}): {e}'
|
|
335
|
-
)
|
|
336
|
-
else:
|
|
337
|
-
if resp:
|
|
338
|
-
if not self._check_status_response(resp.status, request_id):
|
|
339
|
-
return None
|
|
340
|
-
resp_dict = MessageToDict(resp, preserving_proto_field_name=True) # Convert gRPC response to a dict
|
|
341
|
-
del resp_dict['status']
|
|
342
|
-
return resp_dict
|
|
343
|
-
return None
|
|
344
|
-
|
|
345
314
|
def get_vulnerabilities_json(self, purls: dict) -> dict:
|
|
346
315
|
"""
|
|
347
316
|
Client function to call the rpc for Vulnerability GetVulnerabilities
|
|
@@ -462,7 +431,7 @@ class ScanossGrpc(ScanossBase):
|
|
|
462
431
|
return resp_dict
|
|
463
432
|
return None
|
|
464
433
|
|
|
465
|
-
def folder_hash_scan(self, request: Dict) -> Dict:
|
|
434
|
+
def folder_hash_scan(self, request: Dict) -> Optional[Dict]:
|
|
466
435
|
"""
|
|
467
436
|
Client function to call the rpc for Folder Hashing Scan
|
|
468
437
|
|
|
@@ -470,7 +439,7 @@ class ScanossGrpc(ScanossBase):
|
|
|
470
439
|
request (Dict): Folder Hash Request
|
|
471
440
|
|
|
472
441
|
Returns:
|
|
473
|
-
Dict: Folder Hash Response
|
|
442
|
+
Optional[Dict]: Folder Hash Response, or None if the request was not succesfull
|
|
474
443
|
"""
|
|
475
444
|
return self._call_rpc(
|
|
476
445
|
self.scanning_stub.FolderHashScan,
|
|
@@ -479,7 +448,7 @@ class ScanossGrpc(ScanossBase):
|
|
|
479
448
|
'Sending folder hash scan data (rqId: {rqId})...',
|
|
480
449
|
)
|
|
481
450
|
|
|
482
|
-
def _call_rpc(self, rpc_method, request_input, request_type, debug_msg: Optional[str] = None) ->
|
|
451
|
+
def _call_rpc(self, rpc_method, request_input, request_type, debug_msg: Optional[str] = None) -> Optional[Dict]:
|
|
483
452
|
"""
|
|
484
453
|
Call a gRPC method and return the response as a dictionary
|
|
485
454
|
|
|
@@ -490,9 +459,8 @@ class ScanossGrpc(ScanossBase):
|
|
|
490
459
|
debug_msg (str, optional): Debug message template that can include {rqId} placeholder.
|
|
491
460
|
|
|
492
461
|
Returns:
|
|
493
|
-
dict: The parsed gRPC response as a dictionary, or None if
|
|
462
|
+
dict: The parsed gRPC response as a dictionary, or None if something went wrong
|
|
494
463
|
"""
|
|
495
|
-
|
|
496
464
|
request_id = str(uuid.uuid4())
|
|
497
465
|
|
|
498
466
|
if isinstance(request_input, dict):
|
|
@@ -503,7 +471,6 @@ class ScanossGrpc(ScanossBase):
|
|
|
503
471
|
metadata = self.metadata[:] + [('x-request-id', request_id)]
|
|
504
472
|
|
|
505
473
|
self.print_debug(debug_msg.format(rqId=request_id))
|
|
506
|
-
|
|
507
474
|
try:
|
|
508
475
|
resp = rpc_method(request_obj, metadata=metadata, timeout=self.timeout)
|
|
509
476
|
except grpc.RpcError as e:
|
|
@@ -512,10 +479,9 @@ class ScanossGrpc(ScanossBase):
|
|
|
512
479
|
)
|
|
513
480
|
|
|
514
481
|
if resp and not self._check_status_response(resp.status, request_id):
|
|
515
|
-
|
|
482
|
+
return None
|
|
516
483
|
|
|
517
484
|
resp_dict = MessageToDict(resp, preserving_proto_field_name=True)
|
|
518
|
-
resp_dict.pop('status', None)
|
|
519
485
|
return resp_dict
|
|
520
486
|
|
|
521
487
|
def _check_status_response(self, status_response: StatusResponse, request_id: str = None) -> bool:
|
|
@@ -574,13 +540,13 @@ class ScanossGrpc(ScanossBase):
|
|
|
574
540
|
self.print_stderr('ERROR: No message supplied to send to gRPC service.')
|
|
575
541
|
return None
|
|
576
542
|
request_id = str(uuid.uuid4())
|
|
577
|
-
resp:
|
|
543
|
+
resp: ContributorResponse
|
|
578
544
|
try:
|
|
579
545
|
request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
|
|
580
546
|
metadata = self.metadata[:]
|
|
581
547
|
metadata.append(('x-request-id', request_id)) # Set a Request ID
|
|
582
548
|
self.print_debug(f'Sending data for provenance decoration (rqId: {request_id})...')
|
|
583
|
-
resp = self.provenance_stub.
|
|
549
|
+
resp = self.provenance_stub.GetComponentContributors(request, metadata=metadata, timeout=self.timeout)
|
|
584
550
|
except Exception as e:
|
|
585
551
|
self.print_stderr(
|
|
586
552
|
f'ERROR: {e.__class__.__name__} Problem encountered sending gRPC message (rqId: {request_id}): {e}'
|
|
@@ -593,6 +559,108 @@ class ScanossGrpc(ScanossBase):
|
|
|
593
559
|
return resp_dict
|
|
594
560
|
return None
|
|
595
561
|
|
|
562
|
+
def get_provenance_origin(self, request: Dict) -> Optional[Dict]:
|
|
563
|
+
"""
|
|
564
|
+
Client function to call the rpc for GetComponentOrigin
|
|
565
|
+
|
|
566
|
+
Args:
|
|
567
|
+
request (Dict): GetComponentOrigin Request
|
|
568
|
+
|
|
569
|
+
Returns:
|
|
570
|
+
Optional[Dict]: OriginResponse, or None if the request was not successfull
|
|
571
|
+
"""
|
|
572
|
+
return self._call_rpc(
|
|
573
|
+
self.provenance_stub.GetComponentOrigin,
|
|
574
|
+
request,
|
|
575
|
+
PurlRequest,
|
|
576
|
+
'Sending data for provenance origin decoration (rqId: {rqId})...',
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
def get_crypto_algorithms_for_purl(self, request: Dict) -> Optional[Dict]:
|
|
580
|
+
"""
|
|
581
|
+
Client function to call the rpc for GetAlgorithms for a list of purls
|
|
582
|
+
|
|
583
|
+
Args:
|
|
584
|
+
request (Dict): PurlRequest
|
|
585
|
+
|
|
586
|
+
Returns:
|
|
587
|
+
Optional[Dict]: AlgorithmResponse, or None if the request was not successfull
|
|
588
|
+
"""
|
|
589
|
+
return self._call_rpc(
|
|
590
|
+
self.crypto_stub.GetAlgorithms,
|
|
591
|
+
request,
|
|
592
|
+
PurlRequest,
|
|
593
|
+
'Sending data for cryptographic algorithms decoration (rqId: {rqId})...',
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
def get_crypto_algorithms_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
|
|
597
|
+
"""
|
|
598
|
+
Client function to call the rpc for GetAlgorithmsInRange for a list of purls
|
|
599
|
+
|
|
600
|
+
Args:
|
|
601
|
+
request (Dict): PurlRequest
|
|
602
|
+
|
|
603
|
+
Returns:
|
|
604
|
+
Optional[Dict]: AlgorithmsInRangeResponse, or None if the request was not successfull
|
|
605
|
+
"""
|
|
606
|
+
return self._call_rpc(
|
|
607
|
+
self.crypto_stub.GetAlgorithmsInRange,
|
|
608
|
+
request,
|
|
609
|
+
PurlRequest,
|
|
610
|
+
'Sending data for cryptographic algorithms in range decoration (rqId: {rqId})...',
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
def get_encryption_hints_for_purl(self, request: Dict) -> Optional[Dict]:
|
|
614
|
+
"""
|
|
615
|
+
Client function to call the rpc for GetEncryptionHints for a list of purls
|
|
616
|
+
|
|
617
|
+
Args:
|
|
618
|
+
request (Dict): PurlRequest
|
|
619
|
+
|
|
620
|
+
Returns:
|
|
621
|
+
Optional[Dict]: HintsResponse, or None if the request was not successfull
|
|
622
|
+
"""
|
|
623
|
+
return self._call_rpc(
|
|
624
|
+
self.crypto_stub.GetEncryptionHints,
|
|
625
|
+
request,
|
|
626
|
+
PurlRequest,
|
|
627
|
+
'Sending data for encryption hints decoration (rqId: {rqId})...',
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
def get_encryption_hints_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
|
|
631
|
+
"""
|
|
632
|
+
Client function to call the rpc for GetHintsInRange for a list of purls
|
|
633
|
+
|
|
634
|
+
Args:
|
|
635
|
+
request (Dict): PurlRequest
|
|
636
|
+
|
|
637
|
+
Returns:
|
|
638
|
+
Optional[Dict]: HintsInRangeResponse, or None if the request was not successfull
|
|
639
|
+
"""
|
|
640
|
+
return self._call_rpc(
|
|
641
|
+
self.crypto_stub.GetHintsInRange,
|
|
642
|
+
request,
|
|
643
|
+
PurlRequest,
|
|
644
|
+
'Sending data for encryption hints in range decoration (rqId: {rqId})...',
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
def get_versions_in_range_for_purl(self, request: Dict) -> Optional[Dict]:
|
|
648
|
+
"""
|
|
649
|
+
Client function to call the rpc for GetVersionsInRange for a list of purls
|
|
650
|
+
|
|
651
|
+
Args:
|
|
652
|
+
request (Dict): PurlRequest
|
|
653
|
+
|
|
654
|
+
Returns:
|
|
655
|
+
Optional[Dict]: VersionsInRangeResponse, or None if the request was not successfull
|
|
656
|
+
"""
|
|
657
|
+
return self._call_rpc(
|
|
658
|
+
self.crypto_stub.GetVersionsInRange,
|
|
659
|
+
request,
|
|
660
|
+
PurlRequest,
|
|
661
|
+
'Sending data for cryptographic versions in range decoration (rqId: {rqId})...',
|
|
662
|
+
)
|
|
663
|
+
|
|
596
664
|
def load_generic_headers(self):
|
|
597
665
|
"""
|
|
598
666
|
Adds custom headers from req_headers to metadata.
|
|
@@ -623,10 +691,11 @@ class GrpcConfig:
|
|
|
623
691
|
quiet: Optional[bool] = False
|
|
624
692
|
ver_details: Optional[str] = None
|
|
625
693
|
ca_cert: Optional[str] = None
|
|
626
|
-
pac: Optional[PACFile] = None
|
|
627
694
|
timeout: Optional[int] = DEFAULT_TIMEOUT
|
|
628
695
|
proxy: Optional[str] = None
|
|
629
696
|
grpc_proxy: Optional[str] = None
|
|
697
|
+
pac: Optional[PACFile] = None
|
|
698
|
+
req_headers: Optional[dict] = None
|
|
630
699
|
|
|
631
700
|
|
|
632
701
|
def create_grpc_config_from_args(args) -> GrpcConfig:
|
|
@@ -638,7 +707,6 @@ def create_grpc_config_from_args(args) -> GrpcConfig:
|
|
|
638
707
|
quiet=getattr(args, 'quiet', False),
|
|
639
708
|
ver_details=getattr(args, 'ver_details', None),
|
|
640
709
|
ca_cert=getattr(args, 'ca_cert', None),
|
|
641
|
-
pac=getattr(args, 'pac', None),
|
|
642
710
|
timeout=getattr(args, 'timeout', DEFAULT_TIMEOUT),
|
|
643
711
|
proxy=getattr(args, 'proxy', None),
|
|
644
712
|
grpc_proxy=getattr(args, 'grpc_proxy', None),
|
scanoss/utils/file.py
CHANGED
|
@@ -49,8 +49,8 @@ def validate_json_file(json_file_path: str) -> JsonValidation:
|
|
|
49
49
|
json_file_path (str): The JSON file to validate
|
|
50
50
|
|
|
51
51
|
Returns:
|
|
52
|
-
|
|
53
|
-
"""
|
|
52
|
+
JsonValidation: A JsonValidation object containing a boolean indicating if the file is valid, the data, error, and error code
|
|
53
|
+
""" # noqa: E501
|
|
54
54
|
if not json_file_path:
|
|
55
55
|
return JsonValidation(is_valid=False, error='No JSON file specified')
|
|
56
56
|
if not os.path.isfile(json_file_path):
|
|
@@ -4,10 +4,11 @@ protoc_gen_swagger/options/annotations_pb2.py,sha256=b25EDD6gssUWnFby9gxgcpLIROT
|
|
|
4
4
|
protoc_gen_swagger/options/annotations_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
5
5
|
protoc_gen_swagger/options/openapiv2_pb2.py,sha256=vYElGp8E1vGHszvWqX97zNG9GFJ7u2QcdK9ouq0XdyI,14939
|
|
6
6
|
protoc_gen_swagger/options/openapiv2_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
7
|
-
scanoss/__init__.py,sha256=
|
|
8
|
-
scanoss/cli.py,sha256=
|
|
9
|
-
scanoss/components.py,sha256=
|
|
10
|
-
scanoss/constants.py,sha256=
|
|
7
|
+
scanoss/__init__.py,sha256=eyFaTBLEaia158sB-9Qg2uEmdiJFZKEB4ow7f4e5wVw,1146
|
|
8
|
+
scanoss/cli.py,sha256=SAB0xuHjEEw20YtYAPSZwrQaVf4JUsm8NRcVArMzd4U,69099
|
|
9
|
+
scanoss/components.py,sha256=b0R9DdKuXqyQiw5nZZwjQ6NJXBr1U9gyx1RI2FP9ozA,14511
|
|
10
|
+
scanoss/constants.py,sha256=FWCZG8gQputKwV7XwvW1GuwDXL4wDLQyVRGdwygg578,320
|
|
11
|
+
scanoss/cryptography.py,sha256=Q39MOCscP-OFvrnPXaPOMFFkc8OKnf3mC3SgZYEtCog,9407
|
|
11
12
|
scanoss/csvoutput.py,sha256=qNKRwcChSkgIwLm00kZiVX6iHVQUF4Apl-sMbzJ5Taw,10192
|
|
12
13
|
scanoss/cyclonedx.py,sha256=UktDuqZUbXSggdt864Pg8ziTD7sdEQtLxfYL7vd_ZCE,12756
|
|
13
14
|
scanoss/file_filters.py,sha256=_1Ehb_rLnHw_-6N5Zhh4Es2lz6rlx0LozGPn-u52cok,20338
|
|
@@ -18,7 +19,7 @@ scanoss/scanner.py,sha256=ZL8I8KtVyXgUMcl7Ccbip_Q1IlU9WTgI-mFtSpF1JWw,45223
|
|
|
18
19
|
scanoss/scanoss_settings.py,sha256=393JnWLsEZhvMg5tPUGgxmqnBKp8AcLxYsDRbLP7aV4,10650
|
|
19
20
|
scanoss/scanossapi.py,sha256=v4D9i9Impa82Enw-5hZ7KLlscDIpaILNbGOMj3MJXqs,13067
|
|
20
21
|
scanoss/scanossbase.py,sha256=Dkpwxa8NH8XN1iRl03NM_Mkvby0JQ4qfvCiiUrJ5ul0,3163
|
|
21
|
-
scanoss/scanossgrpc.py,sha256=
|
|
22
|
+
scanoss/scanossgrpc.py,sha256=B0rl676-B-ZxqXRp7blXnqbAGPC5rqLAQHG28NoC32E,30004
|
|
22
23
|
scanoss/scanpostprocessor.py,sha256=-JsThlxrU70r92GHykTMERnicdd-6jmwNsE4PH0MN2o,11063
|
|
23
24
|
scanoss/scantype.py,sha256=gFmyVmKQpHWogN2iCmMj032e_sZo4T92xS3_EH5B3Tc,1310
|
|
24
25
|
scanoss/spdxlite.py,sha256=MQqFgQhIO-yrbRwEAQS77HmRgP5GDxff-2JYLVoceA0,28946
|
|
@@ -40,10 +41,10 @@ scanoss/api/dependencies/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC
|
|
|
40
41
|
scanoss/api/dependencies/v2/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
|
|
41
42
|
scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py,sha256=4zG2dIiQnNcicg84WcJPPBqLK5QaOKQjkz49hXRTRkw,6501
|
|
42
43
|
scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py,sha256=8KjaWuOT5rygIMe2oWTmyZND3Ugt7K3g94K7a1Mbwcs,6875
|
|
43
|
-
scanoss/api/
|
|
44
|
-
scanoss/api/
|
|
45
|
-
scanoss/api/
|
|
46
|
-
scanoss/api/
|
|
44
|
+
scanoss/api/geoprovenance/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
|
|
45
|
+
scanoss/api/geoprovenance/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
|
|
46
|
+
scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py,sha256=Z4k9qvU2klesnPRW9DRV6Lq79GT2XJSxYHKpSm3s1HA,5403
|
|
47
|
+
scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py,sha256=B6sv2Taagt05CMWaw7T6silg7PW8E6xQVbqn_4-v14U,6854
|
|
47
48
|
scanoss/api/scanning/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
|
|
48
49
|
scanoss/api/scanning/v2/__init__.py,sha256=hx-P78xbDsh6WQIigewkJ7Y7y1fqc_eYnyHC5IZTKmo,1122
|
|
49
50
|
scanoss/api/scanning/v2/scanoss_scanning_pb2.py,sha256=rHScTNN5_jsgLu_y3UIPTjeBX74GUw0kyjA-IMoz7mQ,4324
|
|
@@ -56,7 +57,7 @@ scanoss/api/vulnerabilities/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSC
|
|
|
56
57
|
scanoss/api/vulnerabilities/v2/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSCHhIDMJT4r0,1122
|
|
57
58
|
scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
|
|
58
59
|
scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
|
|
59
|
-
scanoss/data/build_date.txt,sha256=
|
|
60
|
+
scanoss/data/build_date.txt,sha256=PDQnZE2-WtpYAXPgkmN0EbClN0u6qP3jO1XlbqtFxSk,40
|
|
60
61
|
scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
|
|
61
62
|
scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
|
|
62
63
|
scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
|
|
@@ -69,15 +70,15 @@ scanoss/scanners/__init__.py,sha256=D4C0lWLuNp8k_BjQZEc07WZcUgAvriVwQWOk063b0ZU,
|
|
|
69
70
|
scanoss/scanners/container_scanner.py,sha256=leP4roes6B9B95F49mJ0P_F8WcKCQkvJgk9azWyJrjg,16294
|
|
70
71
|
scanoss/scanners/folder_hasher.py,sha256=ePWinOTN3neSVz7T81TAF7GZVAGNYGJ8SfhM5LBYWb8,9824
|
|
71
72
|
scanoss/scanners/scanner_config.py,sha256=egG7cw3S2akU-D9M1aLE5jLrfz_c8e7_DIotMnnpM84,2601
|
|
72
|
-
scanoss/scanners/scanner_hfh.py,sha256=
|
|
73
|
+
scanoss/scanners/scanner_hfh.py,sha256=KksrC1XnOv7mXSlGyo_AJXwtPfKjqffkttdPoNDc-AQ,5802
|
|
73
74
|
scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
|
|
74
75
|
scanoss/utils/abstract_presenter.py,sha256=teiDTxBj5jBMCk2T8i4l1BJPf_u4zBLWrtCTFHSSECM,3148
|
|
75
76
|
scanoss/utils/crc64.py,sha256=TMrwQimSdE6imhFOUL7oAG6Kxu-8qMpGWMuMg8QpSVs,3169
|
|
76
|
-
scanoss/utils/file.py,sha256=
|
|
77
|
+
scanoss/utils/file.py,sha256=62cA9a17TU9ZvfA3FY5HY4-QOajJeSrc8S6xLA_f-3M,2980
|
|
77
78
|
scanoss/utils/simhash.py,sha256=6iu8DOcecPAY36SZjCOzrrLMT9oIE7-gI6QuYwUQ7B0,5793
|
|
78
|
-
scanoss-1.
|
|
79
|
-
scanoss-1.
|
|
80
|
-
scanoss-1.
|
|
81
|
-
scanoss-1.
|
|
82
|
-
scanoss-1.
|
|
83
|
-
scanoss-1.
|
|
79
|
+
scanoss-1.24.0.dist-info/licenses/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
|
|
80
|
+
scanoss-1.24.0.dist-info/METADATA,sha256=wQSSRp3ABZrmz68RkCS802sgrqTAylb9XzXmMGt_7TI,6060
|
|
81
|
+
scanoss-1.24.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
82
|
+
scanoss-1.24.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
|
|
83
|
+
scanoss-1.24.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
|
|
84
|
+
scanoss-1.24.0.dist-info/RECORD,,
|