scanoss 1.30.0__py3-none-any.whl → 1.31.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.
- scanoss/__init__.py +1 -1
- scanoss/cli.py +572 -188
- scanoss/data/build_date.txt +1 -1
- scanoss/export/dependency_track.py +101 -100
- scanoss/file_filters.py +1 -5
- scanoss/inspection/dependency_track/project_violation.py +449 -0
- scanoss/inspection/policy_check.py +54 -23
- scanoss/inspection/{component_summary.py → raw/component_summary.py} +3 -3
- scanoss/inspection/{copyleft.py → raw/copyleft.py} +63 -54
- scanoss/inspection/{license_summary.py → raw/license_summary.py} +5 -4
- scanoss/inspection/{inspect_base.py → raw/raw_base.py} +9 -6
- scanoss/inspection/{undeclared_component.py → raw/undeclared_component.py} +29 -25
- scanoss/services/dependency_track_service.py +131 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/METADATA +1 -1
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/RECORD +19 -17
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/WHEEL +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/entry_points.txt +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/licenses/LICENSE +0 -0
- {scanoss-1.30.0.dist-info → scanoss-1.31.1.dist-info}/top_level.txt +0 -0
|
@@ -23,12 +23,28 @@ SPDX-License-Identifier: MIT
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
import json
|
|
26
|
-
from
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from typing import Any, Dict, List
|
|
27
28
|
|
|
28
|
-
from
|
|
29
|
+
from ..policy_check import PolicyStatus
|
|
30
|
+
from .raw_base import RawBase
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
@dataclass
|
|
34
|
+
class License:
|
|
35
|
+
spdxid: str
|
|
36
|
+
copyleft: bool
|
|
37
|
+
url: str
|
|
38
|
+
source: str
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class Component:
|
|
42
|
+
purl: str
|
|
43
|
+
version: str
|
|
44
|
+
licenses: List[License]
|
|
45
|
+
status: str
|
|
46
|
+
|
|
47
|
+
class Copyleft(RawBase[Component]):
|
|
32
48
|
"""
|
|
33
49
|
SCANOSS Copyleft class
|
|
34
50
|
Inspects components for copyleft licenses
|
|
@@ -48,7 +64,7 @@ class Copyleft(PolicyCheck):
|
|
|
48
64
|
explicit: str = None,
|
|
49
65
|
):
|
|
50
66
|
"""
|
|
51
|
-
|
|
67
|
+
Initialise the Copyleft class.
|
|
52
68
|
|
|
53
69
|
:param debug: Enable debug mode
|
|
54
70
|
:param trace: Enable trace mode (default True)
|
|
@@ -61,7 +77,7 @@ class Copyleft(PolicyCheck):
|
|
|
61
77
|
:param exclude: Licenses to exclude from the analysis
|
|
62
78
|
:param explicit: Explicitly defined licenses
|
|
63
79
|
"""
|
|
64
|
-
super().__init__(debug, trace, quiet, filepath,
|
|
80
|
+
super().__init__(debug, trace, quiet, format_type,filepath, output ,status, name='Copyleft Policy')
|
|
65
81
|
self.license_util.init(include, exclude, explicit)
|
|
66
82
|
self.filepath = filepath
|
|
67
83
|
self.format = format
|
|
@@ -71,7 +87,7 @@ class Copyleft(PolicyCheck):
|
|
|
71
87
|
self.exclude = exclude
|
|
72
88
|
self.explicit = explicit
|
|
73
89
|
|
|
74
|
-
def _json(self, components: list) -> Dict[str, Any]:
|
|
90
|
+
def _json(self, components: list[Component]) -> Dict[str, Any]:
|
|
75
91
|
"""
|
|
76
92
|
Format the components with copyleft licenses as JSON.
|
|
77
93
|
|
|
@@ -88,61 +104,67 @@ class Copyleft(PolicyCheck):
|
|
|
88
104
|
'summary': f'{len(component_licenses)} component(s) with copyleft licenses were found.\n',
|
|
89
105
|
}
|
|
90
106
|
|
|
91
|
-
def _markdown(self, components: list) -> Dict[str, Any]:
|
|
107
|
+
def _markdown(self, components: list[Component]) -> Dict[str, Any]:
|
|
92
108
|
"""
|
|
93
109
|
Format the components with copyleft licenses as Markdown.
|
|
94
110
|
|
|
95
111
|
:param components: List of components with copyleft licenses
|
|
96
112
|
:return: Dictionary with formatted Markdown details and summary
|
|
97
113
|
"""
|
|
98
|
-
|
|
99
|
-
component_licenses = self._group_components_by_license(components)
|
|
100
|
-
headers = ['Component', 'License', 'URL', 'Copyleft']
|
|
101
|
-
centered_columns = [1, 4]
|
|
102
|
-
rows: [[]] = []
|
|
103
|
-
for comp_lic_item in component_licenses:
|
|
104
|
-
row = [
|
|
105
|
-
comp_lic_item['purl'],
|
|
106
|
-
comp_lic_item['spdxid'],
|
|
107
|
-
comp_lic_item['url'],
|
|
108
|
-
'YES' if comp_lic_item['copyleft'] else 'NO',
|
|
109
|
-
]
|
|
110
|
-
rows.append(row)
|
|
111
|
-
# End license loop
|
|
112
|
-
# End component loop
|
|
113
|
-
return {
|
|
114
|
-
'details': f'### Copyleft licenses\n{self.generate_table(headers, rows, centered_columns)}\n',
|
|
115
|
-
'summary': f'{len(component_licenses)} component(s) with copyleft licenses were found.\n',
|
|
116
|
-
}
|
|
114
|
+
return self._md_summary_generator(components, self.generate_table)
|
|
117
115
|
|
|
118
|
-
def _jira_markdown(self, components: list) -> Dict[str, Any]:
|
|
116
|
+
def _jira_markdown(self, components: list[Component]) -> Dict[str, Any]:
|
|
119
117
|
"""
|
|
120
118
|
Format the components with copyleft licenses as Markdown.
|
|
121
119
|
|
|
122
120
|
:param components: List of components with copyleft licenses
|
|
123
121
|
:return: Dictionary with formatted Markdown details and summary
|
|
124
122
|
"""
|
|
123
|
+
return self._md_summary_generator(components, self.generate_jira_table)
|
|
124
|
+
|
|
125
|
+
def _md_summary_generator(self, components: list[Component], table_generator):
|
|
126
|
+
"""
|
|
127
|
+
Generates a Markdown summary for components with a focus on copyleft licenses.
|
|
128
|
+
|
|
129
|
+
This function processes a list of components and groups them by their licenses.
|
|
130
|
+
For each group, the components are mapped with their license data and a tabular representation is created.
|
|
131
|
+
The generated Markdown summary includes a detailed table and a summary overview.
|
|
132
|
+
|
|
133
|
+
Parameters:
|
|
134
|
+
components: list[Component]
|
|
135
|
+
A list of Component objects to process for generating the summary.
|
|
136
|
+
table_generator
|
|
137
|
+
A callable function to generate tabular data for components.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
dict
|
|
141
|
+
A dictionary containing two keys:
|
|
142
|
+
- 'details': A detailed Markdown representation including a table of components
|
|
143
|
+
and associated copyleft license data.
|
|
144
|
+
- 'summary': A textual summary highlighting the total number of components
|
|
145
|
+
with copyleft licenses.
|
|
146
|
+
"""
|
|
125
147
|
# A component is considered unique by its combination of PURL (Package URL) and license
|
|
126
148
|
component_licenses = self._group_components_by_license(components)
|
|
127
149
|
headers = ['Component', 'License', 'URL', 'Copyleft']
|
|
128
150
|
centered_columns = [1, 4]
|
|
129
|
-
rows
|
|
151
|
+
rows = []
|
|
130
152
|
for comp_lic_item in component_licenses:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
row = [
|
|
154
|
+
comp_lic_item['purl'],
|
|
155
|
+
comp_lic_item['spdxid'],
|
|
156
|
+
comp_lic_item['url'],
|
|
157
|
+
'YES' if comp_lic_item['copyleft'] else 'NO',
|
|
158
|
+
]
|
|
159
|
+
rows.append(row)
|
|
160
|
+
# End license loop
|
|
139
161
|
# End component loop
|
|
140
162
|
return {
|
|
141
|
-
'details': f'{
|
|
163
|
+
'details': f'### Copyleft Licenses\n{table_generator(headers, rows, centered_columns)}',
|
|
142
164
|
'summary': f'{len(component_licenses)} component(s) with copyleft licenses were found.\n',
|
|
143
165
|
}
|
|
144
166
|
|
|
145
|
-
def
|
|
167
|
+
def _get_components_with_copyleft_licenses(self, components: list) -> list[Dict]:
|
|
146
168
|
"""
|
|
147
169
|
Filter the components list to include only those with copyleft licenses.
|
|
148
170
|
|
|
@@ -206,22 +228,9 @@ class Copyleft(PolicyCheck):
|
|
|
206
228
|
if components is None:
|
|
207
229
|
return PolicyStatus.ERROR.value, {}
|
|
208
230
|
# Get a list of copyleft components if they exist
|
|
209
|
-
copyleft_components = self.
|
|
210
|
-
#
|
|
211
|
-
|
|
212
|
-
if formatter is None:
|
|
213
|
-
return PolicyStatus.ERROR.value, {}
|
|
214
|
-
# Format the results
|
|
215
|
-
results = formatter(copyleft_components)
|
|
216
|
-
## Save outputs if required
|
|
217
|
-
self.print_to_file_or_stdout(results['details'], self.output)
|
|
218
|
-
self.print_to_file_or_stderr(results['summary'], self.status)
|
|
219
|
-
# Check to see if we have policy violations
|
|
220
|
-
if len(copyleft_components) <= 0:
|
|
221
|
-
return PolicyStatus.FAIL.value, results
|
|
222
|
-
return PolicyStatus.SUCCESS.value, results
|
|
223
|
-
|
|
224
|
-
|
|
231
|
+
copyleft_components = self._get_components_with_copyleft_licenses(components)
|
|
232
|
+
# Format the results and save to files if required
|
|
233
|
+
return self._generate_formatter_report(copyleft_components)
|
|
225
234
|
#
|
|
226
235
|
# End of Copyleft Class
|
|
227
236
|
#
|
|
@@ -24,10 +24,10 @@ SPDX-License-Identifier: MIT
|
|
|
24
24
|
|
|
25
25
|
import json
|
|
26
26
|
|
|
27
|
-
from .
|
|
27
|
+
from .raw_base import RawBase
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class LicenseSummary(
|
|
30
|
+
class LicenseSummary(RawBase):
|
|
31
31
|
"""
|
|
32
32
|
SCANOSS LicenseSummary class
|
|
33
33
|
Inspects results and generates comprehensive license summaries from detected components.
|
|
@@ -63,7 +63,7 @@ class LicenseSummary(InspectBase):
|
|
|
63
63
|
:param exclude: Licenses to exclude from the analysis
|
|
64
64
|
:param explicit: Explicitly defined licenses
|
|
65
65
|
"""
|
|
66
|
-
super().__init__(debug, trace, quiet, filepath, output)
|
|
66
|
+
super().__init__(debug, trace, quiet, filepath = filepath, output=output)
|
|
67
67
|
self.license_util.init(include, exclude, explicit)
|
|
68
68
|
self.filepath = filepath
|
|
69
69
|
self.output = output
|
|
@@ -123,7 +123,7 @@ class LicenseSummary(InspectBase):
|
|
|
123
123
|
:return: A list of processed components with license data, or `None` if `self.results` is not set.
|
|
124
124
|
"""
|
|
125
125
|
if self.results is None:
|
|
126
|
-
|
|
126
|
+
raise ValueError(f'Error: No results found in ${self.filepath}')
|
|
127
127
|
|
|
128
128
|
components: dict = {}
|
|
129
129
|
# Extract component and license data from file and dependency results. Both helpers mutate `components`
|
|
@@ -132,6 +132,7 @@ class LicenseSummary(InspectBase):
|
|
|
132
132
|
return self._convert_components_to_list(components)
|
|
133
133
|
|
|
134
134
|
def run(self):
|
|
135
|
+
print("Running LicenseSummary")
|
|
135
136
|
components = self._get_components()
|
|
136
137
|
license_summary = self._get_licenses_summary_from_components(components)
|
|
137
138
|
self.print_to_file_or_stdout(json.dumps(license_summary, indent=2), self.output)
|
|
@@ -26,10 +26,10 @@ import json
|
|
|
26
26
|
import os.path
|
|
27
27
|
from abc import abstractmethod
|
|
28
28
|
from enum import Enum
|
|
29
|
-
from typing import Any, Dict
|
|
29
|
+
from typing import Any, Dict, TypeVar
|
|
30
30
|
|
|
31
|
-
from ..
|
|
32
|
-
from
|
|
31
|
+
from ..policy_check import PolicyCheck
|
|
32
|
+
from ..utils.license_utils import LicenseUtil
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class ComponentID(Enum):
|
|
@@ -51,8 +51,8 @@ class ComponentID(Enum):
|
|
|
51
51
|
# End of ComponentID Class
|
|
52
52
|
#
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
class
|
|
54
|
+
T = TypeVar('T')
|
|
55
|
+
class RawBase(PolicyCheck[T]):
|
|
56
56
|
"""
|
|
57
57
|
A base class to perform inspections over scan results.
|
|
58
58
|
|
|
@@ -68,10 +68,13 @@ class InspectBase(ScanossBase):
|
|
|
68
68
|
debug: bool = False,
|
|
69
69
|
trace: bool = False,
|
|
70
70
|
quiet: bool = False,
|
|
71
|
+
format_type: str = None,
|
|
71
72
|
filepath: str = None,
|
|
72
73
|
output: str = None,
|
|
74
|
+
status: str = None,
|
|
75
|
+
name: str = None,
|
|
73
76
|
):
|
|
74
|
-
super().__init__(debug, trace, quiet)
|
|
77
|
+
super().__init__(debug, trace, quiet, format_type,status, name, output)
|
|
75
78
|
self.license_util = LicenseUtil()
|
|
76
79
|
self.filepath = filepath
|
|
77
80
|
self.output = output
|
|
@@ -23,12 +23,27 @@ SPDX-License-Identifier: MIT
|
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
25
|
import json
|
|
26
|
-
from
|
|
26
|
+
from dataclasses import dataclass
|
|
27
|
+
from typing import Any, Dict, List
|
|
27
28
|
|
|
28
|
-
from
|
|
29
|
+
from ..policy_check import PolicyStatus
|
|
30
|
+
from .raw_base import RawBase
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
@dataclass
|
|
34
|
+
class License:
|
|
35
|
+
spdxid: str
|
|
36
|
+
copyleft: bool
|
|
37
|
+
url: str
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class Component:
|
|
41
|
+
purl: str
|
|
42
|
+
version: str
|
|
43
|
+
licenses: List[License]
|
|
44
|
+
status: str
|
|
45
|
+
|
|
46
|
+
class UndeclaredComponent(RawBase[Component]):
|
|
32
47
|
"""
|
|
33
48
|
SCANOSS UndeclaredComponent class
|
|
34
49
|
Inspects for undeclared components
|
|
@@ -58,7 +73,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
58
73
|
:param sbom_format: Sbom format for status output (default 'settings')
|
|
59
74
|
"""
|
|
60
75
|
super().__init__(
|
|
61
|
-
debug, trace, quiet, filepath,
|
|
76
|
+
debug, trace, quiet,format_type, filepath, output, status, name='Undeclared Components Policy'
|
|
62
77
|
)
|
|
63
78
|
self.filepath = filepath
|
|
64
79
|
self.format = format
|
|
@@ -66,7 +81,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
66
81
|
self.status = status
|
|
67
82
|
self.sbom_format = sbom_format
|
|
68
83
|
|
|
69
|
-
def
|
|
84
|
+
def _get_undeclared_components(self, components: list[Component]) -> list or None:
|
|
70
85
|
"""
|
|
71
86
|
Filter the components list to include only undeclared components.
|
|
72
87
|
|
|
@@ -90,7 +105,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
90
105
|
# end component loop
|
|
91
106
|
return undeclared_components
|
|
92
107
|
|
|
93
|
-
def _get_jira_summary(self, components: list) -> str:
|
|
108
|
+
def _get_jira_summary(self, components: list[Component]) -> str:
|
|
94
109
|
"""
|
|
95
110
|
Get a summary of the undeclared components.
|
|
96
111
|
|
|
@@ -147,7 +162,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
147
162
|
|
|
148
163
|
return summary
|
|
149
164
|
|
|
150
|
-
def _json(self, components: list) -> Dict[str, Any]:
|
|
165
|
+
def _json(self, components: list[Component]) -> Dict[str, Any]:
|
|
151
166
|
"""
|
|
152
167
|
Format the undeclared components as JSON.
|
|
153
168
|
|
|
@@ -164,7 +179,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
164
179
|
'summary': self._get_summary(component_licenses),
|
|
165
180
|
}
|
|
166
181
|
|
|
167
|
-
def _markdown(self, components: list) -> Dict[str, Any]:
|
|
182
|
+
def _markdown(self, components: list[Component]) -> Dict[str, Any]:
|
|
168
183
|
"""
|
|
169
184
|
Format the undeclared components as Markdown.
|
|
170
185
|
|
|
@@ -172,7 +187,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
172
187
|
:return: Dictionary with formatted Markdown details and summary
|
|
173
188
|
"""
|
|
174
189
|
headers = ['Component', 'License']
|
|
175
|
-
rows
|
|
190
|
+
rows = []
|
|
176
191
|
# TODO look at using SpdxLite license name lookup method
|
|
177
192
|
component_licenses = self._group_components_by_license(components)
|
|
178
193
|
for component in component_licenses:
|
|
@@ -190,7 +205,7 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
190
205
|
:return: Dictionary with formatted Markdown details and summary
|
|
191
206
|
"""
|
|
192
207
|
headers = ['Component', 'License']
|
|
193
|
-
rows
|
|
208
|
+
rows = []
|
|
194
209
|
# TODO look at using SpdxLite license name lookup method
|
|
195
210
|
component_licenses = self._group_components_by_license(components)
|
|
196
211
|
for component in component_licenses:
|
|
@@ -280,24 +295,13 @@ class UndeclaredComponent(PolicyCheck):
|
|
|
280
295
|
components = self._get_components()
|
|
281
296
|
if components is None:
|
|
282
297
|
return PolicyStatus.ERROR.value, {}
|
|
283
|
-
# Get undeclared component summary (if any)
|
|
284
|
-
undeclared_components = self.
|
|
298
|
+
# Get an undeclared component summary (if any)
|
|
299
|
+
undeclared_components = self._get_undeclared_components(components)
|
|
285
300
|
if undeclared_components is None:
|
|
286
301
|
return PolicyStatus.ERROR.value, {}
|
|
287
302
|
self.print_debug(f'Undeclared components: {undeclared_components}')
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
return PolicyStatus.ERROR.value, {}
|
|
291
|
-
results = formatter(undeclared_components)
|
|
292
|
-
# Output the results
|
|
293
|
-
self.print_to_file_or_stdout(results['details'], self.output)
|
|
294
|
-
self.print_to_file_or_stderr(results['summary'], self.status)
|
|
295
|
-
# Determine if the filter found results or not
|
|
296
|
-
if len(undeclared_components) <= 0:
|
|
297
|
-
return PolicyStatus.FAIL.value, results
|
|
298
|
-
return PolicyStatus.SUCCESS.value, results
|
|
299
|
-
|
|
300
|
-
|
|
303
|
+
# Format the results and save to files if required
|
|
304
|
+
return self._generate_formatter_report(undeclared_components)
|
|
301
305
|
#
|
|
302
306
|
# End of UndeclaredComponent Class
|
|
303
307
|
#
|
|
@@ -0,0 +1,131 @@
|
|
|
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 requests
|
|
26
|
+
|
|
27
|
+
from ..scanossbase import ScanossBase
|
|
28
|
+
|
|
29
|
+
HTTP_OK = 200
|
|
30
|
+
|
|
31
|
+
class DependencyTrackService(ScanossBase):
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
api_key: str,
|
|
36
|
+
url: str,
|
|
37
|
+
debug: bool = False,
|
|
38
|
+
trace: bool = False,
|
|
39
|
+
quiet: bool = False,
|
|
40
|
+
):
|
|
41
|
+
super().__init__(debug=debug, trace=trace, quiet=quiet)
|
|
42
|
+
if not url:
|
|
43
|
+
raise ValueError("Error: Dependency Track URL is required")
|
|
44
|
+
self.url = url.rstrip('/')
|
|
45
|
+
if not api_key:
|
|
46
|
+
raise ValueError("Error: Dependency Track API key is required")
|
|
47
|
+
self.api_key = api_key
|
|
48
|
+
|
|
49
|
+
def get_project_by_name_version(self, name, version):
|
|
50
|
+
"""
|
|
51
|
+
Get project information by name and version from Dependency Track
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
name: Project name to search for
|
|
55
|
+
version: Project version to search for
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
dict: Project data if found, None otherwise
|
|
59
|
+
"""
|
|
60
|
+
if not name or not version:
|
|
61
|
+
self.print_stderr('Error: Missing name or version.')
|
|
62
|
+
return None
|
|
63
|
+
# Use the project search endpoint
|
|
64
|
+
params = {
|
|
65
|
+
'name': name,
|
|
66
|
+
'version': version
|
|
67
|
+
}
|
|
68
|
+
self.print_debug(f'Searching for project by: {params}')
|
|
69
|
+
return self.get_dep_track_data(f'{self.url}/api/v1/project/lookup', params)
|
|
70
|
+
|
|
71
|
+
def get_project_status(self, upload_token):
|
|
72
|
+
"""
|
|
73
|
+
Get Dependency Track project processing status.
|
|
74
|
+
|
|
75
|
+
Queries the Dependency Track API to check if the project upload
|
|
76
|
+
processing is complete using the upload token.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
dict: Project status information or None if request fails
|
|
80
|
+
"""
|
|
81
|
+
if not upload_token:
|
|
82
|
+
self.print_stderr('Error: Missing upload token. Cannot search for project status.')
|
|
83
|
+
return None
|
|
84
|
+
self.print_trace(f'URL: {self.url} Upload token: {upload_token}')
|
|
85
|
+
return self.get_dep_track_data(f'{self.url}/api/v1/event/token/{upload_token}')
|
|
86
|
+
|
|
87
|
+
def get_project_violations(self,project_id:str):
|
|
88
|
+
"""
|
|
89
|
+
Get project violations from Dependency Track.
|
|
90
|
+
|
|
91
|
+
Waits for project processing to complete, then retrieves all policy
|
|
92
|
+
violations for the specified project ID.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
List of policy violations or None if the request fails
|
|
96
|
+
"""
|
|
97
|
+
if not project_id:
|
|
98
|
+
self.print_stderr('Error: Missing project id. Cannot search for project violations.')
|
|
99
|
+
return None
|
|
100
|
+
return self.get_dep_track_data(f'{self.url}/api/v1/violation/project/{project_id}')
|
|
101
|
+
|
|
102
|
+
def get_project_by_id(self, project_id:str):
|
|
103
|
+
"""
|
|
104
|
+
Get a Dependency Track project by id.
|
|
105
|
+
|
|
106
|
+
Queries the Dependency Track API to get a project by id
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
dict
|
|
110
|
+
"""
|
|
111
|
+
if not project_id:
|
|
112
|
+
self.print_stderr('Error: Missing project id. Cannot search for project.')
|
|
113
|
+
return None
|
|
114
|
+
self.print_trace(f'URL: {self.url}, UUID: {project_id}')
|
|
115
|
+
return self.get_dep_track_data(f'{self.url}/api/v1/project/{project_id}')
|
|
116
|
+
|
|
117
|
+
def get_dep_track_data(self, uri, params=None):
|
|
118
|
+
if not uri:
|
|
119
|
+
self.print_stderr('Error: Missing URI. Cannot search for project.')
|
|
120
|
+
return None
|
|
121
|
+
req_headers = {'X-Api-Key': self.api_key, 'Content-Type': 'application/json'}
|
|
122
|
+
try:
|
|
123
|
+
if params:
|
|
124
|
+
response = requests.get(uri, headers=req_headers, params=params)
|
|
125
|
+
else:
|
|
126
|
+
response = requests.get(uri, headers=req_headers)
|
|
127
|
+
response.raise_for_status() # Raises an HTTPError for bad responses
|
|
128
|
+
return response.json()
|
|
129
|
+
except requests.exceptions.RequestException as e:
|
|
130
|
+
self.print_stderr(f"Error: Problem getting project data: {e}")
|
|
131
|
+
return None
|
|
@@ -4,14 +4,14 @@ 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=
|
|
7
|
+
scanoss/__init__.py,sha256=GsEYO0KIg42-7x-yR5eb2Q2I-vZiTNKc7avRQwyt3ek,1146
|
|
8
|
+
scanoss/cli.py,sha256=Hx8ay24LQJq7H1vIs5kKt8UX7OeFxGADY-3uPgNnzlw,91645
|
|
9
9
|
scanoss/components.py,sha256=b0R9DdKuXqyQiw5nZZwjQ6NJXBr1U9gyx1RI2FP9ozA,14511
|
|
10
10
|
scanoss/constants.py,sha256=On8mQ-8ardVMHSJ7WOJqeTvGXIOWPLCgUanjE7Wk-wE,351
|
|
11
11
|
scanoss/cryptography.py,sha256=oj5HHgJk1e31dzQfB-5sIVmQVcUJMsP5DUPyP9QpPgQ,9806
|
|
12
12
|
scanoss/csvoutput.py,sha256=qNKRwcChSkgIwLm00kZiVX6iHVQUF4Apl-sMbzJ5Taw,10192
|
|
13
13
|
scanoss/cyclonedx.py,sha256=JeAeuj2KYaN72v_08j7b3ZyVOhjXhOHOW7DE3Byp0Wk,16986
|
|
14
|
-
scanoss/file_filters.py,sha256=
|
|
14
|
+
scanoss/file_filters.py,sha256=VxfEBylliXReD07YczsHL0coiI3bdNPbfiLJt7GwPWs,20589
|
|
15
15
|
scanoss/filecount.py,sha256=RZjKQ6M5P_RQg0_PMD2tsRe5Z8f98ke0sxYVjPDN8iQ,6538
|
|
16
16
|
scanoss/results.py,sha256=47ZXXuU2sDjYa5vhtbWTmikit9jHhA0rsYKwkvZFI5w,9252
|
|
17
17
|
scanoss/scancodedeps.py,sha256=JbpoGW1POtPMmowzfwa4oh8sSBeeQCqaW9onvc4UFYM,11517
|
|
@@ -57,33 +57,35 @@ scanoss/api/vulnerabilities/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSC
|
|
|
57
57
|
scanoss/api/vulnerabilities/v2/__init__.py,sha256=IFrDk_DTJgKSZmmU-nuLXuq_s8sQZlrSCHhIDMJT4r0,1122
|
|
58
58
|
scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py,sha256=CFhF80av8tenGvn9AIsGEtRJPuV2dC_syA5JLZb2lDw,5464
|
|
59
59
|
scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py,sha256=HlS4k4Zmx6RIAqaO9I96jD-eyF5yU6Xx04pVm7pdqOg,6864
|
|
60
|
-
scanoss/data/build_date.txt,sha256=
|
|
60
|
+
scanoss/data/build_date.txt,sha256=Q8zEemhVmzA8F0x69_8tz3r7VRf6LUVCaREFev502KY,40
|
|
61
61
|
scanoss/data/scanoss-settings-schema.json,sha256=ClkRYAkjAN0Sk704G8BE_Ok006oQ6YnIGmX84CF8h9w,8798
|
|
62
62
|
scanoss/data/spdx-exceptions.json,sha256=s7UTYxC7jqQXr11YBlIWYCNwN6lRDFTR33Y8rpN_dA4,17953
|
|
63
63
|
scanoss/data/spdx-licenses.json,sha256=A6Z0q82gaTLtnopBfzeIVZjJFxkdRW1g2TuumQc-lII,228794
|
|
64
64
|
scanoss/export/__init__.py,sha256=D4C0lWLuNp8k_BjQZEc07WZcUgAvriVwQWOk063b0ZU,1122
|
|
65
|
-
scanoss/export/dependency_track.py,sha256
|
|
65
|
+
scanoss/export/dependency_track.py,sha256=-jQdwiBGoTYz8r7jljB33XK4tSQrd1jNuDH3V8QHaiQ,9001
|
|
66
66
|
scanoss/inspection/__init__.py,sha256=D4C0lWLuNp8k_BjQZEc07WZcUgAvriVwQWOk063b0ZU,1122
|
|
67
|
-
scanoss/inspection/
|
|
68
|
-
scanoss/inspection/
|
|
69
|
-
scanoss/inspection/
|
|
70
|
-
scanoss/inspection/
|
|
71
|
-
scanoss/inspection/
|
|
72
|
-
scanoss/inspection/
|
|
67
|
+
scanoss/inspection/policy_check.py,sha256=JOJko_QVB7_6I8VQiGFJmOmJheN5jlwtpGOS2kBMMCo,9756
|
|
68
|
+
scanoss/inspection/dependency_track/project_violation.py,sha256=OzQSyN_diOCvFHFBk8AGZJBnxMcfediU5al_Wbh9l8E,18778
|
|
69
|
+
scanoss/inspection/raw/component_summary.py,sha256=J4DDGNg9WIxIaTeblk6u4tmtMf4veXDesuC4rmpHNkM,4090
|
|
70
|
+
scanoss/inspection/raw/copyleft.py,sha256=xAKIYROUG-F9SbPs3iIDmTg8yqovh3NVZNni4-byd68,9324
|
|
71
|
+
scanoss/inspection/raw/license_summary.py,sha256=eLvmSvqDE2pu225fEwE2EMSdY6wqruNOMoUUkAXLWyg,5863
|
|
72
|
+
scanoss/inspection/raw/raw_base.py,sha256=gQoInr8a82JxzGjtdBo61ffVJ8sYJ9HNcTNzze1JXKI,18346
|
|
73
|
+
scanoss/inspection/raw/undeclared_component.py,sha256=uN-oVqQF8vWArTc2yDVoxudV0bbrkbZaZ-mdZn-Cntw,11361
|
|
73
74
|
scanoss/inspection/utils/license_utils.py,sha256=Zb6QLmVJb86lKCwZyBsmwakyAtY1SXa54kUyyKmWMqA,5093
|
|
74
75
|
scanoss/scanners/__init__.py,sha256=D4C0lWLuNp8k_BjQZEc07WZcUgAvriVwQWOk063b0ZU,1122
|
|
75
76
|
scanoss/scanners/container_scanner.py,sha256=fOrb64owrstX7LnTuxiIan059YgLeKXeBS6g2QaCyq0,16346
|
|
76
77
|
scanoss/scanners/folder_hasher.py,sha256=-qvTtMC0iPj7zS8nMSZZJyt9d62MeQIK0LcrNDkt7yc,12267
|
|
77
78
|
scanoss/scanners/scanner_config.py,sha256=egG7cw3S2akU-D9M1aLE5jLrfz_c8e7_DIotMnnpM84,2601
|
|
78
79
|
scanoss/scanners/scanner_hfh.py,sha256=OvayCIq_a5iJwv7H7OCdB9K0vI9oxAz9UvgGfg7xrLU,8392
|
|
80
|
+
scanoss/services/dependency_track_service.py,sha256=K0dUXSiVf8NAUOfZcKORqdJJl7fW-08nbndSimlLq8Y,4967
|
|
79
81
|
scanoss/utils/__init__.py,sha256=0hjb5ktavp7utJzFhGMPImPaZiHWgilM2HwvTp5lXJE,1122
|
|
80
82
|
scanoss/utils/abstract_presenter.py,sha256=teiDTxBj5jBMCk2T8i4l1BJPf_u4zBLWrtCTFHSSECM,3148
|
|
81
83
|
scanoss/utils/crc64.py,sha256=TMrwQimSdE6imhFOUL7oAG6Kxu-8qMpGWMuMg8QpSVs,3169
|
|
82
84
|
scanoss/utils/file.py,sha256=62cA9a17TU9ZvfA3FY5HY4-QOajJeSrc8S6xLA_f-3M,2980
|
|
83
85
|
scanoss/utils/simhash.py,sha256=6iu8DOcecPAY36SZjCOzrrLMT9oIE7-gI6QuYwUQ7B0,5793
|
|
84
|
-
scanoss-1.
|
|
85
|
-
scanoss-1.
|
|
86
|
-
scanoss-1.
|
|
87
|
-
scanoss-1.
|
|
88
|
-
scanoss-1.
|
|
89
|
-
scanoss-1.
|
|
86
|
+
scanoss-1.31.1.dist-info/licenses/LICENSE,sha256=LLUaXoiyOroIbr5ubAyrxBOwSRLTm35ETO2FmLpy8QQ,1074
|
|
87
|
+
scanoss-1.31.1.dist-info/METADATA,sha256=Htoqvp9Y0wK1Wp2WDn_Y_Zy2hHY_NHsa2eosqAxshsI,6108
|
|
88
|
+
scanoss-1.31.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
89
|
+
scanoss-1.31.1.dist-info/entry_points.txt,sha256=Uy28xnaDL5KQ7V77sZD5VLDXPNxYYzSr5tsqtiXVzAs,48
|
|
90
|
+
scanoss-1.31.1.dist-info/top_level.txt,sha256=V11PrQ6Pnrc-nDF9xnisnJ8e6-i7HqSIKVNqduRWcL8,27
|
|
91
|
+
scanoss-1.31.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|