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