scanoss 1.19.6__py3-none-any.whl → 1.20.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.
- protoc_gen_swagger/__init__.py +13 -13
- protoc_gen_swagger/options/__init__.py +13 -13
- protoc_gen_swagger/options/annotations_pb2.py +12 -9
- protoc_gen_swagger/options/annotations_pb2_grpc.py +1 -1
- protoc_gen_swagger/options/openapiv2_pb2.py +98 -96
- protoc_gen_swagger/options/openapiv2_pb2_grpc.py +1 -1
- scanoss/__init__.py +18 -18
- scanoss/api/__init__.py +17 -17
- scanoss/api/common/__init__.py +17 -17
- scanoss/api/common/v2/__init__.py +17 -17
- scanoss/api/common/v2/scanoss_common_pb2.py +18 -18
- scanoss/api/common/v2/scanoss_common_pb2_grpc.py +1 -1
- scanoss/api/components/__init__.py +17 -17
- scanoss/api/components/v2/__init__.py +17 -17
- scanoss/api/components/v2/scanoss_components_pb2.py +48 -38
- scanoss/api/components/v2/scanoss_components_pb2_grpc.py +142 -96
- scanoss/api/cryptography/v2/scanoss_cryptography_pb2.py +22 -16
- scanoss/api/cryptography/v2/scanoss_cryptography_pb2_grpc.py +75 -49
- scanoss/api/dependencies/__init__.py +17 -17
- scanoss/api/dependencies/v2/__init__.py +17 -17
- scanoss/api/dependencies/v2/scanoss_dependencies_pb2.py +30 -24
- scanoss/api/dependencies/v2/scanoss_dependencies_pb2_grpc.py +75 -49
- scanoss/api/provenance/__init__.py +23 -0
- scanoss/api/provenance/v2/__init__.py +23 -0
- scanoss/api/provenance/v2/scanoss_provenance_pb2.py +42 -0
- scanoss/api/provenance/v2/scanoss_provenance_pb2_grpc.py +108 -0
- scanoss/api/scanning/__init__.py +17 -17
- scanoss/api/scanning/v2/__init__.py +17 -17
- scanoss/api/scanning/v2/scanoss_scanning_pb2.py +10 -8
- scanoss/api/scanning/v2/scanoss_scanning_pb2_grpc.py +40 -32
- scanoss/api/semgrep/__init__.py +17 -17
- scanoss/api/semgrep/v2/__init__.py +17 -17
- scanoss/api/semgrep/v2/scanoss_semgrep_pb2.py +22 -18
- scanoss/api/semgrep/v2/scanoss_semgrep_pb2_grpc.py +71 -49
- scanoss/api/vulnerabilities/__init__.py +17 -17
- scanoss/api/vulnerabilities/v2/__init__.py +17 -17
- scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2.py +37 -27
- scanoss/api/vulnerabilities/v2/scanoss_vulnerabilities_pb2_grpc.py +109 -72
- scanoss/cli.py +578 -264
- scanoss/components.py +99 -48
- scanoss/csvoutput.py +83 -56
- scanoss/cyclonedx.py +48 -46
- scanoss/data/build_date.txt +1 -1
- scanoss/file_filters.py +13 -15
- scanoss/filecount.py +43 -36
- scanoss/inspection/__init__.py +17 -17
- scanoss/inspection/copyleft.py +71 -58
- scanoss/inspection/policy_check.py +76 -53
- scanoss/inspection/undeclared_component.py +98 -75
- scanoss/inspection/utils/license_utils.py +66 -44
- scanoss/results.py +51 -60
- scanoss/scancodedeps.py +61 -38
- scanoss/scanner.py +203 -135
- scanoss/scanoss_settings.py +5 -3
- scanoss/scanossapi.py +98 -69
- scanoss/scanossbase.py +19 -19
- scanoss/scanossgrpc.py +107 -51
- scanoss/scanpostprocessor.py +9 -6
- scanoss/scantype.py +22 -21
- scanoss/spdxlite.py +265 -171
- scanoss/threadeddependencies.py +91 -61
- scanoss/threadedscanning.py +37 -31
- scanoss/utils/file.py +4 -4
- scanoss/winnowing.py +111 -47
- {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/METADATA +1 -1
- scanoss-1.20.1.dist-info/RECORD +74 -0
- scanoss-1.19.6.dist-info/RECORD +0 -70
- {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/LICENSE +0 -0
- {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/WHEEL +0 -0
- {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/entry_points.txt +0 -0
- {scanoss-1.19.6.dist-info → scanoss-1.20.1.dist-info}/top_level.txt +0 -0
scanoss/cli.py
CHANGED
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
23
|
"""
|
|
24
|
+
|
|
24
25
|
import argparse
|
|
25
26
|
import os
|
|
26
|
-
from pathlib import Path
|
|
27
27
|
import sys
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
28
30
|
import pypac
|
|
29
31
|
|
|
32
|
+
from . import __version__
|
|
33
|
+
from .components import Components
|
|
34
|
+
from .csvoutput import CsvOutput
|
|
35
|
+
from .cyclonedx import CycloneDx
|
|
36
|
+
from .filecount import FileCount
|
|
30
37
|
from .inspection.copyleft import Copyleft
|
|
31
38
|
from .inspection.undeclared_component import UndeclaredComponent
|
|
32
|
-
from .
|
|
33
|
-
from .scanoss_settings import ScanossSettings, ScanossSettingsError
|
|
39
|
+
from .results import Results
|
|
34
40
|
from .scancodedeps import ScancodeDeps
|
|
35
|
-
from .scanner import Scanner
|
|
41
|
+
from .scanner import FAST_WINNOWING, Scanner
|
|
42
|
+
from .scanoss_settings import ScanossSettings, ScanossSettingsError
|
|
36
43
|
from .scantype import ScanType
|
|
37
|
-
from .filecount import FileCount
|
|
38
|
-
from .cyclonedx import CycloneDx
|
|
39
44
|
from .spdxlite import SpdxLite
|
|
40
|
-
from .
|
|
41
|
-
from .components import Components
|
|
42
|
-
from . import __version__
|
|
43
|
-
from .scanner import FAST_WINNOWING
|
|
44
|
-
from .results import Results
|
|
45
|
+
from .threadeddependencies import SCOPE
|
|
45
46
|
from .utils.file import validate_json_file
|
|
46
47
|
|
|
47
48
|
|
|
@@ -56,152 +57,248 @@ def setup_args() -> None:
|
|
|
56
57
|
"""
|
|
57
58
|
Setup all the command line arguments for processing
|
|
58
59
|
"""
|
|
59
|
-
parser = argparse.ArgumentParser(
|
|
60
|
+
parser = argparse.ArgumentParser(
|
|
61
|
+
description=f'SCANOSS Python CLI. Ver: {__version__}, License: MIT, Fast Winnowing: {FAST_WINNOWING}'
|
|
62
|
+
)
|
|
60
63
|
parser.add_argument('--version', '-v', action='store_true', help='Display version details')
|
|
61
64
|
|
|
62
|
-
subparsers = parser.add_subparsers(
|
|
63
|
-
|
|
65
|
+
subparsers = parser.add_subparsers(
|
|
66
|
+
title='Sub Commands', dest='subparser', description='valid subcommands', help='sub-command help'
|
|
67
|
+
)
|
|
64
68
|
# Sub-command: version
|
|
65
|
-
p_ver = subparsers.add_parser(
|
|
66
|
-
|
|
69
|
+
p_ver = subparsers.add_parser(
|
|
70
|
+
'version', aliases=['ver'], description=f'Version of SCANOSS CLI: {__version__}', help='SCANOSS version'
|
|
71
|
+
)
|
|
67
72
|
p_ver.set_defaults(func=ver)
|
|
68
73
|
|
|
69
74
|
# Sub-command: scan
|
|
70
|
-
p_scan = subparsers.add_parser(
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
p_scan = subparsers.add_parser(
|
|
76
|
+
'scan',
|
|
77
|
+
aliases=['sc'],
|
|
78
|
+
description=f'Analyse/scan the given source base: {__version__}',
|
|
79
|
+
help='Scan source code',
|
|
80
|
+
)
|
|
73
81
|
p_scan.set_defaults(func=scan)
|
|
74
82
|
p_scan.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
|
|
75
|
-
p_scan.add_argument('--wfp', '-w',
|
|
76
|
-
|
|
77
|
-
p_scan.add_argument(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
p_scan.add_argument('--files', '-e', type=str, nargs="*", help='List of files to scan.')
|
|
83
|
+
p_scan.add_argument('--wfp', '-w', type=str, help='Scan a WFP File instead of a folder (optional)')
|
|
84
|
+
p_scan.add_argument('--dep', '-p', type=str, help='Use a dependency file instead of a folder (optional)')
|
|
85
|
+
p_scan.add_argument(
|
|
86
|
+
'--stdin', '-s', metavar='STDIN-FILENAME', type=str, help='Scan the file contents supplied via STDIN (optional)'
|
|
87
|
+
)
|
|
88
|
+
p_scan.add_argument('--files', '-e', type=str, nargs='*', help='List of files to scan.')
|
|
82
89
|
p_scan.add_argument('--identify', '-i', type=str, help='Scan and identify components in SBOM file')
|
|
83
|
-
p_scan.add_argument('--ignore',
|
|
84
|
-
p_scan.add_argument('--output',
|
|
85
|
-
p_scan.add_argument(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
p_scan.add_argument('--ignore', '-n', type=str, help='Ignore components specified in the SBOM file')
|
|
91
|
+
p_scan.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
92
|
+
p_scan.add_argument(
|
|
93
|
+
'--format',
|
|
94
|
+
'-f',
|
|
95
|
+
type=str,
|
|
96
|
+
choices=['plain', 'cyclonedx', 'spdxlite', 'csv'],
|
|
97
|
+
help='Result output format (optional - default: plain)',
|
|
98
|
+
)
|
|
99
|
+
p_scan.add_argument(
|
|
100
|
+
'--threads', '-T', type=int, default=5, help='Number of threads to use while scanning (optional - default 5)'
|
|
101
|
+
)
|
|
102
|
+
p_scan.add_argument(
|
|
103
|
+
'--flags',
|
|
104
|
+
'-F',
|
|
105
|
+
type=int,
|
|
106
|
+
help='Scanning engine flags (1: disable snippet matching, 2 enable snippet ids, '
|
|
107
|
+
'4: disable dependencies, 8: disable licenses, 16: disable copyrights,'
|
|
108
|
+
'32: disable vulnerabilities, 64: disable quality, 128: disable cryptography,'
|
|
109
|
+
'256: disable best match only, 512: hide identified files, '
|
|
110
|
+
'1024: enable download_url, 2048: enable GitHub full path, '
|
|
111
|
+
'4096: disable extended server stats)',
|
|
112
|
+
)
|
|
113
|
+
p_scan.add_argument(
|
|
114
|
+
'--post-size',
|
|
115
|
+
'-P',
|
|
116
|
+
type=int,
|
|
117
|
+
default=32,
|
|
118
|
+
help='Number of kilobytes to limit the post to while scanning (optional - default 32)',
|
|
119
|
+
)
|
|
120
|
+
p_scan.add_argument(
|
|
121
|
+
'--timeout',
|
|
122
|
+
'-M',
|
|
123
|
+
type=int,
|
|
124
|
+
default=180,
|
|
125
|
+
help='Timeout (in seconds) for API communication (optional - default 180)',
|
|
126
|
+
)
|
|
127
|
+
p_scan.add_argument(
|
|
128
|
+
'--retry', '-R', type=int, default=5, help='Retry limit for API communication (optional - default 5)'
|
|
129
|
+
)
|
|
102
130
|
p_scan.add_argument('--no-wfp-output', action='store_true', help='Skip WFP file generation')
|
|
103
131
|
p_scan.add_argument('--dependencies', '-D', action='store_true', help='Add Dependency scanning')
|
|
104
132
|
p_scan.add_argument('--dependencies-only', action='store_true', help='Run Dependency scanning only')
|
|
105
|
-
p_scan.add_argument(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
133
|
+
p_scan.add_argument(
|
|
134
|
+
'--sc-command', type=str, help='Scancode command and path if required (optional - default scancode).'
|
|
135
|
+
)
|
|
136
|
+
p_scan.add_argument(
|
|
137
|
+
'--sc-timeout',
|
|
138
|
+
type=int,
|
|
139
|
+
default=600,
|
|
140
|
+
help='Timeout (in seconds) for scancode to complete (optional - default 600)',
|
|
141
|
+
)
|
|
142
|
+
p_scan.add_argument(
|
|
143
|
+
'--dep-scope', '-ds', type=SCOPE, help='Filter dependencies by scope - default all (options: dev/prod)'
|
|
144
|
+
)
|
|
145
|
+
p_scan.add_argument('--dep-scope-inc', '-dsi', type=str, help='Include dependencies with declared scopes')
|
|
111
146
|
p_scan.add_argument('--dep-scope-exc', '-dse', type=str, help='Exclude dependencies with declared scopes')
|
|
112
147
|
p_scan.add_argument(
|
|
113
|
-
'--settings',
|
|
148
|
+
'--settings',
|
|
149
|
+
'-st',
|
|
114
150
|
type=str,
|
|
115
151
|
help='Settings file to use for scanning (optional - default scanoss.json)',
|
|
116
152
|
)
|
|
117
153
|
p_scan.add_argument(
|
|
118
|
-
'--skip-settings-file',
|
|
154
|
+
'--skip-settings-file',
|
|
155
|
+
'-stf',
|
|
156
|
+
action='store_true',
|
|
119
157
|
help='Skip default settings file (scanoss.json) if it exists',
|
|
120
158
|
)
|
|
121
159
|
|
|
122
160
|
# Sub-command: fingerprint
|
|
123
|
-
p_wfp = subparsers.add_parser(
|
|
124
|
-
|
|
125
|
-
|
|
161
|
+
p_wfp = subparsers.add_parser(
|
|
162
|
+
'fingerprint',
|
|
163
|
+
aliases=['fp', 'wfp'],
|
|
164
|
+
description=f'Fingerprint the given source base: {__version__}',
|
|
165
|
+
help='Fingerprint source code',
|
|
166
|
+
)
|
|
126
167
|
p_wfp.set_defaults(func=wfp)
|
|
127
|
-
p_wfp.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?',
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
168
|
+
p_wfp.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
|
|
169
|
+
p_wfp.add_argument(
|
|
170
|
+
'--stdin',
|
|
171
|
+
'-s',
|
|
172
|
+
metavar='STDIN-FILENAME',
|
|
173
|
+
type=str,
|
|
174
|
+
help='Fingerprint the file contents supplied via STDIN (optional)',
|
|
175
|
+
)
|
|
131
176
|
p_wfp.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
132
177
|
p_wfp.add_argument(
|
|
133
|
-
'--settings',
|
|
178
|
+
'--settings',
|
|
179
|
+
'-st',
|
|
134
180
|
type=str,
|
|
135
181
|
help='Settings file to use for fingerprinting (optional - default scanoss.json)',
|
|
136
182
|
)
|
|
137
183
|
p_wfp.add_argument(
|
|
138
|
-
'--skip-settings-file',
|
|
184
|
+
'--skip-settings-file',
|
|
185
|
+
'-stf',
|
|
186
|
+
action='store_true',
|
|
139
187
|
help='Skip default settings file (scanoss.json) if it exists',
|
|
140
188
|
)
|
|
141
189
|
|
|
142
190
|
# Sub-command: dependency
|
|
143
|
-
p_dep = subparsers.add_parser(
|
|
144
|
-
|
|
145
|
-
|
|
191
|
+
p_dep = subparsers.add_parser(
|
|
192
|
+
'dependencies',
|
|
193
|
+
aliases=['dp', 'dep'],
|
|
194
|
+
description=f'Produce dependency file summary: {__version__}',
|
|
195
|
+
help='Scan source code for dependencies, but do not decorate them',
|
|
196
|
+
)
|
|
146
197
|
p_dep.set_defaults(func=dependency)
|
|
147
198
|
p_dep.add_argument('scan_dir', metavar='FILE/DIR', type=str, nargs='?', help='A file or folder to scan')
|
|
148
199
|
p_dep.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
149
|
-
p_dep.add_argument(
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
200
|
+
p_dep.add_argument(
|
|
201
|
+
'--sc-command', type=str, help='Scancode command and path if required (optional - default scancode).'
|
|
202
|
+
)
|
|
203
|
+
p_dep.add_argument(
|
|
204
|
+
'--sc-timeout',
|
|
205
|
+
type=int,
|
|
206
|
+
default=600,
|
|
207
|
+
help='Timeout (in seconds) for scancode to complete (optional - default 600)',
|
|
208
|
+
)
|
|
153
209
|
|
|
154
210
|
# Sub-command: file_count
|
|
155
|
-
p_fc = subparsers.add_parser(
|
|
156
|
-
|
|
157
|
-
|
|
211
|
+
p_fc = subparsers.add_parser(
|
|
212
|
+
'file_count',
|
|
213
|
+
aliases=['fc'],
|
|
214
|
+
description=f'Produce a file type count summary: {__version__}',
|
|
215
|
+
help='Search the source tree and produce a file type summary',
|
|
216
|
+
)
|
|
158
217
|
p_fc.set_defaults(func=file_count)
|
|
159
218
|
p_fc.add_argument('scan_dir', metavar='DIR', type=str, nargs='?', help='A folder to search')
|
|
160
219
|
p_fc.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
161
220
|
p_fc.add_argument('--all-hidden', action='store_true', help='Scan all hidden files/folders')
|
|
162
221
|
|
|
163
222
|
# Sub-command: convert
|
|
164
|
-
p_cnv = subparsers.add_parser(
|
|
165
|
-
|
|
166
|
-
|
|
223
|
+
p_cnv = subparsers.add_parser(
|
|
224
|
+
'convert',
|
|
225
|
+
aliases=['cv', 'cnv', 'cvrt'],
|
|
226
|
+
description=f'Convert results files between formats: {__version__}',
|
|
227
|
+
help='Convert file format',
|
|
228
|
+
)
|
|
167
229
|
p_cnv.set_defaults(func=convert)
|
|
168
230
|
p_cnv.add_argument('--input', '-i', type=str, required=True, help='Input file name')
|
|
169
231
|
p_cnv.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
170
|
-
p_cnv.add_argument(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
232
|
+
p_cnv.add_argument(
|
|
233
|
+
'--format',
|
|
234
|
+
'-f',
|
|
235
|
+
type=str,
|
|
236
|
+
choices=['cyclonedx', 'spdxlite', 'csv'],
|
|
237
|
+
default='spdxlite',
|
|
238
|
+
help='Output format (optional - default: spdxlite)',
|
|
239
|
+
)
|
|
240
|
+
p_cnv.add_argument(
|
|
241
|
+
'--input-format', type=str, choices=['plain'], default='plain', help='Input format (optional - default: plain)'
|
|
242
|
+
)
|
|
174
243
|
|
|
175
244
|
# Sub-command: component
|
|
176
|
-
p_comp = subparsers.add_parser(
|
|
177
|
-
|
|
178
|
-
|
|
245
|
+
p_comp = subparsers.add_parser(
|
|
246
|
+
'component',
|
|
247
|
+
aliases=['comp'],
|
|
248
|
+
description=f'SCANOSS Component commands: {__version__}',
|
|
249
|
+
help='Component support commands',
|
|
250
|
+
)
|
|
179
251
|
|
|
180
|
-
comp_sub = p_comp.add_subparsers(
|
|
181
|
-
|
|
252
|
+
comp_sub = p_comp.add_subparsers(
|
|
253
|
+
title='Component Commands',
|
|
254
|
+
dest='subparsercmd',
|
|
255
|
+
description='component sub-commands',
|
|
256
|
+
help='component sub-commands',
|
|
257
|
+
)
|
|
182
258
|
|
|
183
259
|
# Component Sub-command: component crypto
|
|
184
|
-
c_crypto = comp_sub.add_parser(
|
|
185
|
-
|
|
186
|
-
|
|
260
|
+
c_crypto = comp_sub.add_parser(
|
|
261
|
+
'crypto',
|
|
262
|
+
aliases=['cr'],
|
|
263
|
+
description=f'Show Cryptographic algorithms: {__version__}',
|
|
264
|
+
help='Retrieve cryptographic algorithms for the given components',
|
|
265
|
+
)
|
|
187
266
|
c_crypto.set_defaults(func=comp_crypto)
|
|
188
267
|
|
|
189
268
|
# Component Sub-command: component vulns
|
|
190
|
-
c_vulns = comp_sub.add_parser(
|
|
191
|
-
|
|
192
|
-
|
|
269
|
+
c_vulns = comp_sub.add_parser(
|
|
270
|
+
'vulns',
|
|
271
|
+
aliases=['vulnerabilities', 'vu'],
|
|
272
|
+
description=f'Show Vulnerability details: {__version__}',
|
|
273
|
+
help='Retrieve vulnerabilities for the given components',
|
|
274
|
+
)
|
|
193
275
|
c_vulns.set_defaults(func=comp_vulns)
|
|
194
276
|
|
|
195
277
|
# Component Sub-command: component semgrep
|
|
196
|
-
c_semgrep = comp_sub.add_parser(
|
|
197
|
-
|
|
198
|
-
|
|
278
|
+
c_semgrep = comp_sub.add_parser(
|
|
279
|
+
'semgrep',
|
|
280
|
+
aliases=['sp'],
|
|
281
|
+
description=f'Show Semgrep findings: {__version__}',
|
|
282
|
+
help='Retrieve semgrep issues/findings for the given components',
|
|
283
|
+
)
|
|
199
284
|
c_semgrep.set_defaults(func=comp_semgrep)
|
|
200
285
|
|
|
286
|
+
# Component Sub-command: component provenance
|
|
287
|
+
c_provenance = comp_sub.add_parser(
|
|
288
|
+
'provenance',
|
|
289
|
+
aliases=['prov', 'prv'],
|
|
290
|
+
description=f'Show Provenance findings: {__version__}',
|
|
291
|
+
help='Retrieve provenance for the given components',
|
|
292
|
+
)
|
|
293
|
+
c_provenance.set_defaults(func=c_provenance)
|
|
294
|
+
|
|
201
295
|
# Component Sub-command: component search
|
|
202
|
-
c_search = comp_sub.add_parser(
|
|
203
|
-
|
|
204
|
-
|
|
296
|
+
c_search = comp_sub.add_parser(
|
|
297
|
+
'search',
|
|
298
|
+
aliases=['sc'],
|
|
299
|
+
description=f'Search component details: {__version__}',
|
|
300
|
+
help='Search for a KB component',
|
|
301
|
+
)
|
|
205
302
|
c_search.add_argument('--input', '-i', type=str, help='Input file name')
|
|
206
303
|
c_search.add_argument('--search', '-s', type=str, help='Generic component search')
|
|
207
304
|
c_search.add_argument('--vendor', '-v', type=str, help='Generic component search')
|
|
@@ -212,9 +309,12 @@ def setup_args() -> None:
|
|
|
212
309
|
c_search.set_defaults(func=comp_search)
|
|
213
310
|
|
|
214
311
|
# Component Sub-command: component versions
|
|
215
|
-
c_versions = comp_sub.add_parser(
|
|
216
|
-
|
|
217
|
-
|
|
312
|
+
c_versions = comp_sub.add_parser(
|
|
313
|
+
'versions',
|
|
314
|
+
aliases=['vs'],
|
|
315
|
+
description=f'Get component version details: {__version__}',
|
|
316
|
+
help='Search for component versions',
|
|
317
|
+
)
|
|
218
318
|
c_versions.add_argument('--input', '-i', type=str, help='Input file name')
|
|
219
319
|
c_versions.add_argument('--purl', '-p', type=str, help='Generic component search')
|
|
220
320
|
c_versions.add_argument('--limit', '-l', type=int, help='Generic component search')
|
|
@@ -222,58 +322,87 @@ def setup_args() -> None:
|
|
|
222
322
|
|
|
223
323
|
# Common purl Component sub-command options
|
|
224
324
|
for p in [c_crypto, c_vulns, c_semgrep]:
|
|
225
|
-
p.add_argument('--purl',
|
|
325
|
+
p.add_argument('--purl', '-p', type=str, nargs='*', help='Package URL - PURL to process.')
|
|
226
326
|
p.add_argument('--input', '-i', type=str, help='Input file name')
|
|
227
327
|
# Common Component sub-command options
|
|
228
|
-
for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
|
|
328
|
+
for p in [c_crypto, c_vulns, c_search, c_versions, c_semgrep, c_provenance]:
|
|
229
329
|
p.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
230
|
-
p.add_argument(
|
|
231
|
-
|
|
330
|
+
p.add_argument(
|
|
331
|
+
'--timeout',
|
|
332
|
+
'-M',
|
|
333
|
+
type=int,
|
|
334
|
+
default=600,
|
|
335
|
+
help='Timeout (in seconds) for API communication (optional - default 600)',
|
|
336
|
+
)
|
|
232
337
|
|
|
233
338
|
# Sub-command: utils
|
|
234
|
-
p_util = subparsers.add_parser(
|
|
235
|
-
|
|
236
|
-
|
|
339
|
+
p_util = subparsers.add_parser(
|
|
340
|
+
'utils',
|
|
341
|
+
aliases=['ut'],
|
|
342
|
+
description=f'SCANOSS Utility commands: {__version__}',
|
|
343
|
+
help='General utility support commands',
|
|
344
|
+
)
|
|
237
345
|
|
|
238
|
-
utils_sub = p_util.add_subparsers(
|
|
239
|
-
|
|
346
|
+
utils_sub = p_util.add_subparsers(
|
|
347
|
+
title='Utils Commands', dest='subparsercmd', description='utils sub-commands', help='utils sub-commands'
|
|
348
|
+
)
|
|
240
349
|
|
|
241
350
|
# Utils Sub-command: utils fast
|
|
242
|
-
p_f_f = utils_sub.add_parser(
|
|
243
|
-
|
|
351
|
+
p_f_f = utils_sub.add_parser(
|
|
352
|
+
'fast', description=f'Is fast winnowing enabled: {__version__}', help='SCANOSS fast winnowing'
|
|
353
|
+
)
|
|
244
354
|
p_f_f.set_defaults(func=fast)
|
|
245
355
|
|
|
246
356
|
# Utils Sub-command: utils certloc
|
|
247
|
-
p_c_loc = utils_sub.add_parser(
|
|
248
|
-
|
|
249
|
-
|
|
357
|
+
p_c_loc = utils_sub.add_parser(
|
|
358
|
+
'certloc',
|
|
359
|
+
aliases=['cl'],
|
|
360
|
+
description=f'Show location of Python CA Certs: {__version__}',
|
|
361
|
+
help='Display the location of Python CA Certs',
|
|
362
|
+
)
|
|
250
363
|
p_c_loc.set_defaults(func=utils_certloc)
|
|
251
364
|
|
|
252
365
|
# Utils Sub-command: utils cert-download
|
|
253
|
-
p_c_dwnld = utils_sub.add_parser(
|
|
254
|
-
|
|
255
|
-
|
|
366
|
+
p_c_dwnld = utils_sub.add_parser(
|
|
367
|
+
'cert-download',
|
|
368
|
+
aliases=['cdl', 'cert-dl'],
|
|
369
|
+
description=f'Download Server SSL Cert: {__version__}',
|
|
370
|
+
help="Download the specified server's SSL PEM certificate",
|
|
371
|
+
)
|
|
256
372
|
p_c_dwnld.set_defaults(func=utils_cert_download)
|
|
257
373
|
p_c_dwnld.add_argument('--hostname', '-n', required=True, type=str, help='Server hostname to download cert from.')
|
|
258
|
-
p_c_dwnld.add_argument(
|
|
259
|
-
|
|
374
|
+
p_c_dwnld.add_argument(
|
|
375
|
+
'--port', '-p', required=False, type=int, default=443, help='Server port number (default: 443).'
|
|
376
|
+
)
|
|
260
377
|
p_c_dwnld.add_argument('--output', '-o', type=str, help='Output result file name (optional - default stdout).')
|
|
261
378
|
|
|
262
379
|
# Utils Sub-command: utils pac-proxy
|
|
263
|
-
p_p_proxy = utils_sub.add_parser(
|
|
264
|
-
|
|
265
|
-
|
|
380
|
+
p_p_proxy = utils_sub.add_parser(
|
|
381
|
+
'pac-proxy',
|
|
382
|
+
aliases=['pac'],
|
|
383
|
+
description=f'Determine Proxy from PAC: {__version__}',
|
|
384
|
+
help='Use Proxy Auto-Config to determine proxy configuration',
|
|
385
|
+
)
|
|
266
386
|
p_p_proxy.set_defaults(func=utils_pac_proxy)
|
|
267
|
-
p_p_proxy.add_argument(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
387
|
+
p_p_proxy.add_argument(
|
|
388
|
+
'--pac',
|
|
389
|
+
required=False,
|
|
390
|
+
type=str,
|
|
391
|
+
default='auto',
|
|
392
|
+
help='Proxy auto configuration. Specify a file, http url or "auto" to try to discover it.',
|
|
393
|
+
)
|
|
394
|
+
p_p_proxy.add_argument(
|
|
395
|
+
'--url',
|
|
396
|
+
required=False,
|
|
397
|
+
type=str,
|
|
398
|
+
default='https://api.osskb.org',
|
|
399
|
+
help='URL to test (default: https://api.osskb.org).',
|
|
400
|
+
)
|
|
272
401
|
|
|
273
402
|
p_results = subparsers.add_parser(
|
|
274
403
|
'results',
|
|
275
404
|
aliases=['res'],
|
|
276
|
-
description=f
|
|
405
|
+
description=f'SCANOSS Results commands: {__version__}',
|
|
277
406
|
help='Process scan results',
|
|
278
407
|
)
|
|
279
408
|
p_results.add_argument(
|
|
@@ -311,37 +440,66 @@ def setup_args() -> None:
|
|
|
311
440
|
)
|
|
312
441
|
p_results.set_defaults(func=results)
|
|
313
442
|
|
|
314
|
-
|
|
315
443
|
# Sub-command: inspect
|
|
316
|
-
p_inspect = subparsers.add_parser(
|
|
317
|
-
|
|
318
|
-
|
|
444
|
+
p_inspect = subparsers.add_parser(
|
|
445
|
+
'inspect', aliases=['insp', 'ins'], description=f'Inspect results: {__version__}', help='Inspect results'
|
|
446
|
+
)
|
|
319
447
|
# Sub-parser: inspect
|
|
320
|
-
p_inspect_sub = p_inspect.add_subparsers(
|
|
321
|
-
|
|
448
|
+
p_inspect_sub = p_inspect.add_subparsers(
|
|
449
|
+
title='Inspect Commands', dest='subparsercmd', description='Inspect sub-commands', help='Inspect sub-commands'
|
|
450
|
+
)
|
|
322
451
|
# Inspect Sub-command: inspect copyleft
|
|
323
|
-
p_copyleft = p_inspect_sub.add_parser(
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
p_copyleft.add_argument(
|
|
452
|
+
p_copyleft = p_inspect_sub.add_parser(
|
|
453
|
+
'copyleft', aliases=['cp'], description='Inspect for copyleft licenses', help='Inspect for copyleft licenses'
|
|
454
|
+
)
|
|
455
|
+
p_copyleft.add_argument(
|
|
456
|
+
'--include',
|
|
457
|
+
help='List of Copyleft licenses to append to the default list. Provide licenses as a comma-separated list.',
|
|
458
|
+
)
|
|
459
|
+
p_copyleft.add_argument(
|
|
460
|
+
'--exclude',
|
|
461
|
+
help='List of Copyleft licenses to remove from default list. Provide licenses as a comma-separated list.',
|
|
462
|
+
)
|
|
463
|
+
p_copyleft.add_argument(
|
|
464
|
+
'--explicit',
|
|
465
|
+
help='Explicit list of Copyleft licenses to consider. Provide licenses as a comma-separated list.s',
|
|
466
|
+
)
|
|
327
467
|
p_copyleft.set_defaults(func=inspect_copyleft)
|
|
328
468
|
|
|
329
469
|
# Inspect Sub-command: inspect undeclared
|
|
330
|
-
p_undeclared = p_inspect_sub.add_parser(
|
|
331
|
-
|
|
332
|
-
|
|
470
|
+
p_undeclared = p_inspect_sub.add_parser(
|
|
471
|
+
'undeclared',
|
|
472
|
+
aliases=['un'],
|
|
473
|
+
description='Inspect for undeclared components',
|
|
474
|
+
help='Inspect for undeclared components',
|
|
475
|
+
)
|
|
476
|
+
p_undeclared.add_argument(
|
|
477
|
+
'--sbom-format',
|
|
478
|
+
required=False,
|
|
479
|
+
choices=['legacy', 'settings'],
|
|
480
|
+
default='settings',
|
|
481
|
+
help='Sbom format for status output',
|
|
482
|
+
)
|
|
333
483
|
p_undeclared.set_defaults(func=inspect_undeclared)
|
|
334
484
|
|
|
335
485
|
for p in [p_copyleft, p_undeclared]:
|
|
336
486
|
p.add_argument('-i', '--input', nargs='?', help='Path to results file')
|
|
337
|
-
p.add_argument(
|
|
487
|
+
p.add_argument(
|
|
488
|
+
'-f',
|
|
489
|
+
'--format',
|
|
490
|
+
required=False,
|
|
491
|
+
choices=['json', 'md', 'jira_md'],
|
|
492
|
+
default='json',
|
|
493
|
+
help='Output format (default: json)',
|
|
494
|
+
)
|
|
338
495
|
p.add_argument('-o', '--output', type=str, help='Save details into a file')
|
|
339
496
|
p.add_argument('-s', '--status', type=str, help='Save summary data into Markdown file')
|
|
340
497
|
|
|
341
498
|
# Global Scan command options
|
|
342
499
|
for p in [p_scan]:
|
|
343
|
-
p.add_argument(
|
|
344
|
-
|
|
500
|
+
p.add_argument(
|
|
501
|
+
'--apiurl', type=str, help='SCANOSS API URL (optional - default: https://api.osskb.org/scan/direct)'
|
|
502
|
+
)
|
|
345
503
|
p.add_argument('--ignore-cert-errors', action='store_true', help='Ignore certificate errors')
|
|
346
504
|
|
|
347
505
|
# Global Scan/Fingerprint filter options
|
|
@@ -354,36 +512,74 @@ def setup_args() -> None:
|
|
|
354
512
|
p.add_argument('--skip-snippets', '-S', action='store_true', help='Skip the generation of snippets')
|
|
355
513
|
p.add_argument('--skip-extension', '-E', type=str, action='append', help='File Extension to skip.')
|
|
356
514
|
p.add_argument('--skip-folder', '-O', type=str, action='append', help='Folder to skip.')
|
|
357
|
-
p.add_argument(
|
|
358
|
-
|
|
515
|
+
p.add_argument(
|
|
516
|
+
'--skip-size',
|
|
517
|
+
'-Z',
|
|
518
|
+
type=int,
|
|
519
|
+
default=0,
|
|
520
|
+
help='Minimum file size to consider for fingerprinting (optional - default 0 bytes [unlimited])',
|
|
521
|
+
)
|
|
359
522
|
p.add_argument('--skip-md5', '-5', type=str, action='append', help='Skip files matching MD5.')
|
|
360
523
|
p.add_argument('--strip-hpsm', '-G', type=str, action='append', help='Strip HPSM string from WFP.')
|
|
361
524
|
p.add_argument('--strip-snippet', '-N', type=str, action='append', help='Strip Snippet ID string from WFP.')
|
|
362
525
|
|
|
363
526
|
# Global Scan/GRPC options
|
|
364
527
|
for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
|
|
365
|
-
p.add_argument(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
528
|
+
p.add_argument(
|
|
529
|
+
'--key', '-k', type=str, help='SCANOSS API Key token (optional - not required for default OSSKB URL)'
|
|
530
|
+
)
|
|
531
|
+
p.add_argument(
|
|
532
|
+
'--proxy',
|
|
533
|
+
type=str,
|
|
534
|
+
help='Proxy URL to use for connections (optional). '
|
|
535
|
+
'Can also use the environment variable "HTTPS_PROXY=<ip>:<port>" '
|
|
536
|
+
'and "grcp_proxy=<ip>:<port>" for gRPC',
|
|
537
|
+
)
|
|
538
|
+
p.add_argument(
|
|
539
|
+
'--pac',
|
|
540
|
+
type=str,
|
|
541
|
+
help='Proxy auto configuration (optional). Specify a file, http url or "auto" to try to discover it.',
|
|
542
|
+
)
|
|
543
|
+
p.add_argument(
|
|
544
|
+
'--ca-cert',
|
|
545
|
+
type=str,
|
|
546
|
+
help='Alternative certificate PEM file (optional). '
|
|
547
|
+
'Can also use the environment variable '
|
|
548
|
+
'"REQUESTS_CA_BUNDLE=/path/to/cacert.pem" and '
|
|
549
|
+
'"GRPC_DEFAULT_SSL_ROOTS_FILE_PATH=/path/to/cacert.pem" for gRPC',
|
|
550
|
+
)
|
|
376
551
|
|
|
377
552
|
# Global GRPC options
|
|
378
553
|
for p in [p_scan, c_crypto, c_vulns, c_search, c_versions, c_semgrep]:
|
|
379
|
-
p.add_argument(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
554
|
+
p.add_argument(
|
|
555
|
+
'--api2url', type=str, help='SCANOSS gRPC API 2.0 URL (optional - default: https://api.osskb.org)'
|
|
556
|
+
)
|
|
557
|
+
p.add_argument(
|
|
558
|
+
'--grpc-proxy',
|
|
559
|
+
type=str,
|
|
560
|
+
help='GRPC Proxy URL to use for connections (optional). '
|
|
561
|
+
'Can also use the environment variable "grcp_proxy=<ip>:<port>"',
|
|
562
|
+
)
|
|
383
563
|
|
|
384
564
|
# Help/Trace command options
|
|
385
|
-
for p in [
|
|
386
|
-
|
|
565
|
+
for p in [
|
|
566
|
+
p_scan,
|
|
567
|
+
p_wfp,
|
|
568
|
+
p_dep,
|
|
569
|
+
p_fc,
|
|
570
|
+
p_cnv,
|
|
571
|
+
p_c_loc,
|
|
572
|
+
p_c_dwnld,
|
|
573
|
+
p_p_proxy,
|
|
574
|
+
c_crypto,
|
|
575
|
+
c_vulns,
|
|
576
|
+
c_search,
|
|
577
|
+
c_versions,
|
|
578
|
+
c_semgrep,
|
|
579
|
+
p_results,
|
|
580
|
+
p_undeclared,
|
|
581
|
+
p_copyleft,
|
|
582
|
+
]:
|
|
387
583
|
p.add_argument('--debug', '-d', action='store_true', help='Enable debug messages')
|
|
388
584
|
p.add_argument('--trace', '-t', action='store_true', help='Enable trace messages, including API posts')
|
|
389
585
|
p.add_argument('--quiet', '-q', action='store_true', help='Enable quiet mode')
|
|
@@ -395,13 +591,17 @@ def setup_args() -> None:
|
|
|
395
591
|
if not args.subparser:
|
|
396
592
|
parser.print_help() # No sub command subcommand, print general help
|
|
397
593
|
exit(1)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
594
|
+
elif (
|
|
595
|
+
args.subparser == 'utils'
|
|
596
|
+
or args.subparser == 'ut'
|
|
597
|
+
or args.subparser == 'component'
|
|
598
|
+
or args.subparser == 'comp'
|
|
599
|
+
or args.subparser == 'inspect'
|
|
600
|
+
or args.subparser == 'insp'
|
|
601
|
+
or args.subparser == 'ins'
|
|
602
|
+
) and not args.subparsercmd:
|
|
603
|
+
parser.parse_args([args.subparser, '--help']) # Force utils helps to be displayed
|
|
604
|
+
exit(1)
|
|
405
605
|
args.func(parser, args) # Execute the function associated with the sub-command
|
|
406
606
|
|
|
407
607
|
|
|
@@ -440,9 +640,13 @@ def file_count(parser, args):
|
|
|
440
640
|
scan_output = args.output
|
|
441
641
|
open(scan_output, 'w').close()
|
|
442
642
|
|
|
443
|
-
counter = FileCount(
|
|
444
|
-
|
|
445
|
-
|
|
643
|
+
counter = FileCount(
|
|
644
|
+
debug=args.debug,
|
|
645
|
+
quiet=args.quiet,
|
|
646
|
+
trace=args.trace,
|
|
647
|
+
scan_output=scan_output,
|
|
648
|
+
hidden_files_folders=args.all_hidden,
|
|
649
|
+
)
|
|
446
650
|
if not os.path.exists(args.scan_dir):
|
|
447
651
|
print_stderr(f'Error: Folder specified does not exist: {args.scan_dir}.')
|
|
448
652
|
exit(1)
|
|
@@ -468,12 +672,12 @@ def wfp(parser, args):
|
|
|
468
672
|
parser.parse_args([args.subparser, '-h'])
|
|
469
673
|
exit(1)
|
|
470
674
|
if args.strip_hpsm and not args.hpsm and not args.quiet:
|
|
471
|
-
print_stderr(
|
|
675
|
+
print_stderr('Warning: --strip-hpsm option supplied without enabling HPSM (--hpsm). Ignoring.')
|
|
472
676
|
scan_output: str = None
|
|
473
677
|
if args.output:
|
|
474
678
|
scan_output = args.output
|
|
475
679
|
open(scan_output, 'w').close()
|
|
476
|
-
|
|
680
|
+
|
|
477
681
|
# Load scan settings
|
|
478
682
|
scan_settings = None
|
|
479
683
|
if not args.skip_settings_file:
|
|
@@ -485,13 +689,24 @@ def wfp(parser, args):
|
|
|
485
689
|
exit(1)
|
|
486
690
|
|
|
487
691
|
scan_options = 0 if args.skip_snippets else ScanType.SCAN_SNIPPETS.value # Skip snippet generation or not
|
|
488
|
-
scanner = Scanner(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
692
|
+
scanner = Scanner(
|
|
693
|
+
debug=args.debug,
|
|
694
|
+
trace=args.trace,
|
|
695
|
+
quiet=args.quiet,
|
|
696
|
+
obfuscate=args.obfuscate,
|
|
697
|
+
scan_options=scan_options,
|
|
698
|
+
all_extensions=args.all_extensions,
|
|
699
|
+
all_folders=args.all_folders,
|
|
700
|
+
hidden_files_folders=args.all_hidden,
|
|
701
|
+
hpsm=args.hpsm,
|
|
702
|
+
skip_size=args.skip_size,
|
|
703
|
+
skip_extensions=args.skip_extension,
|
|
704
|
+
skip_folders=args.skip_folder,
|
|
705
|
+
skip_md5_ids=args.skip_md5,
|
|
706
|
+
strip_hpsm_ids=args.strip_hpsm,
|
|
707
|
+
strip_snippet_ids=args.strip_snippet,
|
|
708
|
+
scan_settings=scan_settings,
|
|
709
|
+
)
|
|
495
710
|
if args.stdin:
|
|
496
711
|
contents = sys.stdin.buffer.read()
|
|
497
712
|
scanner.wfp_contents(args.stdin, contents, scan_output)
|
|
@@ -532,11 +747,11 @@ def get_scan_options(args):
|
|
|
532
747
|
|
|
533
748
|
if args.debug:
|
|
534
749
|
if ScanType.SCAN_FILES.value & scan_options:
|
|
535
|
-
print_stderr(
|
|
750
|
+
print_stderr('Scan Files')
|
|
536
751
|
if ScanType.SCAN_SNIPPETS.value & scan_options:
|
|
537
|
-
print_stderr(
|
|
752
|
+
print_stderr('Scan Snippets')
|
|
538
753
|
if ScanType.SCAN_DEPENDENCIES.value & scan_options:
|
|
539
|
-
print_stderr(
|
|
754
|
+
print_stderr('Scan Dependencies')
|
|
540
755
|
if scan_options <= 0:
|
|
541
756
|
print_stderr(f'Error: No valid scan options configured: {scan_options}')
|
|
542
757
|
exit(1)
|
|
@@ -575,11 +790,17 @@ def scan(parser, args):
|
|
|
575
790
|
scan_settings = ScanossSettings(debug=args.debug, trace=args.trace, quiet=args.quiet)
|
|
576
791
|
try:
|
|
577
792
|
if args.identify:
|
|
578
|
-
scan_settings.load_json_file(args.identify, args.scan_dir).set_file_type('legacy').set_scan_type(
|
|
793
|
+
scan_settings.load_json_file(args.identify, args.scan_dir).set_file_type('legacy').set_scan_type(
|
|
794
|
+
'identify'
|
|
795
|
+
)
|
|
579
796
|
elif args.ignore:
|
|
580
|
-
scan_settings.load_json_file(args.ignore, args.scan_dir).set_file_type('legacy').set_scan_type(
|
|
797
|
+
scan_settings.load_json_file(args.ignore, args.scan_dir).set_file_type('legacy').set_scan_type(
|
|
798
|
+
'blacklist'
|
|
799
|
+
)
|
|
581
800
|
else:
|
|
582
|
-
scan_settings.load_json_file(args.settings, args.scan_dir).set_file_type('new').set_scan_type(
|
|
801
|
+
scan_settings.load_json_file(args.settings, args.scan_dir).set_file_type('new').set_scan_type(
|
|
802
|
+
'identify'
|
|
803
|
+
)
|
|
583
804
|
except ScanossSettingsError as e:
|
|
584
805
|
print_stderr(f'Error: {e}')
|
|
585
806
|
exit(1)
|
|
@@ -604,13 +825,13 @@ def scan(parser, args):
|
|
|
604
825
|
if args.skip_settings_file:
|
|
605
826
|
print_stderr('Skipping Settings file...')
|
|
606
827
|
if args.all_extensions:
|
|
607
|
-
print_stderr(
|
|
828
|
+
print_stderr('Scanning all file extensions/types...')
|
|
608
829
|
if args.all_folders:
|
|
609
|
-
print_stderr(
|
|
830
|
+
print_stderr('Scanning all folders...')
|
|
610
831
|
if args.all_hidden:
|
|
611
|
-
print_stderr(
|
|
832
|
+
print_stderr('Scanning all hidden files/folders...')
|
|
612
833
|
if args.skip_snippets:
|
|
613
|
-
print_stderr(
|
|
834
|
+
print_stderr('Skipping snippets...')
|
|
614
835
|
if args.post_size != 32:
|
|
615
836
|
print_stderr(f'Changing scanning POST size to: {args.post_size}k...')
|
|
616
837
|
if args.timeout != 180:
|
|
@@ -618,7 +839,7 @@ def scan(parser, args):
|
|
|
618
839
|
if args.retry != 5:
|
|
619
840
|
print_stderr(f'Changing scanning POST retry to: {args.retry}...')
|
|
620
841
|
if args.obfuscate:
|
|
621
|
-
print_stderr(
|
|
842
|
+
print_stderr('Obfuscating file fingerprints...')
|
|
622
843
|
if args.proxy:
|
|
623
844
|
print_stderr(f'Using Proxy {args.proxy}...')
|
|
624
845
|
if args.grpc_proxy:
|
|
@@ -628,7 +849,7 @@ def scan(parser, args):
|
|
|
628
849
|
if args.ca_cert:
|
|
629
850
|
print_stderr(f'Using Certificate {args.ca_cert}...')
|
|
630
851
|
if args.hpsm:
|
|
631
|
-
print_stderr(
|
|
852
|
+
print_stderr('Setting HPSM mode...')
|
|
632
853
|
if flags:
|
|
633
854
|
print_stderr(f'Using flags {flags}...')
|
|
634
855
|
elif not args.quiet:
|
|
@@ -647,8 +868,11 @@ def scan(parser, args):
|
|
|
647
868
|
scan_options = get_scan_options(args) # Figure out what scanning options we have
|
|
648
869
|
|
|
649
870
|
scanner = Scanner(
|
|
650
|
-
debug=args.debug,
|
|
651
|
-
|
|
871
|
+
debug=args.debug,
|
|
872
|
+
trace=args.trace,
|
|
873
|
+
quiet=args.quiet,
|
|
874
|
+
api_key=args.key,
|
|
875
|
+
url=args.apiurl,
|
|
652
876
|
scan_output=scan_output,
|
|
653
877
|
output_format=output_format,
|
|
654
878
|
flags=flags,
|
|
@@ -684,7 +908,7 @@ def scan(parser, args):
|
|
|
684
908
|
print_stderr(f'Error: Cannot specify WFP scanning if file/snippet options are disabled ({scan_options})')
|
|
685
909
|
exit(1)
|
|
686
910
|
if scanner.is_dependency_scan() and not args.dep:
|
|
687
|
-
print_stderr(
|
|
911
|
+
print_stderr('Error: Cannot specify WFP & Dependency scanning without a dependency file (--dep)')
|
|
688
912
|
exit(1)
|
|
689
913
|
scanner.scan_wfp_with_options(args.wfp, args.dep)
|
|
690
914
|
elif args.stdin:
|
|
@@ -692,21 +916,31 @@ def scan(parser, args):
|
|
|
692
916
|
if not scanner.scan_contents(args.stdin, contents):
|
|
693
917
|
exit(1)
|
|
694
918
|
elif args.files:
|
|
695
|
-
if not scanner.scan_files_with_options(
|
|
696
|
-
args.files, args.dep, scanner.winnowing.file_map
|
|
697
|
-
):
|
|
919
|
+
if not scanner.scan_files_with_options(args.files, args.dep, scanner.winnowing.file_map):
|
|
698
920
|
exit(1)
|
|
699
921
|
elif args.scan_dir:
|
|
700
922
|
if not os.path.exists(args.scan_dir):
|
|
701
923
|
print_stderr(f'Error: File or folder specified does not exist: {args.scan_dir}.')
|
|
702
924
|
exit(1)
|
|
703
925
|
if os.path.isdir(args.scan_dir):
|
|
704
|
-
if not scanner.scan_folder_with_options(
|
|
705
|
-
|
|
926
|
+
if not scanner.scan_folder_with_options(
|
|
927
|
+
args.scan_dir,
|
|
928
|
+
args.dep,
|
|
929
|
+
scanner.winnowing.file_map,
|
|
930
|
+
args.dep_scope,
|
|
931
|
+
args.dep_scope_inc,
|
|
932
|
+
args.dep_scope_exc,
|
|
933
|
+
):
|
|
706
934
|
exit(1)
|
|
707
935
|
elif os.path.isfile(args.scan_dir):
|
|
708
|
-
if not scanner.scan_file_with_options(
|
|
709
|
-
|
|
936
|
+
if not scanner.scan_file_with_options(
|
|
937
|
+
args.scan_dir,
|
|
938
|
+
args.dep,
|
|
939
|
+
scanner.winnowing.file_map,
|
|
940
|
+
args.dep_scope,
|
|
941
|
+
args.dep_scope_inc,
|
|
942
|
+
args.dep_scope_exc,
|
|
943
|
+
):
|
|
710
944
|
exit(1)
|
|
711
945
|
else:
|
|
712
946
|
print_stderr(f'Error: Path specified is neither a file or a folder: {args.scan_dir}.')
|
|
@@ -714,11 +948,12 @@ def scan(parser, args):
|
|
|
714
948
|
elif args.dep:
|
|
715
949
|
if not args.dependencies_only:
|
|
716
950
|
print_stderr(
|
|
717
|
-
|
|
951
|
+
'Error: No file or folder specified to scan. Please add --dependencies-only to decorate dependency file only.'
|
|
718
952
|
)
|
|
719
953
|
exit(1)
|
|
720
|
-
if not scanner.scan_folder_with_options(
|
|
721
|
-
|
|
954
|
+
if not scanner.scan_folder_with_options(
|
|
955
|
+
'.', args.dep, scanner.winnowing.file_map, args.dep_scope, args.dep_scope_inc, args.dep_scope_exc
|
|
956
|
+
):
|
|
722
957
|
exit(1)
|
|
723
958
|
else:
|
|
724
959
|
print_stderr('No action found to process')
|
|
@@ -747,9 +982,9 @@ def dependency(parser, args):
|
|
|
747
982
|
scan_output = args.output
|
|
748
983
|
open(scan_output, 'w').close()
|
|
749
984
|
|
|
750
|
-
sc_deps = ScancodeDeps(
|
|
751
|
-
|
|
752
|
-
|
|
985
|
+
sc_deps = ScancodeDeps(
|
|
986
|
+
debug=args.debug, quiet=args.quiet, trace=args.trace, sc_command=args.sc_command, timeout=args.sc_timeout
|
|
987
|
+
)
|
|
753
988
|
if not sc_deps.get_dependencies(what_to_scan=args.scan_dir, result_output=scan_output):
|
|
754
989
|
exit(1)
|
|
755
990
|
|
|
@@ -771,17 +1006,17 @@ def convert(parser, args):
|
|
|
771
1006
|
success = False
|
|
772
1007
|
if args.format == 'cyclonedx':
|
|
773
1008
|
if not args.quiet:
|
|
774
|
-
print_stderr(
|
|
1009
|
+
print_stderr('Producing CycloneDX report...')
|
|
775
1010
|
cdx = CycloneDx(debug=args.debug, output_file=args.output)
|
|
776
1011
|
success = cdx.produce_from_file(args.input)
|
|
777
1012
|
elif args.format == 'spdxlite':
|
|
778
1013
|
if not args.quiet:
|
|
779
|
-
print_stderr(
|
|
1014
|
+
print_stderr('Producing SPDX Lite report...')
|
|
780
1015
|
spdxlite = SpdxLite(debug=args.debug, output_file=args.output)
|
|
781
1016
|
success = spdxlite.produce_from_file(args.input)
|
|
782
1017
|
elif args.format == 'csv':
|
|
783
1018
|
if not args.quiet:
|
|
784
|
-
print_stderr(
|
|
1019
|
+
print_stderr('Producing CSV report...')
|
|
785
1020
|
csvo = CsvOutput(debug=args.debug, output_file=args.output)
|
|
786
1021
|
success = csvo.produce_from_file(args.input)
|
|
787
1022
|
else:
|
|
@@ -789,6 +1024,7 @@ def convert(parser, args):
|
|
|
789
1024
|
if not success:
|
|
790
1025
|
exit(1)
|
|
791
1026
|
|
|
1027
|
+
|
|
792
1028
|
def inspect_copyleft(parser, args):
|
|
793
1029
|
"""
|
|
794
1030
|
Run the "inspect" sub-command
|
|
@@ -813,12 +1049,22 @@ def inspect_copyleft(parser, args):
|
|
|
813
1049
|
status_output = args.status
|
|
814
1050
|
open(status_output, 'w').close()
|
|
815
1051
|
|
|
816
|
-
i_copyleft = Copyleft(
|
|
817
|
-
|
|
818
|
-
|
|
1052
|
+
i_copyleft = Copyleft(
|
|
1053
|
+
debug=args.debug,
|
|
1054
|
+
trace=args.trace,
|
|
1055
|
+
quiet=args.quiet,
|
|
1056
|
+
filepath=args.input,
|
|
1057
|
+
format_type=args.format,
|
|
1058
|
+
status=status_output,
|
|
1059
|
+
output=output,
|
|
1060
|
+
include=args.include,
|
|
1061
|
+
exclude=args.exclude,
|
|
1062
|
+
explicit=args.explicit,
|
|
1063
|
+
)
|
|
819
1064
|
status, _ = i_copyleft.run()
|
|
820
1065
|
sys.exit(status)
|
|
821
1066
|
|
|
1067
|
+
|
|
822
1068
|
def inspect_undeclared(parser, args):
|
|
823
1069
|
"""
|
|
824
1070
|
Run the "inspect" sub-command
|
|
@@ -842,20 +1088,30 @@ def inspect_undeclared(parser, args):
|
|
|
842
1088
|
if args.status:
|
|
843
1089
|
status_output = args.status
|
|
844
1090
|
open(status_output, 'w').close()
|
|
845
|
-
i_undeclared = UndeclaredComponent(
|
|
846
|
-
|
|
847
|
-
|
|
1091
|
+
i_undeclared = UndeclaredComponent(
|
|
1092
|
+
debug=args.debug,
|
|
1093
|
+
trace=args.trace,
|
|
1094
|
+
quiet=args.quiet,
|
|
1095
|
+
filepath=args.input,
|
|
1096
|
+
format_type=args.format,
|
|
1097
|
+
status=status_output,
|
|
1098
|
+
output=output,
|
|
1099
|
+
sbom_format=args.sbom_format,
|
|
1100
|
+
)
|
|
848
1101
|
status, _ = i_undeclared.run()
|
|
849
1102
|
sys.exit(status)
|
|
850
1103
|
|
|
1104
|
+
|
|
851
1105
|
def utils_certloc(*_):
|
|
852
1106
|
"""
|
|
853
1107
|
Run the "utils certloc" sub-command
|
|
854
1108
|
:param _: ignored/unused
|
|
855
1109
|
"""
|
|
856
1110
|
import certifi
|
|
1111
|
+
|
|
857
1112
|
print(f'CA Cert File: {certifi.where()}')
|
|
858
1113
|
|
|
1114
|
+
|
|
859
1115
|
def utils_cert_download(_, args):
|
|
860
1116
|
"""
|
|
861
1117
|
Run the "utils cert-download" sub-command
|
|
@@ -890,7 +1146,9 @@ def utils_cert_download(_, args):
|
|
|
890
1146
|
if not args.quiet:
|
|
891
1147
|
print_stderr(f'Certificate {index} - CN: {cn}')
|
|
892
1148
|
if sys.version_info[0] >= 3:
|
|
893
|
-
print(
|
|
1149
|
+
print(
|
|
1150
|
+
(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8')).strip(), file=file
|
|
1151
|
+
) # Print the downloaded PEM certificate
|
|
894
1152
|
else:
|
|
895
1153
|
print((crypto.dump_certificate(crypto.FILETYPE_PEM, cert)).strip(), file=file)
|
|
896
1154
|
except SSL.Error as e:
|
|
@@ -912,8 +1170,9 @@ def utils_pac_proxy(_, args):
|
|
|
912
1170
|
:param args: Parsed arguments
|
|
913
1171
|
"""
|
|
914
1172
|
from pypac.resolver import ProxyResolver
|
|
1173
|
+
|
|
915
1174
|
if not args.pac:
|
|
916
|
-
print_stderr(
|
|
1175
|
+
print_stderr('Error: No pac file option specified.')
|
|
917
1176
|
exit(1)
|
|
918
1177
|
pac_file = get_pac_file(args.pac)
|
|
919
1178
|
if pac_file is None:
|
|
@@ -967,9 +1226,18 @@ def comp_crypto(parser, args):
|
|
|
967
1226
|
print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
|
|
968
1227
|
exit(1)
|
|
969
1228
|
pac_file = get_pac_file(args.pac)
|
|
970
|
-
comps = Components(
|
|
971
|
-
|
|
972
|
-
|
|
1229
|
+
comps = Components(
|
|
1230
|
+
debug=args.debug,
|
|
1231
|
+
trace=args.trace,
|
|
1232
|
+
quiet=args.quiet,
|
|
1233
|
+
grpc_url=args.api2url,
|
|
1234
|
+
api_key=args.key,
|
|
1235
|
+
ca_cert=args.ca_cert,
|
|
1236
|
+
proxy=args.proxy,
|
|
1237
|
+
grpc_proxy=args.grpc_proxy,
|
|
1238
|
+
pac=pac_file,
|
|
1239
|
+
timeout=args.timeout,
|
|
1240
|
+
)
|
|
973
1241
|
if not comps.get_crypto_details(args.input, args.purl, args.output):
|
|
974
1242
|
exit(1)
|
|
975
1243
|
|
|
@@ -992,12 +1260,22 @@ def comp_vulns(parser, args):
|
|
|
992
1260
|
print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
|
|
993
1261
|
exit(1)
|
|
994
1262
|
pac_file = get_pac_file(args.pac)
|
|
995
|
-
comps = Components(
|
|
996
|
-
|
|
997
|
-
|
|
1263
|
+
comps = Components(
|
|
1264
|
+
debug=args.debug,
|
|
1265
|
+
trace=args.trace,
|
|
1266
|
+
quiet=args.quiet,
|
|
1267
|
+
grpc_url=args.api2url,
|
|
1268
|
+
api_key=args.key,
|
|
1269
|
+
ca_cert=args.ca_cert,
|
|
1270
|
+
proxy=args.proxy,
|
|
1271
|
+
grpc_proxy=args.grpc_proxy,
|
|
1272
|
+
pac=pac_file,
|
|
1273
|
+
timeout=args.timeout,
|
|
1274
|
+
)
|
|
998
1275
|
if not comps.get_vulnerabilities(args.input, args.purl, args.output):
|
|
999
1276
|
exit(1)
|
|
1000
1277
|
|
|
1278
|
+
|
|
1001
1279
|
def comp_semgrep(parser, args):
|
|
1002
1280
|
"""
|
|
1003
1281
|
Run the "component semgrep" sub-command
|
|
@@ -1016,12 +1294,22 @@ def comp_semgrep(parser, args):
|
|
|
1016
1294
|
print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
|
|
1017
1295
|
exit(1)
|
|
1018
1296
|
pac_file = get_pac_file(args.pac)
|
|
1019
|
-
comps = Components(
|
|
1020
|
-
|
|
1021
|
-
|
|
1297
|
+
comps = Components(
|
|
1298
|
+
debug=args.debug,
|
|
1299
|
+
trace=args.trace,
|
|
1300
|
+
quiet=args.quiet,
|
|
1301
|
+
grpc_url=args.api2url,
|
|
1302
|
+
api_key=args.key,
|
|
1303
|
+
ca_cert=args.ca_cert,
|
|
1304
|
+
proxy=args.proxy,
|
|
1305
|
+
grpc_proxy=args.grpc_proxy,
|
|
1306
|
+
pac=pac_file,
|
|
1307
|
+
timeout=args.timeout,
|
|
1308
|
+
)
|
|
1022
1309
|
if not comps.get_semgrep_details(args.input, args.purl, args.output):
|
|
1023
1310
|
exit(1)
|
|
1024
1311
|
|
|
1312
|
+
|
|
1025
1313
|
def comp_search(parser, args):
|
|
1026
1314
|
"""
|
|
1027
1315
|
Run the "component search" sub-command
|
|
@@ -1032,8 +1320,9 @@ def comp_search(parser, args):
|
|
|
1032
1320
|
args: Namespace
|
|
1033
1321
|
Parsed arguments
|
|
1034
1322
|
"""
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
1323
|
+
if (not args.input and not args.search and not args.vendor and not args.comp) or (
|
|
1324
|
+
args.input and (args.search or args.vendor or args.comp)
|
|
1325
|
+
):
|
|
1037
1326
|
print_stderr('Please specify an input file or search terms (--input or --search, or --vendor or --comp.)')
|
|
1038
1327
|
parser.parse_args([args.subparser, args.subparsercmd, '-h'])
|
|
1039
1328
|
exit(1)
|
|
@@ -1042,12 +1331,28 @@ def comp_search(parser, args):
|
|
|
1042
1331
|
print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
|
|
1043
1332
|
exit(1)
|
|
1044
1333
|
pac_file = get_pac_file(args.pac)
|
|
1045
|
-
comps = Components(
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1334
|
+
comps = Components(
|
|
1335
|
+
debug=args.debug,
|
|
1336
|
+
trace=args.trace,
|
|
1337
|
+
quiet=args.quiet,
|
|
1338
|
+
grpc_url=args.api2url,
|
|
1339
|
+
api_key=args.key,
|
|
1340
|
+
ca_cert=args.ca_cert,
|
|
1341
|
+
proxy=args.proxy,
|
|
1342
|
+
grpc_proxy=args.grpc_proxy,
|
|
1343
|
+
pac=pac_file,
|
|
1344
|
+
timeout=args.timeout,
|
|
1345
|
+
)
|
|
1346
|
+
if not comps.search_components(
|
|
1347
|
+
args.output,
|
|
1348
|
+
json_file=args.input,
|
|
1349
|
+
search=args.search,
|
|
1350
|
+
vendor=args.vendor,
|
|
1351
|
+
comp=args.comp,
|
|
1352
|
+
package=args.package,
|
|
1353
|
+
limit=args.limit,
|
|
1354
|
+
offset=args.offset,
|
|
1355
|
+
):
|
|
1051
1356
|
exit(1)
|
|
1052
1357
|
|
|
1053
1358
|
|
|
@@ -1070,9 +1375,18 @@ def comp_versions(parser, args):
|
|
|
1070
1375
|
print_stderr(f'Error: Certificate file does not exist: {args.ca_cert}.')
|
|
1071
1376
|
exit(1)
|
|
1072
1377
|
pac_file = get_pac_file(args.pac)
|
|
1073
|
-
comps = Components(
|
|
1074
|
-
|
|
1075
|
-
|
|
1378
|
+
comps = Components(
|
|
1379
|
+
debug=args.debug,
|
|
1380
|
+
trace=args.trace,
|
|
1381
|
+
quiet=args.quiet,
|
|
1382
|
+
grpc_url=args.api2url,
|
|
1383
|
+
api_key=args.key,
|
|
1384
|
+
ca_cert=args.ca_cert,
|
|
1385
|
+
proxy=args.proxy,
|
|
1386
|
+
grpc_proxy=args.grpc_proxy,
|
|
1387
|
+
pac=pac_file,
|
|
1388
|
+
timeout=args.timeout,
|
|
1389
|
+
)
|
|
1076
1390
|
if not comps.get_component_versions(args.output, json_file=args.input, purl=args.purl, limit=args.limit):
|
|
1077
1391
|
exit(1)
|
|
1078
1392
|
|
|
@@ -1089,13 +1403,13 @@ def results(parser, args):
|
|
|
1089
1403
|
"""
|
|
1090
1404
|
if not args.filepath:
|
|
1091
1405
|
print_stderr('ERROR: Please specify a file containing the results')
|
|
1092
|
-
parser.parse_args([args.subparser,
|
|
1406
|
+
parser.parse_args([args.subparser, '-h'])
|
|
1093
1407
|
exit(1)
|
|
1094
1408
|
|
|
1095
1409
|
file_path = Path(args.filepath).resolve()
|
|
1096
1410
|
|
|
1097
1411
|
if not file_path.is_file():
|
|
1098
|
-
print_stderr(f
|
|
1412
|
+
print_stderr(f'The specified file {args.filepath} does not exist')
|
|
1099
1413
|
exit(1)
|
|
1100
1414
|
|
|
1101
1415
|
results = Results(
|
|
@@ -1124,5 +1438,5 @@ def main():
|
|
|
1124
1438
|
setup_args()
|
|
1125
1439
|
|
|
1126
1440
|
|
|
1127
|
-
if __name__ ==
|
|
1441
|
+
if __name__ == '__main__':
|
|
1128
1442
|
main()
|