scanoss 1.19.6__py3-none-any.whl → 1.20.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 CHANGED
@@ -22,4 +22,4 @@
22
22
  THE SOFTWARE.
23
23
  """
24
24
 
25
- __version__ = "1.19.6"
25
+ __version__ = "1.20.0"
@@ -0,0 +1,23 @@
1
+ """
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2021, SCANOSS
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+ """
@@ -0,0 +1,23 @@
1
+ """
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2021, SCANOSS
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+ """
@@ -0,0 +1,42 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: scanoss/api/provenance/v2/scanoss-provenance.proto
4
+ # Protobuf Python Version: 4.25.1
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+ from scanoss.api.common.v2 import scanoss_common_pb2 as scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2
16
+ from google.api import annotations_pb2 as google_dot_api_dot_annotations__pb2
17
+ from protoc_gen_swagger.options import annotations_pb2 as protoc__gen__swagger_dot_options_dot_annotations__pb2
18
+
19
+
20
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n2scanoss/api/provenance/v2/scanoss-provenance.proto\x12\x19scanoss.api.provenance.v2\x1a*scanoss/api/common/v2/scanoss-common.proto\x1a\x1cgoogle/api/annotations.proto\x1a,protoc-gen-swagger/options/annotations.proto\"\xd5\x03\n\x12ProvenanceResponse\x12\x42\n\x05purls\x18\x01 \x03(\x0b\x32\x33.scanoss.api.provenance.v2.ProvenanceResponse.Purls\x12\x35\n\x06status\x18\x02 \x01(\x0b\x32%.scanoss.api.common.v2.StatusResponse\x1a\x32\n\x10\x44\x65\x63laredLocation\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x10\n\x08location\x18\x02 \x01(\t\x1a\x31\n\x0f\x43uratedLocation\x12\x0f\n\x07\x63ountry\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x05\x1a\xdc\x01\n\x05Purls\x12\x0c\n\x04purl\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12Z\n\x12\x64\x65\x63lared_locations\x18\x03 \x03(\x0b\x32>.scanoss.api.provenance.v2.ProvenanceResponse.DeclaredLocation\x12X\n\x11\x63urated_locations\x18\x04 \x03(\x0b\x32=.scanoss.api.provenance.v2.ProvenanceResponse.CuratedLocation2\x98\x02\n\nProvenance\x12s\n\x04\x45\x63ho\x12\".scanoss.api.common.v2.EchoRequest\x1a#.scanoss.api.common.v2.EchoResponse\"\"\x82\xd3\xe4\x93\x02\x1c\"\x17/api/v2/provenance/echo:\x01*\x12\x94\x01\n\x16GetComponentProvenance\x12\".scanoss.api.common.v2.PurlRequest\x1a-.scanoss.api.provenance.v2.ProvenanceResponse\"\'\x82\xd3\xe4\x93\x02!\"\x1c/api/v2/provenance/countries:\x01*B\x94\x02Z5github.com/scanoss/papi/api/provenancev2;provenancev2\x92\x41\xd9\x01\x12s\n\x1aSCANOSS Provenance Service\"P\n\x12scanoss-provenance\x12%https://github.com/scanoss/provenance\x1a\x13support@scanoss.com2\x03\x32.0*\x01\x01\x32\x10\x61pplication/json:\x10\x61pplication/jsonR;\n\x03\x34\x30\x34\x12\x34\n*Returned when the resource does not exist.\x12\x06\n\x04\x9a\x02\x01\x07\x62\x06proto3')
21
+
22
+ _globals = globals()
23
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
24
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'scanoss.api.provenance.v2.scanoss_provenance_pb2', _globals)
25
+ if _descriptor._USE_C_DESCRIPTORS == False:
26
+ _globals['DESCRIPTOR']._options = None
27
+ _globals['DESCRIPTOR']._serialized_options = b'Z5github.com/scanoss/papi/api/provenancev2;provenancev2\222A\331\001\022s\n\032SCANOSS Provenance Service\"P\n\022scanoss-provenance\022%https://github.com/scanoss/provenance\032\023support@scanoss.com2\0032.0*\001\0012\020application/json:\020application/jsonR;\n\003404\0224\n*Returned when the resource does not exist.\022\006\n\004\232\002\001\007'
28
+ _globals['_PROVENANCE'].methods_by_name['Echo']._options = None
29
+ _globals['_PROVENANCE'].methods_by_name['Echo']._serialized_options = b'\202\323\344\223\002\034\"\027/api/v2/provenance/echo:\001*'
30
+ _globals['_PROVENANCE'].methods_by_name['GetComponentProvenance']._options = None
31
+ _globals['_PROVENANCE'].methods_by_name['GetComponentProvenance']._serialized_options = b'\202\323\344\223\002!\"\034/api/v2/provenance/countries:\001*'
32
+ _globals['_PROVENANCERESPONSE']._serialized_start=202
33
+ _globals['_PROVENANCERESPONSE']._serialized_end=671
34
+ _globals['_PROVENANCERESPONSE_DECLAREDLOCATION']._serialized_start=347
35
+ _globals['_PROVENANCERESPONSE_DECLAREDLOCATION']._serialized_end=397
36
+ _globals['_PROVENANCERESPONSE_CURATEDLOCATION']._serialized_start=399
37
+ _globals['_PROVENANCERESPONSE_CURATEDLOCATION']._serialized_end=448
38
+ _globals['_PROVENANCERESPONSE_PURLS']._serialized_start=451
39
+ _globals['_PROVENANCERESPONSE_PURLS']._serialized_end=671
40
+ _globals['_PROVENANCE']._serialized_start=674
41
+ _globals['_PROVENANCE']._serialized_end=954
42
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,108 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
5
+ from scanoss.api.common.v2 import scanoss_common_pb2 as scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2
6
+ from scanoss.api.provenance.v2 import scanoss_provenance_pb2 as scanoss_dot_api_dot_provenance_dot_v2_dot_scanoss__provenance__pb2
7
+
8
+
9
+ class ProvenanceStub(object):
10
+ """*
11
+ Expose all of the SCANOSS Provenance RPCs here
12
+ """
13
+
14
+ def __init__(self, channel):
15
+ """Constructor.
16
+
17
+ Args:
18
+ channel: A grpc.Channel.
19
+ """
20
+ self.Echo = channel.unary_unary(
21
+ '/scanoss.api.provenance.v2.Provenance/Echo',
22
+ request_serializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoRequest.SerializeToString,
23
+ response_deserializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoResponse.FromString,
24
+ )
25
+ self.GetComponentProvenance = channel.unary_unary(
26
+ '/scanoss.api.provenance.v2.Provenance/GetComponentProvenance',
27
+ request_serializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.PurlRequest.SerializeToString,
28
+ response_deserializer=scanoss_dot_api_dot_provenance_dot_v2_dot_scanoss__provenance__pb2.ProvenanceResponse.FromString,
29
+ )
30
+
31
+
32
+ class ProvenanceServicer(object):
33
+ """*
34
+ Expose all of the SCANOSS Provenance RPCs here
35
+ """
36
+
37
+ def Echo(self, request, context):
38
+ """Standard echo
39
+ """
40
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
41
+ context.set_details('Method not implemented!')
42
+ raise NotImplementedError('Method not implemented!')
43
+
44
+ def GetComponentProvenance(self, request, context):
45
+ """Get Provenance countrues associated with a list of PURLs
46
+ """
47
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
48
+ context.set_details('Method not implemented!')
49
+ raise NotImplementedError('Method not implemented!')
50
+
51
+
52
+ def add_ProvenanceServicer_to_server(servicer, server):
53
+ rpc_method_handlers = {
54
+ 'Echo': grpc.unary_unary_rpc_method_handler(
55
+ servicer.Echo,
56
+ request_deserializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoRequest.FromString,
57
+ response_serializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoResponse.SerializeToString,
58
+ ),
59
+ 'GetComponentProvenance': grpc.unary_unary_rpc_method_handler(
60
+ servicer.GetComponentProvenance,
61
+ request_deserializer=scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.PurlRequest.FromString,
62
+ response_serializer=scanoss_dot_api_dot_provenance_dot_v2_dot_scanoss__provenance__pb2.ProvenanceResponse.SerializeToString,
63
+ ),
64
+ }
65
+ generic_handler = grpc.method_handlers_generic_handler(
66
+ 'scanoss.api.provenance.v2.Provenance', rpc_method_handlers)
67
+ server.add_generic_rpc_handlers((generic_handler,))
68
+
69
+
70
+ # This class is part of an EXPERIMENTAL API.
71
+ class Provenance(object):
72
+ """*
73
+ Expose all of the SCANOSS Provenance RPCs here
74
+ """
75
+
76
+ @staticmethod
77
+ def Echo(request,
78
+ target,
79
+ options=(),
80
+ channel_credentials=None,
81
+ call_credentials=None,
82
+ insecure=False,
83
+ compression=None,
84
+ wait_for_ready=None,
85
+ timeout=None,
86
+ metadata=None):
87
+ return grpc.experimental.unary_unary(request, target, '/scanoss.api.provenance.v2.Provenance/Echo',
88
+ scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoRequest.SerializeToString,
89
+ scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.EchoResponse.FromString,
90
+ options, channel_credentials,
91
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
92
+
93
+ @staticmethod
94
+ def GetComponentProvenance(request,
95
+ target,
96
+ options=(),
97
+ channel_credentials=None,
98
+ call_credentials=None,
99
+ insecure=False,
100
+ compression=None,
101
+ wait_for_ready=None,
102
+ timeout=None,
103
+ metadata=None):
104
+ return grpc.experimental.unary_unary(request, target, '/scanoss.api.provenance.v2.Provenance/GetComponentProvenance',
105
+ scanoss_dot_api_dot_common_dot_v2_dot_scanoss__common__pb2.PurlRequest.SerializeToString,
106
+ scanoss_dot_api_dot_provenance_dot_v2_dot_scanoss__provenance__pb2.ProvenanceResponse.FromString,
107
+ options, channel_credentials,
108
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
scanoss/cli.py CHANGED
@@ -198,6 +198,13 @@ def setup_args() -> None:
198
198
  help='Retrieve semgrep issues/findings for the given components')
199
199
  c_semgrep.set_defaults(func=comp_semgrep)
200
200
 
201
+ # Component Sub-command: component provenance
202
+ c_provenance = comp_sub.add_parser('provenance', aliases=['prov', 'prv'],
203
+ description=f'Show Provenance findings: {__version__}',
204
+ help='Retrieve provenance for the given components')
205
+ c_provenance.set_defaults(func=comp_provenance)
206
+
207
+
201
208
  # Component Sub-command: component search
202
209
  c_search = comp_sub.add_parser('search', aliases=['sc'],
203
210
  description=f'Search component details: {__version__}',
@@ -221,11 +228,11 @@ def setup_args() -> None:
221
228
  c_versions.set_defaults(func=comp_versions)
222
229
 
223
230
  # Common purl Component sub-command options
224
- for p in [c_crypto, c_vulns, c_semgrep]:
231
+ for p in [c_crypto, c_vulns, c_semgrep, c_provenance]:
225
232
  p.add_argument('--purl', '-p', type=str, nargs="*", help='Package URL - PURL to process.')
226
233
  p.add_argument('--input', '-i', type=str, help='Input file name')
227
234
  # Common Component sub-command options
228
- for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
235
+ for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
229
236
  p.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
230
237
  p.add_argument('--timeout', '-M', type=int, default=600,
231
238
  help='Timeout (in seconds) for API communication (optional - default 600)')
@@ -361,7 +368,7 @@ def setup_args() -> None:
361
368
  p.add_argument('--strip-snippet', '-N', type=str, action='append', help='Strip Snippet ID string from WFP.')
362
369
 
363
370
  # Global Scan/GRPC options
364
- for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
371
+ for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
365
372
  p.add_argument('--key', '-k', type=str,
366
373
  help='SCANOSS API Key token (optional - not required for default OSSKB URL)')
367
374
  p.add_argument('--proxy', type=str, help='Proxy URL to use for connections (optional). '
@@ -375,7 +382,7 @@ def setup_args() -> None:
375
382
  '"GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/path/to/cacert.pem" for gRPC')
376
383
 
377
384
  # Global GRPC options
378
- for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
385
+ for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
379
386
  p.add_argument('--api2url', type=str,
380
387
  help='SCANOSS gRPC API 2.0 URL (optional - default: https://api.osskb.org)')
381
388
  p.add_argument('--grpc-proxy', type=str, help='GRPC Proxy URL to use for connections (optional). '
@@ -383,7 +390,7 @@ def setup_args() -> None:
383
390
 
384
391
  # Help/Trace command options
385
392
  for p in [p_scan, p_wfp, p_dep, p_fc, p_cnv, p_c_loc, p_c_dwnld, p_p_proxy, c_crypto, c_vulns, c_search,
386
- c_versions, c_semgrep, p_results, p_undeclared, p_copyleft]:
393
+ c_versions, c_semgrep, p_results, p_undeclared, p_copyleft, c_provenance]:
387
394
  p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages')
388
395
  p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts')
389
396
  p.add_argument('--quiet', '-q', action='store_true', help='Enable quiet mode')
@@ -473,7 +480,7 @@ def wfp(parser, args):
473
480
  if args.output:
474
481
  scan_output = args.output
475
482
  open(scan_output, 'w').close()
476
-
483
+
477
484
  # Load scan settings
478
485
  scan_settings = None
479
486
  if not args.skip_settings_file:
@@ -1022,6 +1029,30 @@ def comp_semgrep(parser, args):
1022
1029
  if not comps.get_semgrep_details(args.input, args.purl, args.output):
1023
1030
  exit(1)
1024
1031
 
1032
+ def comp_provenance(parser, args):
1033
+ """
1034
+ Run the "component provenance" sub-command
1035
+ Parameters
1036
+ ----------
1037
+ parser: ArgumentParser
1038
+ command line parser object
1039
+ args: Namespace
1040
+ Parsed arguments
1041
+ """
1042
+ if (not args.purl and not args.input) or (args.purl and args.input):
1043
+ print_stderr('Please specify an input file or purl to decorate (--purl or --input)')
1044
+ parser.parse_args([args.subparser, args.subparsercmd, '-h'])
1045
+ exit(1)
1046
+ if args.ca_cert and not os.path.exists(args.ca_cert):
1047
+ print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
1048
+ exit(1)
1049
+ pac_file = get_pac_file(args.pac)
1050
+ comps = Components(debug=args.debug, trace=args.trace, quiet=args.quiet, grpc_url=args.api2url, api_key=args.key,
1051
+ ca_cert=args.ca_cert, proxy=args.proxy, grpc_proxy=args.grpc_proxy, pac=pac_file,
1052
+ timeout=args.timeout)
1053
+ if not comps.get_provenance_details(args.input, args.purl, args.output):
1054
+ exit(1)
1055
+
1025
1056
  def comp_search(parser, args):
1026
1057
  """
1027
1058
  Run the "component search" sub-command
scanoss/components.py CHANGED
@@ -24,7 +24,7 @@
24
24
  import json
25
25
  import os
26
26
  import sys
27
- from typing import TextIO
27
+ from typing import TextIO, Optional, List
28
28
 
29
29
  from pypac.parser import PACFile
30
30
 
@@ -62,13 +62,13 @@ class Components(ScanossBase):
62
62
  ver_details=ver_details, ca_cert=ca_cert, proxy=proxy, pac=pac,
63
63
  grpc_proxy=grpc_proxy, timeout=timeout)
64
64
 
65
- def load_purls(self, json_file: str = None, purls: [] = None) -> dict:
65
+ def load_purls(self, json_file: Optional[str] = None, purls: Optional[List[str]] = None) -> Optional[dict]:
66
66
  """
67
67
  Load the specified purls and return a dictionary
68
68
 
69
69
  :param json_file: JSON PURL file (optional)
70
70
  :param purls: list of PURLs (optional)
71
- :return: PURL Request dictionary
71
+ :return: PURL Request dictionary or None
72
72
  """
73
73
  if json_file:
74
74
  if not os.path.isfile(json_file) or not os.access(json_file, os.R_OK):
@@ -81,6 +81,9 @@ class Components(ScanossBase):
81
81
  self.print_stderr(f'ERROR: Problem parsing input JSON: {e}')
82
82
  return None
83
83
  elif purls:
84
+ if not all(isinstance(purl, str) for purl in purls):
85
+ self.print_stderr('ERROR: PURLs must be a list of strings.')
86
+ return None
84
87
  parsed_purls = []
85
88
  for p in purls:
86
89
  parsed_purls.append({'purl': p})
@@ -302,3 +305,29 @@ class Components(ScanossBase):
302
305
  self.print_msg(f'Results written to: {output_file}')
303
306
  self._close_file(output_file, file)
304
307
  return success
308
+
309
+ def get_provenance_details(self, json_file: str = None, purls: [] = None, output_file: str = None) -> bool:
310
+ """
311
+ Retrieve the semgrep details for the supplied PURLs
312
+
313
+ :param json_file: PURL JSON request file (optional)
314
+ :param purls: PURL request array (optional)
315
+ :param output_file: output filename (optional). Default: STDOUT
316
+ :return: True on success, False otherwise
317
+ """
318
+ success = False
319
+ purls_request = self.load_purls(json_file, purls)
320
+ if purls_request is None or len(purls_request) == 0:
321
+ return False
322
+ file = self._open_file_or_sdtout(output_file)
323
+ if file is None:
324
+ return False
325
+ self.print_msg('Sending PURLs to Provenance API for decoration...')
326
+ response = self.grpc_api.get_provenance_json(purls_request)
327
+ if response:
328
+ print(json.dumps(response, indent=2, sort_keys=True), file=file)
329
+ success = True
330
+ if output_file:
331
+ self.print_msg(f'Results written to: {output_file}')
332
+ self._close_file(output_file, file)
333
+ return success
@@ -1 +1 @@
1
- date: 20250130190618, utime: 1738263978
1
+ date: 20250205133848, utime: 1738762728
scanoss/scanossgrpc.py CHANGED
@@ -37,6 +37,7 @@ from .api.components.v2.scanoss_components_pb2_grpc import ComponentsStub
37
37
  from .api.cryptography.v2.scanoss_cryptography_pb2_grpc import CryptographyStub
38
38
  from .api.dependencies.v2.scanoss_dependencies_pb2_grpc import DependenciesStub
39
39
  from .api.vulnerabilities.v2.scanoss_vulnerabilities_pb2_grpc import VulnerabilitiesStub
40
+ from .api.provenance.v2.scanoss_provenance_pb2_grpc import ProvenanceStub
40
41
  from .api.semgrep.v2.scanoss_semgrep_pb2_grpc import SemgrepStub
41
42
  from .api.cryptography.v2.scanoss_cryptography_pb2 import AlgorithmResponse
42
43
  from .api.dependencies.v2.scanoss_dependencies_pb2 import DependencyRequest, DependencyResponse
@@ -45,6 +46,8 @@ from .api.vulnerabilities.v2.scanoss_vulnerabilities_pb2 import VulnerabilityRes
45
46
  from .api.semgrep.v2.scanoss_semgrep_pb2 import SemgrepResponse
46
47
  from .api.components.v2.scanoss_components_pb2 import (CompSearchRequest, CompSearchResponse,
47
48
  CompVersionRequest, CompVersionResponse)
49
+ from .api.provenance.v2.scanoss_provenance_pb2 import ProvenanceResponse
50
+
48
51
  from .scanossbase import ScanossBase
49
52
  from . import __version__
50
53
 
@@ -113,6 +116,7 @@ class ScanossGrpc(ScanossBase):
113
116
  self.dependencies_stub = DependenciesStub(grpc.insecure_channel(self.url))
114
117
  self.semgrep_stub = SemgrepStub(grpc.insecure_channel(self.url))
115
118
  self.vuln_stub = VulnerabilitiesStub(grpc.insecure_channel(self.url))
119
+ self.provenance_stub = ProvenanceStub(grpc.insecure_channel(self.url))
116
120
  else:
117
121
  if ca_cert is not None:
118
122
  credentials = grpc.ssl_channel_credentials(cert_data) # secure with specified certificate
@@ -123,6 +127,7 @@ class ScanossGrpc(ScanossBase):
123
127
  self.dependencies_stub = DependenciesStub(grpc.secure_channel(self.url, credentials))
124
128
  self.semgrep_stub = SemgrepStub(grpc.secure_channel(self.url, credentials))
125
129
  self.vuln_stub = VulnerabilitiesStub(grpc.secure_channel(self.url, credentials))
130
+ self.provenance_stub = ProvenanceStub(grpc.secure_channel(self.url, credentials))
126
131
 
127
132
  @classmethod
128
133
  def _load_cert(cls, cert_file: str) -> bytes:
@@ -383,13 +388,15 @@ class ScanossGrpc(ScanossBase):
383
388
  self.print_debug(f'Checking response status (rqId: {request_id}): {status_response}')
384
389
  status_code: StatusCode = status_response.status
385
390
  if status_code > 1:
391
+ ret_val = False # default to failed
386
392
  msg = "Unsuccessful"
387
393
  if status_code == 2:
388
394
  msg = "Succeeded with warnings"
395
+ ret_val = True # No need to fail as it succeeded with warnings
389
396
  elif status_code == 3:
390
397
  msg = "Failed with warnings"
391
398
  self.print_stderr(f'{msg} (rqId: {request_id} - status: {status_code}): {status_response.message}')
392
- return False
399
+ return ret_val
393
400
  return True
394
401
 
395
402
  def _get_proxy_config(self):
@@ -414,6 +421,33 @@ class ScanossGrpc(ScanossBase):
414
421
  os.environ["http_proxy"] = proxies.get("http") or ""
415
422
  os.environ["https_proxy"] = proxies.get("https") or ""
416
423
 
424
+ def get_provenance_json(self, purls: dict) -> dict:
425
+ """
426
+ Client function to call the rpc for GetComponentProvenance
427
+ :param purls: Message to send to the service
428
+ :return: Server response or None
429
+ """
430
+ if not purls:
431
+ self.print_stderr(f'ERROR: No message supplied to send to gRPC service.')
432
+ return None
433
+ request_id = str(uuid.uuid4())
434
+ resp: ProvenanceResponse
435
+ try:
436
+ request = ParseDict(purls, PurlRequest()) # Parse the JSON/Dict into the purl request object
437
+ metadata = self.metadata[:]
438
+ metadata.append(('x-request-id', request_id)) # Set a Request ID
439
+ self.print_debug(f'Sending data for provenance decoration (rqId: {request_id})...')
440
+ resp = self.provenance_stub.GetComponentProvenance(request, metadata=metadata, timeout=self.timeout)
441
+ except Exception as e:
442
+ self.print_stderr(f'ERROR: {e.__class__.__name__} Problem encountered sending gRPC message '
443
+ f'(rqId: {request_id}): {e}')
444
+ else:
445
+ if resp:
446
+ if not self._check_status_response(resp.status, request_id):
447
+ return None
448
+ resp_dict = MessageToDict(resp, preserving_proto_field_name=True) # Convert gRPC response to a dict
449
+ return resp_dict
450
+ return None
417
451
  #
418
452
  # End of ScanossGrpc Class
419
453
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: scanoss
3
- Version: 1.19.6
3
+ Version: 1.20.0
4
4
  Summary: Simple Python library to leverage the SCANOSS APIs
5
5
  Home-page: https://scanoss.com
6
6
  Author: SCANOSS
@@ -4,9 +4,9 @@ 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=DKQ4C2kCmfEN06YVkz4aiecv2uhkktLk14P24tTMmJ8,1163
8
- scanoss/cli.py,sha256=6mAO8bBFiQ8DVEsWNs45x8luT51FxnxfE8GT_jQWWNE,51554
9
- scanoss/components.py,sha256=ZHZ1KA69shxOASZK7USD9yPTITpAc_RXL5q5zpDK23o,12590
7
+ scanoss/__init__.py,sha256=cs78w1v2fZ3JVQdN5zxPVWRoM_AcHHRAo26bCr0R63k,1163
8
+ scanoss/cli.py,sha256=pQwdt-LQGc5Iy3WKffYmtFcyM93LOILpiDyEPlVHggU,53034
9
+ scanoss/components.py,sha256=u7x3tdCQUTvbB97wTSuwfjtrhW6BsFdkeQqUmPZGPF4,13957
10
10
  scanoss/csvoutput.py,sha256=hBwr_Fc6mBdOdXgyQcdFrockYH-PJ0jblowlExJ6OPg,9925
11
11
  scanoss/cyclonedx.py,sha256=QWDNvn6o_Y6xWYEr0-qDgDtNOTaHccxPeHFoNZLx0is,12766
12
12
  scanoss/file_filters.py,sha256=HGGECJ-P0LL8pg8YVO4BP8ql24tCnanx0_S2wA8EWis,16642
@@ -17,7 +17,7 @@ scanoss/scanner.py,sha256=hF8N8XXSwYw93htpqv0h0t-IqswG_bcxH7awe4JA5Aw,45374
17
17
  scanoss/scanoss_settings.py,sha256=VwcvbUYjhPv6svBhtOlxULrY3TnUZgLOlcmaU_f2jTk,10590
18
18
  scanoss/scanossapi.py,sha256=TJxPctr-0DTn_26LfM__OAMfntaXzvheFTbdmU-5pnM,11953
19
19
  scanoss/scanossbase.py,sha256=zMDRCLbrcoRvYEKQRuZXnBiVY4_Vsplmg_APbB65oaU,3084
20
- scanoss/scanossgrpc.py,sha256=ythZkr6F0P0hl_KPYoHkos_IL97TxLKeYfAouX_CUnM,20491
20
+ scanoss/scanossgrpc.py,sha256=NsHd8eIDOVcMcdR_o1gAKQu9d-O0z0qUwrOJ3BlrooA,22348
21
21
  scanoss/scanpostprocessor.py,sha256=OY75PLUMRas7hyjrHTCKiu4X-N_Z5t710wc9f3HPHqw,11074
22
22
  scanoss/scantype.py,sha256=R2-ExLGOrYxaJFtIK2AEo2caD0XrN1zpF5q1qT9Zsyc,1326
23
23
  scanoss/spdxlite.py,sha256=REChAWV-6qhp16jc4X2lMb1v7VvYiDH5nN9VDV3fDaQ,15828
@@ -39,6 +39,10 @@ scanoss/api/dependencies/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70
39
39
  scanoss/api/dependencies/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
40
40
  scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py,sha256=mHeRlzUEHFFWQyJnpoJ7MG86p8Gqc64lfPG2nPK1n9A,5118
41
41
  scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py,sha256=JknWEAxZX21YyYjXs8BL2IUp52wqf_2a1Tn337i_3-g,4815
42
+ scanoss/api/provenance/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
43
+ scanoss/api/provenance/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
44
+ scanoss/api/provenance/v2/scanoss_provenance_pb2.py,sha256=cxcyIWxhYzjjRPdgTeEfLdOA3XfI_SuYi1OMZMv1c-Q,4443
45
+ scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py,sha256=87EYBU4fiVEQ8hDkOTzP29KgNPAbxDgEV85pZSPqPXE,4799
42
46
  scanoss/api/scanning/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
43
47
  scanoss/api/scanning/v2/__init__.py,sha256=KlDD87JmyZP-10T-fuJo0_v2zt1gxWfTgs70wjky9xg,1139
44
48
  scanoss/api/scanning/v2/scanoss_scanning_pb2.py,sha256=bod1HOOmiewM8gLH7LAwmK5BNAm0NxUoUwUZb9zs8LY,2550
@@ -51,7 +55,7 @@ scanoss/api/vulnerabilities/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEK
51
55
  scanoss/api/vulnerabilities/v2/__init__.py,sha256=FLQtiDiv85Q1Chk-sJ9ky9WOV1mulZhEKjiBihlwiaM,1139
52
56
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
53
57
  scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
54
- scanoss/data/build_date.txt,sha256=pY9qGh_8jGdbdRkRMjlqers462ORg9vEPvGq8Vk2PPU,40
58
+ scanoss/data/build_date.txt,sha256=SOOdGv4jmfsYyqJ4HbzIPZoLJcG2RLXv3tyKuaOnX8E,40
55
59
  scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
56
60
  scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
57
61
  scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
@@ -62,9 +66,9 @@ scanoss/inspection/undeclared_component.py,sha256=QvlBgYpytQhaWlVqrz3p8JPIGbsX8v
62
66
  scanoss/inspection/utils/license_utils.py,sha256=mIaoVWXMA6shkRQmgmiP2mWchjxX4ex8LWs91Nf6rq4,5093
63
67
  scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
64
68
  scanoss/utils/file.py,sha256=0Dv0Si8qVOGjauOboqos_caZhLR6qc6qEyKZDNwG3VA,2933
65
- scanoss-1.19.6.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
66
- scanoss-1.19.6.dist-info/METADATA,sha256=J5Gz8LczPYkxOAQrJuheiw2vIprpOtxx1arxKoEX5QU,6019
67
- scanoss-1.19.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
68
- scanoss-1.19.6.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
69
- scanoss-1.19.6.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
70
- scanoss-1.19.6.dist-info/RECORD,,
69
+ scanoss-1.20.0.dist-info/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
70
+ scanoss-1.20.0.dist-info/METADATA,sha256=KwnfB_BgcJot2j6MMJfUVabjTiwWOg0UUiTNREb0cjg,6019
71
+ scanoss-1.20.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
72
+ scanoss-1.20.0.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
73
+ scanoss-1.20.0.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
74
+ scanoss-1.20.0.dist-info/RECORD,,