scanoss 1.12.2__py3-none-any.whl → 1.43.1__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.
Files changed (109) hide show
  1. protoc_gen_swagger/__init__.py +13 -13
  2. protoc_gen_swagger/options/__init__.py +13 -13
  3. protoc_gen_swagger/options/annotations_pb2.py +18 -12
  4. protoc_gen_swagger/options/annotations_pb2.pyi +48 -0
  5. protoc_gen_swagger/options/annotations_pb2_grpc.py +20 -0
  6. protoc_gen_swagger/options/openapiv2_pb2.py +110 -99
  7. protoc_gen_swagger/options/openapiv2_pb2.pyi +1317 -0
  8. protoc_gen_swagger/options/openapiv2_pb2_grpc.py +20 -0
  9. scanoss/__init__.py +18 -18
  10. scanoss/api/__init__.py +17 -17
  11. scanoss/api/common/__init__.py +17 -17
  12. scanoss/api/common/v2/__init__.py +17 -17
  13. scanoss/api/common/v2/scanoss_common_pb2.py +49 -20
  14. scanoss/api/common/v2/scanoss_common_pb2_grpc.py +25 -0
  15. scanoss/api/components/__init__.py +17 -17
  16. scanoss/api/components/v2/__init__.py +17 -17
  17. scanoss/api/components/v2/scanoss_components_pb2.py +68 -43
  18. scanoss/api/components/v2/scanoss_components_pb2_grpc.py +83 -22
  19. scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +136 -21
  20. scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +766 -13
  21. scanoss/api/dependencies/__init__.py +17 -17
  22. scanoss/api/dependencies/v2/__init__.py +17 -17
  23. scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +56 -29
  24. scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +94 -8
  25. scanoss/api/geoprovenance/__init__.py +23 -0
  26. scanoss/api/geoprovenance/v2/__init__.py +23 -0
  27. scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2.py +92 -0
  28. scanoss/api/geoprovenance/v2/scanoss_geoprovenance_pb2_grpc.py +381 -0
  29. scanoss/api/licenses/__init__.py +23 -0
  30. scanoss/api/licenses/v2/__init__.py +23 -0
  31. scanoss/api/licenses/v2/scanoss_licenses_pb2.py +84 -0
  32. scanoss/api/licenses/v2/scanoss_licenses_pb2_grpc.py +302 -0
  33. scanoss/api/scanning/__init__.py +17 -17
  34. scanoss/api/scanning/v2/__init__.py +17 -17
  35. scanoss/api/scanning/v2/scanoss_scanning_pb2.py +42 -13
  36. scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +86 -7
  37. scanoss/api/semgrep/__init__.py +17 -17
  38. scanoss/api/semgrep/v2/__init__.py +17 -17
  39. scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +50 -23
  40. scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +151 -16
  41. scanoss/api/vulnerabilities/__init__.py +17 -17
  42. scanoss/api/vulnerabilities/v2/__init__.py +17 -17
  43. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +78 -31
  44. scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +282 -18
  45. scanoss/cli.py +2359 -370
  46. scanoss/components.py +187 -94
  47. scanoss/constants.py +22 -0
  48. scanoss/cryptography.py +308 -0
  49. scanoss/csvoutput.py +91 -58
  50. scanoss/cyclonedx.py +221 -63
  51. scanoss/data/build_date.txt +1 -1
  52. scanoss/data/osadl-copyleft.json +133 -0
  53. scanoss/data/scanoss-settings-schema.json +254 -0
  54. scanoss/delta.py +197 -0
  55. scanoss/export/__init__.py +23 -0
  56. scanoss/export/dependency_track.py +227 -0
  57. scanoss/file_filters.py +582 -0
  58. scanoss/filecount.py +75 -69
  59. scanoss/gitlabqualityreport.py +214 -0
  60. scanoss/header_filter.py +563 -0
  61. scanoss/inspection/__init__.py +23 -0
  62. scanoss/inspection/policy_check/__init__.py +0 -0
  63. scanoss/inspection/policy_check/dependency_track/__init__.py +0 -0
  64. scanoss/inspection/policy_check/dependency_track/project_violation.py +479 -0
  65. scanoss/inspection/policy_check/policy_check.py +222 -0
  66. scanoss/inspection/policy_check/scanoss/__init__.py +0 -0
  67. scanoss/inspection/policy_check/scanoss/copyleft.py +243 -0
  68. scanoss/inspection/policy_check/scanoss/undeclared_component.py +309 -0
  69. scanoss/inspection/summary/__init__.py +0 -0
  70. scanoss/inspection/summary/component_summary.py +170 -0
  71. scanoss/inspection/summary/license_summary.py +191 -0
  72. scanoss/inspection/summary/match_summary.py +341 -0
  73. scanoss/inspection/utils/file_utils.py +44 -0
  74. scanoss/inspection/utils/license_utils.py +123 -0
  75. scanoss/inspection/utils/markdown_utils.py +63 -0
  76. scanoss/inspection/utils/scan_result_processor.py +417 -0
  77. scanoss/osadl.py +125 -0
  78. scanoss/results.py +275 -0
  79. scanoss/scancodedeps.py +87 -38
  80. scanoss/scanner.py +431 -539
  81. scanoss/scanners/__init__.py +23 -0
  82. scanoss/scanners/container_scanner.py +476 -0
  83. scanoss/scanners/folder_hasher.py +358 -0
  84. scanoss/scanners/scanner_config.py +73 -0
  85. scanoss/scanners/scanner_hfh.py +252 -0
  86. scanoss/scanoss_settings.py +337 -0
  87. scanoss/scanossapi.py +140 -101
  88. scanoss/scanossbase.py +59 -22
  89. scanoss/scanossgrpc.py +799 -251
  90. scanoss/scanpostprocessor.py +294 -0
  91. scanoss/scantype.py +22 -21
  92. scanoss/services/dependency_track_service.py +132 -0
  93. scanoss/spdxlite.py +532 -174
  94. scanoss/threadeddependencies.py +148 -47
  95. scanoss/threadedscanning.py +53 -37
  96. scanoss/utils/__init__.py +23 -0
  97. scanoss/utils/abstract_presenter.py +103 -0
  98. scanoss/utils/crc64.py +96 -0
  99. scanoss/utils/file.py +84 -0
  100. scanoss/utils/scanoss_scan_results_utils.py +41 -0
  101. scanoss/utils/simhash.py +198 -0
  102. scanoss/winnowing.py +241 -63
  103. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/METADATA +18 -9
  104. scanoss-1.43.1.dist-info/RECORD +110 -0
  105. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/WHEEL +1 -1
  106. scanoss-1.12.2.dist-info/RECORD +0 -58
  107. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/entry_points.txt +0 -0
  108. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info/licenses}/LICENSE +0 -0
  109. {scanoss-1.12.2.dist-info → scanoss-1.43.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,227 @@
1
+ """
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright (c) 2025, 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
+ """
24
+
25
+ import base64
26
+ import json
27
+ import traceback
28
+
29
+ import requests
30
+
31
+ from ..cyclonedx import CycloneDx
32
+ from ..scanossbase import ScanossBase
33
+ from ..services.dependency_track_service import DependencyTrackService
34
+ from ..utils.file import validate_json_file
35
+
36
+
37
+ def _build_payload(encoded_sbom: str, project_id, project_name, project_version) -> dict:
38
+ """
39
+ Build the API payload
40
+
41
+ Args:
42
+ encoded_sbom: Base64 encoded SBOM
43
+
44
+ Returns:
45
+ API payload dictionary
46
+ """
47
+ if project_id:
48
+ return {'project': project_id, 'bom': encoded_sbom}
49
+ else:
50
+ return {
51
+ 'projectName': project_name,
52
+ 'projectVersion': project_version,
53
+ 'autoCreate': True,
54
+ 'bom': encoded_sbom,
55
+ }
56
+
57
+
58
+ class DependencyTrackExporter(ScanossBase):
59
+ """
60
+ Class for exporting SBOM files to Dependency Track
61
+ """
62
+ def __init__( # noqa: PLR0913
63
+ self,
64
+ url: str = None,
65
+ apikey: str = None,
66
+ output: str = None,
67
+ debug: bool = False,
68
+ trace: bool = False,
69
+ quiet: bool = False
70
+ ):
71
+ """
72
+ Initialize DependencyTrackExporter
73
+
74
+ Args:
75
+ url: Dependency Track URL
76
+ apikey: Dependency Track API Key
77
+ output: File to store output response data (optional)
78
+ debug: Enable debug output
79
+ trace: Enable trace output
80
+ quiet: Enable quiet mode
81
+ """
82
+ super().__init__(debug=debug, trace=trace, quiet=quiet)
83
+ self.url = url.rstrip('/')
84
+ self.apikey = apikey
85
+ self.output = output
86
+ self.dt_service = DependencyTrackService(self.apikey, self.url, debug=debug, trace=trace, quiet=quiet)
87
+
88
+ def _read_and_validate_sbom(self, input_file: str) -> dict:
89
+ """
90
+ Read and validate the SBOM file
91
+
92
+ Args:
93
+ input_file: Path to the SBOM file
94
+
95
+ Returns:
96
+ Parsed SBOM content as dictionary
97
+
98
+ Raises:
99
+ ValueError: If the file doesn't exist or is invalid or not a valid CycloneDX SBOM
100
+ """
101
+ result = validate_json_file(input_file)
102
+ if not result.is_valid:
103
+ raise ValueError(f'Invalid JSON file: {result.error}')
104
+
105
+ cdx = CycloneDx(debug=self.debug)
106
+ if not cdx.is_cyclonedx_json(json.dumps(result.data)):
107
+ raise ValueError(f'Input file is not a valid CycloneDX SBOM: {input_file}')
108
+ return result.data
109
+
110
+ def _encode_sbom(self, sbom_content: dict) -> str:
111
+ """
112
+ Encode SBOM content to base64
113
+
114
+ Args:
115
+ sbom_content: SBOM dictionary
116
+
117
+ Returns:
118
+ Base64 encoded string
119
+ """
120
+ if not sbom_content:
121
+ self.print_stderr('Warning: Empty SBOM content provided')
122
+ return ''
123
+ # Check if SBOM has no components (empty scan results)
124
+ components = sbom_content.get('components', [])
125
+ if len(components) == 0:
126
+ self.print_msg('Notice: SBOM contains no components (empty scan results)')
127
+ json_str = json.dumps(sbom_content, separators=(',', ':'))
128
+ encoded = base64.b64encode(json_str.encode('utf-8')).decode('utf-8')
129
+ return encoded
130
+
131
+ def upload_sbom_file(self, input_file, project_id, project_name, project_version, output_file):
132
+ """
133
+ Uploads an SBOM file to the specified project with an
134
+ optional output file and processes the file content for validation.
135
+
136
+ Args:
137
+ input_file (str): The path to the SBOM file to be read and uploaded.
138
+ project_id (str): The unique identifier of the project to which the SBOM is being uploaded.
139
+ project_name (str): The name of the project to which the SBOM is being uploaded.
140
+ project_version (str): The version of the project to which the SBOM is being uploaded.
141
+ output_file (str): The path to save output related to the SBOM upload process.
142
+
143
+ Returns:
144
+ bool: Returns True if the SBOM file was uploaded successfully, False otherwise.
145
+
146
+ Raises:
147
+ ValueError: Raised if there are validation issues with the SBOM content.
148
+ """
149
+ try:
150
+ if not self.quiet:
151
+ self.print_stderr(f'Reading SBOM file: {input_file}')
152
+ sbom_content = self._read_and_validate_sbom(input_file)
153
+ return self.upload_sbom_contents(sbom_content, project_id, project_name, project_version, output_file)
154
+ except ValueError as e:
155
+ self.print_stderr(f'Validation error: {e}')
156
+ return False
157
+
158
+ def upload_sbom_contents(self, sbom_content: dict, project_id, project_name, project_version, output_file) -> bool:
159
+ """
160
+ Uploads an SBOM to a Dependency Track server.
161
+
162
+ Parameters:
163
+ sbom_content (dict): The SBOM content in dictionary format to be uploaded.
164
+ project_id: The unique identifier for the project.
165
+ project_name: The name of the project in Dependency Track.
166
+ project_version: The version of the project in Dependency Track.
167
+ output_file: The path to the file where the token and UUID data
168
+ should be written. If not provided, the data will be written to
169
+ standard output.
170
+
171
+ Returns:
172
+ bool: True if the upload is successful; False otherwise.
173
+
174
+ Raises:
175
+ ValueError: If the SBOM encoding process fails.
176
+ requests.exceptions.RequestException: If an error occurs during the HTTP request.
177
+ Exception: For any other unexpected error.
178
+ """
179
+ if not project_id and not (project_name and project_version):
180
+ self.print_stderr('Error: Missing project id or name and version.')
181
+ return False
182
+ output = self.output
183
+ if output_file:
184
+ output = output_file
185
+ try:
186
+ self.print_debug('Encoding SBOM to base64')
187
+ payload = _build_payload(self._encode_sbom(sbom_content), project_id, project_name, project_version)
188
+ url = f'{self.url}/api/v1/bom'
189
+ headers = {'Content-Type': 'application/json', 'X-Api-Key': self.apikey}
190
+ self.print_trace(f'URL: {url}, Headers: {headers}, Payload keys: {list(payload.keys())}')
191
+ self.print_msg('Uploading SBOM to Dependency Track...')
192
+ response = requests.put(url, json=payload, headers=headers)
193
+ response.raise_for_status()
194
+ # Treat any 2xx status as success
195
+ if (requests.codes.ok <= response.status_code < requests.codes.multiple_choices and
196
+ response.status_code != requests.codes.no_content):
197
+ self.print_msg('SBOM uploaded successfully')
198
+ try:
199
+ response_data = response.json()
200
+ token = ''
201
+ project_uuid = project_id
202
+ if 'token' in response_data:
203
+ token = response_data['token']
204
+ if project_name and project_version:
205
+ project_data = self.dt_service.get_project_by_name_version(project_name, project_version)
206
+ if project_data:
207
+ project_uuid = project_data.get("uuid", project_id)
208
+ token_json = json.dumps(
209
+ {"token": token, "project_uuid": project_uuid},
210
+ indent=2
211
+ )
212
+ self.print_to_file_or_stdout(token_json, output)
213
+ except json.JSONDecodeError:
214
+ pass
215
+ return True
216
+ else:
217
+ self.print_stderr(f'Upload failed with status code: {response.status_code}')
218
+ self.print_stderr(f'Response: {response.text}')
219
+ except ValueError as e:
220
+ self.print_stderr(f'DT SBOM Upload Validation error: {e}')
221
+ except requests.exceptions.RequestException as e:
222
+ self.print_stderr(f'DT API Request error: {e}')
223
+ except Exception as e:
224
+ self.print_stderr(f'Unexpected error: {e}')
225
+ if self.debug:
226
+ traceback.print_exc()
227
+ return False