fosslight-util 2.1.2__tar.gz → 2.1.4__tar.gz

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 (38) hide show
  1. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/PKG-INFO +1 -1
  2. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/requirements.txt +1 -0
  3. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/setup.py +1 -1
  4. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/download.py +1 -0
  5. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/output_format.py +7 -3
  6. fosslight_util-2.1.4/src/fosslight_util/write_cyclonedx.py +215 -0
  7. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/PKG-INFO +1 -1
  8. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/SOURCES.txt +1 -0
  9. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/requires.txt +1 -0
  10. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/LICENSE +0 -0
  11. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/MANIFEST.in +0 -0
  12. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/README.md +0 -0
  13. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/setup.cfg +0 -0
  14. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/__init__.py +0 -0
  15. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/_get_downloadable_url.py +0 -0
  16. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/compare_yaml.py +0 -0
  17. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/constant.py +0 -0
  18. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/correct.py +0 -0
  19. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/cover.py +0 -0
  20. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/help.py +0 -0
  21. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/oss_item.py +0 -0
  22. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/parsing_yaml.py +0 -0
  23. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/read_excel.py +0 -0
  24. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/resources/frequentLicenselist.json +0 -0
  25. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/resources/frequent_license_nick_list.json +0 -0
  26. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/resources/licenses.json +0 -0
  27. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/set_log.py +0 -0
  28. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/spdx_licenses.py +0 -0
  29. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/timer_thread.py +0 -0
  30. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_excel.py +0 -0
  31. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_opossum.py +0 -0
  32. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_scancodejson.py +0 -0
  33. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_spdx.py +0 -0
  34. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_txt.py +0 -0
  35. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util/write_yaml.py +0 -0
  36. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/dependency_links.txt +0 -0
  37. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/entry_points.txt +0 -0
  38. {fosslight_util-2.1.2 → fosslight_util-2.1.4}/src/fosslight_util.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fosslight_util
3
- Version: 2.1.2
3
+ Version: 2.1.4
4
4
  Summary: FOSSLight Util
5
5
  Home-page: https://github.com/fosslight/fosslight_util
6
6
  Author: LG Electronics
@@ -15,3 +15,4 @@ numpy>=1.22.2; python_version >= '3.8'
15
15
  npm
16
16
  requests
17
17
  GitPython
18
+ cyclonedx-python-lib==8.5.*;sys_platform=="linux"
@@ -14,7 +14,7 @@ with open('requirements.txt', 'r', 'utf-8') as f:
14
14
  if __name__ == "__main__":
15
15
  setup(
16
16
  name='fosslight_util',
17
- version='2.1.2',
17
+ version='2.1.4',
18
18
  package_dir={"": "src"},
19
19
  packages=find_packages(where='src'),
20
20
  description='FOSSLight Util',
@@ -106,6 +106,7 @@ def cli_download_and_extract(link: str, target_dir: str, log_dir: str, checkout_
106
106
  datetime.now().strftime('%Y%m%d_%H-%M-%S')+".txt"
107
107
  logger, log_item = init_log(os.path.join(log_dir, log_file_name))
108
108
  link = link.strip()
109
+ is_rubygems = False
109
110
 
110
111
  try:
111
112
  if not link:
@@ -8,11 +8,12 @@ from fosslight_util.write_excel import write_result_to_excel, write_result_to_cs
8
8
  from fosslight_util.write_opossum import write_opossum
9
9
  from fosslight_util.write_yaml import write_yaml
10
10
  from fosslight_util.write_spdx import write_spdx
11
+ from fosslight_util.write_cyclonedx import write_cyclonedx
11
12
  from typing import Tuple
12
13
 
13
14
  SUPPORT_FORMAT = {'excel': '.xlsx', 'csv': '.csv', 'opossum': '.json', 'yaml': '.yaml',
14
15
  'spdx-yaml': '.yaml', 'spdx-json': '.json', 'spdx-xml': '.xml',
15
- 'spdx-tag': '.tag'}
16
+ 'spdx-tag': '.tag', 'cyclonedx-json': '.json', 'cyclonedx-xml': '.xml'}
16
17
 
17
18
 
18
19
  def check_output_format(output='', format='', customized_format={}):
@@ -182,12 +183,15 @@ def write_output_file(output_file_without_ext: str, file_extension: str, scan_it
182
183
  success, msg = write_opossum(result_file, scan_item)
183
184
  elif format == 'yaml':
184
185
  success, msg, _ = write_yaml(result_file, scan_item, False)
185
- elif format.startswith('spdx'):
186
+ elif format.startswith('spdx') or format.startswith('cyclonedx'):
186
187
  if platform.system() == 'Windows' or platform.system() == 'Darwin':
187
188
  success = False
188
189
  msg = f'{platform.system()} not support spdx format.'
189
190
  else:
190
- success, msg, _ = write_spdx(output_file_without_ext, file_extension, scan_item, spdx_version)
191
+ if format.startswith('spdx'):
192
+ success, msg, _ = write_spdx(output_file_without_ext, file_extension, scan_item, spdx_version)
193
+ elif format.startswith('cyclonedx'):
194
+ success, msg, _ = write_cyclonedx(output_file_without_ext, file_extension, scan_item)
191
195
  else:
192
196
  if file_extension == '.xlsx':
193
197
  success, msg = write_result_to_excel(result_file, scan_item, extended_header, hide_header)
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ # Copyright (c) 2024 LG Electronics Inc.
4
+ # Copyright (c) OWASP Foundation.
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ import os
8
+ import sys
9
+ import logging
10
+ import re
11
+ import json
12
+ from pathlib import Path
13
+ from datetime import datetime
14
+ from fosslight_util.spdx_licenses import get_spdx_licenses_json, get_license_from_nick
15
+ from fosslight_util.constant import (LOGGER_NAME, FOSSLIGHT_DEPENDENCY, FOSSLIGHT_SCANNER,
16
+ FOSSLIGHT_BINARY, FOSSLIGHT_SOURCE)
17
+ from fosslight_util.oss_item import CHECKSUM_NULL, get_checksum_sha1
18
+ from packageurl import PackageURL
19
+ import traceback
20
+ try:
21
+ from cyclonedx.builder.this import this_component as cdx_lib_component
22
+ from cyclonedx.exception import MissingOptionalDependencyException
23
+ from cyclonedx.factory.license import LicenseFactory
24
+ from cyclonedx.model import XsUri, ExternalReferenceType
25
+ from cyclonedx.model.bom import Bom
26
+ from cyclonedx.model.component import Component, ComponentType, HashAlgorithm, HashType, ExternalReference
27
+ from cyclonedx.model.contact import OrganizationalEntity
28
+ from cyclonedx.output import make_outputter, BaseOutput
29
+ from cyclonedx.output.json import JsonV1Dot6
30
+ from cyclonedx.schema import OutputFormat, SchemaVersion
31
+ from cyclonedx.validation import make_schemabased_validator
32
+ from cyclonedx.validation.json import JsonStrictValidator
33
+ from cyclonedx.output.json import Json as JsonOutputter
34
+ from cyclonedx.output.xml import Xml as XmlOutputter
35
+ from cyclonedx.validation.xml import XmlValidator
36
+ except Exception:
37
+ logger.info('No import cyclonedx-python-lib')
38
+ logger = logging.getLogger(LOGGER_NAME)
39
+
40
+
41
+ def write_cyclonedx(output_file_without_ext, output_extension, scan_item):
42
+ success = True
43
+ error_msg = ''
44
+
45
+ bom = Bom()
46
+ if scan_item:
47
+ try:
48
+ cover_name = scan_item.cover.get_print_json()["Tool information"].split('(').pop(0).strip()
49
+ match = re.search(r"(.+) v([0-9.]+)", cover_name)
50
+ if match:
51
+ scanner_name = match.group(1)
52
+ else:
53
+ scanner_name = FOSSLIGHT_SCANNER
54
+ except Exception:
55
+ cover_name = FOSSLIGHT_SCANNER
56
+ scanner_name = FOSSLIGHT_SCANNER
57
+
58
+ lc_factory = LicenseFactory()
59
+ bom.metadata.tools.components.add(cdx_lib_component())
60
+ bom.metadata.tools.components.add(Component(name=scanner_name.upper(),
61
+ type=ComponentType.APPLICATION))
62
+ comp_id = 0
63
+ bom.metadata.component = root_component = Component(name='Root Component',
64
+ type=ComponentType.APPLICATION,
65
+ bom_ref=str(comp_id))
66
+ relation_tree = {}
67
+ bom_ref_packages = []
68
+
69
+ output_dir = os.path.dirname(output_file_without_ext)
70
+ Path(output_dir).mkdir(parents=True, exist_ok=True)
71
+ try:
72
+ root_package = False
73
+ for scanner_name, file_items in scan_item.file_items.items():
74
+ for file_item in file_items:
75
+ if file_item.exclude:
76
+ continue
77
+ if scanner_name == FOSSLIGHT_SOURCE:
78
+ comp_type = ComponentType.FILE
79
+ else:
80
+ comp_type = ComponentType.LIBRARY
81
+
82
+ for oss_item in file_item.oss_items:
83
+ if oss_item.name == '':
84
+ if scanner_name == FOSSLIGHT_DEPENDENCY:
85
+ continue
86
+ else:
87
+ comp_name = file_item.source_name_or_path
88
+ else:
89
+ comp_name = oss_item.name
90
+
91
+ comp_id += 1
92
+ comp = Component(type=comp_type,
93
+ name=comp_name,
94
+ bom_ref=str(comp_id))
95
+
96
+ if oss_item.version != '':
97
+ comp.version = oss_item.version
98
+ if oss_item.copyright != '':
99
+ comp.copyright = oss_item.copyright
100
+ if scanner_name == FOSSLIGHT_DEPENDENCY and file_item.purl:
101
+ comp.purl = PackageURL.from_string(file_item.purl)
102
+ if scanner_name != FOSSLIGHT_DEPENDENCY:
103
+ comp.hashes = [HashType(alg=HashAlgorithm.SHA_1, content=file_item.checksum)]
104
+
105
+ if oss_item.download_location != '':
106
+ comp.external_references = [ExternalReference(url=XsUri(oss_item.download_location),
107
+ type=ExternalReferenceType.WEBSITE)]
108
+
109
+ oss_licenses = []
110
+ for ol in oss_item.license:
111
+ try:
112
+ oss_licenses.append(lc_factory.make_from_string(ol))
113
+ except Exception:
114
+ logger.info(f'No spdx license name: {oi}')
115
+ if oss_licenses:
116
+ comp.licenses = oss_licenses
117
+
118
+ root_package = False
119
+ if scanner_name == FOSSLIGHT_DEPENDENCY:
120
+ if oss_item.comment:
121
+ oss_comment = oss_item.comment.split('/')
122
+ for oc in oss_comment:
123
+ if oc in ['direct', 'transitive', 'root package']:
124
+ if oc == 'direct':
125
+ bom.register_dependency(root_component, [comp])
126
+ elif oc == 'root package':
127
+ root_package = True
128
+ root_component.name = comp_name
129
+ root_component.type = comp_type
130
+ comp_id -= 1
131
+ else:
132
+ bom.register_dependency(root_component, [comp])
133
+ if len(file_item.depends_on) > 0:
134
+ purl = file_item.purl
135
+ relation_tree[purl] = []
136
+ relation_tree[purl].extend(file_item.depends_on)
137
+
138
+ if not root_package:
139
+ bom.components.add(comp)
140
+
141
+ if len(bom.components) > 0:
142
+ for comp_purl in relation_tree:
143
+ comp = bom.get_component_by_purl(PackageURL.from_string(comp_purl))
144
+ if comp:
145
+ dep_comp_list = []
146
+ for dep_comp_purl in relation_tree[comp_purl]:
147
+ dep_comp = bom.get_component_by_purl(PackageURL.from_string(dep_comp_purl))
148
+ if dep_comp:
149
+ dep_comp_list.append(dep_comp)
150
+ bom.register_dependency(comp, dep_comp_list)
151
+
152
+ except Exception as e:
153
+ success = False
154
+ error_msg = f'Failed to create CycloneDX document object:{e}, {traceback.format_exc()}'
155
+ else:
156
+ success = False
157
+ error_msg = 'No item to write in output file.'
158
+
159
+ result_file = ''
160
+ if success:
161
+ result_file = output_file_without_ext + output_extension
162
+ try:
163
+ if output_extension == '.json':
164
+ write_cyclonedx_json(bom, result_file)
165
+ elif output_extension == '.xml':
166
+ write_cyclonedx_xml(bom, result_file)
167
+ else:
168
+ success = False
169
+ error_msg = f'Not supported output_extension({output_extension})'
170
+ except Exception as e:
171
+ success = False
172
+ error_msg = f'Failed to write CycloneDX document: {e}'
173
+ if os.path.exists(result_file):
174
+ os.remove(result_file)
175
+
176
+ return success, error_msg, result_file
177
+
178
+
179
+ def write_cyclonedx_json(bom, result_file):
180
+ success = True
181
+ try:
182
+ my_json_outputter: 'JsonOutputter' = JsonV1Dot6(bom)
183
+ my_json_outputter.output_to_file(result_file)
184
+ serialized_json = my_json_outputter.output_as_string(indent=2)
185
+ my_json_validator = JsonStrictValidator(SchemaVersion.V1_6)
186
+ try:
187
+ validation_errors = my_json_validator.validate_str(serialized_json)
188
+ if validation_errors:
189
+ logger.warning(f'JSON invalid, ValidationError: {repr(validation_errors)}')
190
+ except MissingOptionalDependencyException as error:
191
+ logger.debug(f'JSON-validation was skipped due to {error}')
192
+ except Exception as e:
193
+ success = False
194
+ return success
195
+
196
+
197
+
198
+ def write_cyclonedx_xml(bom, result_file):
199
+ success = True
200
+ try:
201
+ my_xml_outputter: BaseOutput = make_outputter(bom=bom,
202
+ output_format=OutputFormat.XML,
203
+ schema_version=SchemaVersion.V1_6)
204
+ my_xml_outputter.output_to_file(filename=result_file)
205
+ serialized_xml = my_xml_outputter.output_as_string(indent=2)
206
+ my_xml_validator = XmlValidator(SchemaVersion.V1_6)
207
+ try:
208
+ validation_errors = my_xml_validator.validate_str(serialized_xml)
209
+ if validation_errors:
210
+ logger.warning(f'XML invalid, ValidationError: {repr(validation_errors)}')
211
+ except MissingOptionalDependencyException as error:
212
+ logger.debug(f'XML-validation was skipped due to {error}')
213
+ except Exception as e:
214
+ success = False
215
+ return success
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fosslight-util
3
- Version: 2.1.2
3
+ Version: 2.1.4
4
4
  Summary: FOSSLight Util
5
5
  Home-page: https://github.com/fosslight/fosslight_util
6
6
  Author: LG Electronics
@@ -18,6 +18,7 @@ src/fosslight_util/read_excel.py
18
18
  src/fosslight_util/set_log.py
19
19
  src/fosslight_util/spdx_licenses.py
20
20
  src/fosslight_util/timer_thread.py
21
+ src/fosslight_util/write_cyclonedx.py
21
22
  src/fosslight_util/write_excel.py
22
23
  src/fosslight_util/write_opossum.py
23
24
  src/fosslight_util/write_scancodejson.py
@@ -27,3 +27,4 @@ pygit2>=1.10.1
27
27
 
28
28
  [:sys_platform == "linux"]
29
29
  spdx-tools==0.8.*
30
+ cyclonedx-python-lib==8.5.*
File without changes
File without changes
File without changes