Skip to content

Commit

Permalink
fix: ToolRepository serialize migrated tools deduplicated (#686)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
  • Loading branch information
jkowalleck authored Sep 27, 2024
1 parent e00af17 commit 35ccdd1
Show file tree
Hide file tree
Showing 36 changed files with 820 additions and 515 deletions.
20 changes: 12 additions & 8 deletions cyclonedx/model/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
# Copyright (c) OWASP Foundation. All Rights Reserved.


from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Type, Union
from itertools import chain
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Type, Union
from warnings import warn
from xml.etree.ElementTree import Element # nosec B405

Expand Down Expand Up @@ -265,12 +266,14 @@ def __hash__(self) -> int:
class _ToolRepositoryHelper(BaseHelper):

@staticmethod
def __all_as_tools(o: ToolRepository) -> Tuple[Tool, ...]:
return (
*o.tools,
*map(Tool.from_component, o.components),
*map(Tool.from_service, o.services),
)
def __all_as_tools(o: ToolRepository) -> 'SortedSet[Tool]':
# use a set here, so the collection gets deduplicated.
# use SortedSet set here, so the order stays reproducible.
return SortedSet(chain(
o.tools,
map(Tool.from_component, o.components),
map(Tool.from_service, o.services),
))

@staticmethod
def __supports_components_and_services(view: Any) -> bool:
Expand All @@ -284,7 +287,8 @@ def json_normalize(cls, o: ToolRepository, *,
view: Optional[Type['ViewType']],
**__: Any) -> Any:
if len(o.tools) > 0 or not cls.__supports_components_and_services(view):
return cls.__all_as_tools(o) or None
ts = cls.__all_as_tools(o)
return tuple(ts) if ts else None
elem: Dict[str, Any] = {}
if o.components:
elem['components'] = tuple(o.components)
Expand Down
25 changes: 25 additions & 0 deletions tests/_data/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1172,6 +1172,31 @@ def get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate
return _make_bom(metadata=BomMetaData(tools=tools))


def get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate() -> Bom:
"""on serialization, it is expected that only tools are emitted, and that they are deduplicated"""
tools = ToolRepository()
tcomp = tools.components
tserv = tools.services
ttools = tools.tools
tcomp.update((
this_component(),
Component(name='test-component'),
Component(type=ComponentType.APPLICATION,
group='acme',
name='other-component'),
))
tserv.update((
Service(name='test-service'),
Service(group='acme',
name='other-service'),
))
ttools.clear()
# duplicate components and services as tools
ttools.update(map(Tool.from_component, tcomp))
ttools.update(map(Tool.from_service, tserv))
return _make_bom(metadata=BomMetaData(tools=tools))


def get_bom_for_issue_497_urls() -> Bom:
"""regression test for issue #497
see https://github.com/CycloneDX/cyclonedx-python-lib/issues/497
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.0" version="1">
<components/>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" ?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.1" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
<components/>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"metadata": {
"timestamp": "2023-01-07T13:44:32.312678+00:00",
"tools": [
{
"name": "cyclonedx-python-lib",
"vendor": "CycloneDX",
"version": "TESTING"
},
{
"name": "other-component",
"vendor": "acme"
},
{
"name": "other-service",
"vendor": "acme"
},
{
"name": "test-component"
},
{
"name": "test-service"
}
]
},
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.2" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
<metadata>
<timestamp>2023-01-07T13:44:32.312678+00:00</timestamp>
<tools>
<tool>
<vendor>CycloneDX</vendor>
<name>cyclonedx-python-lib</name>
<version>TESTING</version>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-component</name>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-service</name>
</tool>
<tool>
<name>test-component</name>
</tool>
<tool>
<name>test-service</name>
</tool>
</tools>
</metadata>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"metadata": {
"timestamp": "2023-01-07T13:44:32.312678+00:00",
"tools": [
{
"name": "cyclonedx-python-lib",
"vendor": "CycloneDX",
"version": "TESTING"
},
{
"name": "other-component",
"vendor": "acme"
},
{
"name": "other-service",
"vendor": "acme"
},
{
"name": "test-component"
},
{
"name": "test-service"
}
]
},
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.3"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
<metadata>
<timestamp>2023-01-07T13:44:32.312678+00:00</timestamp>
<tools>
<tool>
<vendor>CycloneDX</vendor>
<name>cyclonedx-python-lib</name>
<version>TESTING</version>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-component</name>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-service</name>
</tool>
<tool>
<name>test-component</name>
</tool>
<tool>
<name>test-service</name>
</tool>
</tools>
</metadata>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"metadata": {
"timestamp": "2023-01-07T13:44:32.312678+00:00",
"tools": [
{
"externalReferences": [
{
"type": "build-system",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib/actions"
},
{
"type": "distribution",
"url": "https://pypi.org/project/cyclonedx-python-lib/"
},
{
"type": "documentation",
"url": "https://cyclonedx-python-library.readthedocs.io/"
},
{
"type": "issue-tracker",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib/issues"
},
{
"type": "license",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE"
},
{
"type": "release-notes",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md"
},
{
"type": "vcs",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib"
},
{
"type": "website",
"url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme"
}
],
"name": "cyclonedx-python-lib",
"vendor": "CycloneDX",
"version": "TESTING"
},
{
"name": "other-component",
"vendor": "acme"
},
{
"name": "other-service",
"vendor": "acme"
},
{
"name": "test-component"
},
{
"name": "test-service"
}
]
},
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.4"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" ?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
<metadata>
<timestamp>2023-01-07T13:44:32.312678+00:00</timestamp>
<tools>
<tool>
<vendor>CycloneDX</vendor>
<name>cyclonedx-python-lib</name>
<version>TESTING</version>
<externalReferences>
<reference type="build-system">
<url>https://github.com/CycloneDX/cyclonedx-python-lib/actions</url>
</reference>
<reference type="distribution">
<url>https://pypi.org/project/cyclonedx-python-lib/</url>
</reference>
<reference type="documentation">
<url>https://cyclonedx-python-library.readthedocs.io/</url>
</reference>
<reference type="issue-tracker">
<url>https://github.com/CycloneDX/cyclonedx-python-lib/issues</url>
</reference>
<reference type="license">
<url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE</url>
</reference>
<reference type="release-notes">
<url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md</url>
</reference>
<reference type="vcs">
<url>https://github.com/CycloneDX/cyclonedx-python-lib</url>
</reference>
<reference type="website">
<url>https://github.com/CycloneDX/cyclonedx-python-lib/#readme</url>
</reference>
</externalReferences>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-component</name>
</tool>
<tool>
<vendor>acme</vendor>
<name>other-service</name>
</tool>
<tool>
<name>test-component</name>
</tool>
<tool>
<name>test-service</name>
</tool>
</tools>
</metadata>
</bom>
Loading

0 comments on commit 35ccdd1

Please sign in to comment.