From fb4598d65f65e65c22f008ff165dbd0316f58169 Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Tue, 5 Nov 2024 14:03:21 -0500 Subject: [PATCH 1/9] feat: add `cyclonedx.model.dependency.Dependency.provides` Signed-off-by: Uzair Chhapra --- cyclonedx/model/dependency.py | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/cyclonedx/model/dependency.py b/cyclonedx/model/dependency.py index 4cdfe17e..04645205 100644 --- a/cyclonedx/model/dependency.py +++ b/cyclonedx/model/dependency.py @@ -53,12 +53,20 @@ class Dependency: Models a Dependency within a BOM. .. note:: - See https://cyclonedx.org/docs/1.4/xml/#type_dependencyType + See: + 1. https://cyclonedx.org/docs/1.6/xml/#type_dependencyType + 2. https://cyclonedx.org/docs/1.6/json/#dependencies """ - def __init__(self, ref: BomRef, dependencies: Optional[Iterable['Dependency']] = None) -> None: + def __init__( + self, + ref: BomRef, + dependencies: Optional[Iterable['Dependency']] = None, + provides: Optional[Iterable['Dependency']] = None + ) -> None: self.ref = ref self.dependencies = dependencies or [] # type:ignore[assignment] + self.provides = provides or [] # type:ignore[assignment] @property @serializable.type_mapping(BomRefHelper) @@ -81,9 +89,23 @@ def dependencies(self) -> 'SortedSet[Dependency]': def dependencies(self, dependencies: Iterable['Dependency']) -> None: self._dependencies = SortedSet(dependencies) + @property + @serializable.json_name('provides') + @serializable.type_mapping(_DependencyRepositorySerializationHelper) + @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'provides') + def provides(self) -> 'SortedSet[Dependency]': + return self._provides + + @provides.setter + def provides(self, provides: Iterable['Dependency']) -> None: + self._provides = SortedSet(provides) + def dependencies_as_bom_refs(self) -> Set[BomRef]: return set(map(lambda d: d.ref, self.dependencies)) + def provides_as_bom_refs(self) -> Set[BomRef]: + return set(map(lambda d: d.ref, self.provides)) + def __eq__(self, other: object) -> bool: if isinstance(other, Dependency): return hash(other) == hash(self) @@ -92,17 +114,25 @@ def __eq__(self, other: object) -> bool: def __lt__(self, other: Any) -> bool: if isinstance(other, Dependency): return _ComparableTuple(( - self.ref, _ComparableTuple(self.dependencies) + self.ref, + _ComparableTuple(self.dependencies), + _ComparableTuple(self.provides) )) < _ComparableTuple(( - other.ref, _ComparableTuple(other.dependencies) + other.ref, + _ComparableTuple(other.dependencies), + _ComparableTuple(other.provides) )) return NotImplemented def __hash__(self) -> int: - return hash((self.ref, tuple(self.dependencies))) + return hash((self.ref, tuple(self.dependencies), tuple(self.provides))) def __repr__(self) -> str: - return f'' + return ( + f'' + ) class Dependable(ABC): From 00536a774cfb980fe05f2fb3ea36029bfac3410a Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Tue, 5 Nov 2024 14:36:34 -0500 Subject: [PATCH 2/9] chore(test): add unit test `test_dependency_with_provides` Signed-off-by: Uzair Chhapra --- tests/test_model_dependency.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/test_model_dependency.py b/tests/test_model_dependency.py index 77f68b79..33e8d518 100644 --- a/tests/test_model_dependency.py +++ b/tests/test_model_dependency.py @@ -41,3 +41,26 @@ def test_sort(self) -> None: sorted_deps = sorted(deps) expected_deps = reorder(deps, expected_order) self.assertEqual(sorted_deps, expected_deps) + + def test_dependency_with_provides(self) -> None: + # Create test data + ref1 = BomRef(value='be2c6502-7e9a-47db-9a66-e34f729810a3') + ref2 = BomRef(value='0b049d09-64c0-4490-a0f5-c84d9aacf857') + provides_ref1 = BomRef(value='cd3e9c95-9d41-49e7-9924-8cf0465ae789') + provides_ref2 = BomRef(value='17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda') + + # Create dependencies with provides + dep1 = Dependency(ref=ref1, provides=[Dependency(ref=provides_ref1)]) + dep2 = Dependency(ref=ref2, provides=[Dependency(ref=provides_ref2)]) + + # Verify provides field + self.assertEqual(len(dep1.provides), 1) + self.assertEqual(len(dep2.provides), 1) + + # Check provides_as_bom_refs + self.assertEqual(dep1.provides_as_bom_refs(), {provides_ref1}) + self.assertEqual(dep2.provides_as_bom_refs(), {provides_ref2}) + + # Verify comparison and hashing + self.assertNotEqual(hash(dep1), hash(dep2)) + self.assertNotEqual(dep1, dep2) From abf6abfcf651b1defd1945b99486a96c4e8d793c Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Mon, 11 Nov 2024 10:10:23 -0500 Subject: [PATCH 3/9] ft: update `validate` and `register_dependency` to read `provides` Signed-off-by: Uzair Chhapra --- cyclonedx/model/bom.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/cyclonedx/model/bom.py b/cyclonedx/model/bom.py index 7b657604..715a95c0 100644 --- a/cyclonedx/model/bom.py +++ b/cyclonedx/model/bom.py @@ -644,23 +644,36 @@ def has_vulnerabilities(self) -> bool: """ return bool(self.vulnerabilities) - def register_dependency(self, target: Dependable, depends_on: Optional[Iterable[Dependable]] = None) -> None: + def register_dependency( + self, + target: Dependable, + depends_on: Optional[Iterable[Dependable]] = None, + provides: Optional[Iterable[Dependable]] = None, + ) -> None: _d = next(filter(lambda _d: _d.ref == target.bom_ref, self.dependencies), None) if _d: # Dependency Target already registered - but it might have new dependencies to add if depends_on: _d.dependencies.update(map(lambda _d: Dependency(ref=_d.bom_ref), depends_on)) + if provides: + _d.provides.update(map(lambda _p: Dependency(ref=_p.bom_ref), provides)) else: # First time we are seeing this target as a Dependency - self._dependencies.add(Dependency( - ref=target.bom_ref, - dependencies=map(lambda _dep: Dependency(ref=_dep.bom_ref), depends_on) if depends_on else [] - )) + self._dependencies.add( + Dependency( + ref=target.bom_ref, + dependencies=map(lambda _dep: Dependency(ref=_dep.bom_ref), depends_on) if depends_on else [], + provides=map(lambda _prov: Dependency(ref=_prov.bom_ref), provides) if provides else [], + ) + ) if depends_on: # Ensure dependents are registered with no further dependents in the DependencyGraph for _d2 in depends_on: self.register_dependency(target=_d2, depends_on=None) + if provides: + for _p2 in provides: + self.register_dependency(target=_p2, depends_on=None, provides=None) def urn(self) -> str: return f'{_BOM_LINK_PREFIX}{self.serial_number}/{self.version}' @@ -681,12 +694,14 @@ def validate(self) -> bool: for _s in self.services: self.register_dependency(target=_s) - # 1. Make sure dependencies are all in this Bom. + # 1. Make sure dependencies and provides are all in this Bom. component_bom_refs = set(map(lambda c: c.bom_ref, self._get_all_components())) | set( map(lambda s: s.bom_ref, self.services)) + dependency_bom_refs = set(chain( (d.ref for d in self.dependencies), - chain.from_iterable(d.dependencies_as_bom_refs() for d in self.dependencies) + chain.from_iterable(d.dependencies_as_bom_refs() for d in self.dependencies), + chain.from_iterable(d.provides_as_bom_refs() for d in self.dependencies) # Include provides refs here )) dependency_diff = dependency_bom_refs - component_bom_refs if len(dependency_diff) > 0: From 8cdb39b62cc5d51cf2e307c574567f442098b8a0 Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Mon, 11 Nov 2024 10:25:54 -0500 Subject: [PATCH 4/9] chore: set view schema to 1.6 for provides Signed-off-by: Uzair Chhapra --- cyclonedx/model/dependency.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cyclonedx/model/dependency.py b/cyclonedx/model/dependency.py index 04645205..27a9aab3 100644 --- a/cyclonedx/model/dependency.py +++ b/cyclonedx/model/dependency.py @@ -22,6 +22,8 @@ import serializable from sortedcontainers import SortedSet +from cyclonedx.schema.schema import SchemaVersion1Dot6 + from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.serialization import SerializationOfUnexpectedValueException from ..serialization import BomRefHelper @@ -90,6 +92,7 @@ def dependencies(self, dependencies: Iterable['Dependency']) -> None: self._dependencies = SortedSet(dependencies) @property + @serializable.view(SchemaVersion1Dot6) @serializable.json_name('provides') @serializable.type_mapping(_DependencyRepositorySerializationHelper) @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'provides') From 2525660a4bfafb9cdc87dbb6d471953462febf4b Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Mon, 11 Nov 2024 10:28:43 -0500 Subject: [PATCH 5/9] chore(test): add test `get_bom_with_provides_valid` Signed-off-by: Uzair Chhapra --- tests/_data/models.py | 22 ++++ .../get_bom_with_provides_valid-1.6.json.bin | 113 ++++++++++++++++++ .../get_bom_with_provides_valid-1.6.xml.bin | 77 ++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin diff --git a/tests/_data/models.py b/tests/_data/models.py index ffbf7d4a..d34414f9 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -1310,6 +1310,28 @@ def get_bom_with_definitions_standards() -> Bom: ) +def get_bom_with_provides_valid() -> Bom: + c1 = get_component_toml_with_hashes_with_references('crypto-library') + c2 = get_component_setuptools_simple('some-library') + c3 = get_component_crypto_asset_algorithm('crypto-algorithm') + return _make_bom( + components=[c1, c2, c3], + dependencies=[ + Dependency( + ref=c1.bom_ref, + dependencies=[Dependency(ref=c2.bom_ref)], + provides=[Dependency(ref=c3.bom_ref)] + ), + Dependency( + ref=c2.bom_ref + ), + Dependency( + ref=c3.bom_ref + ), + ], + ) + + # --- diff --git a/tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin b/tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin new file mode 100644 index 00000000..5aa6bc69 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin @@ -0,0 +1,113 @@ +{ + "components": [ + { + "bom-ref": "crypto-algorithm", + "cryptoProperties": { + "algorithmProperties": { + "certificationLevel": [ + "fips140-1-l1", + "fips140-2-l3", + "other" + ], + "classicalSecurityLevel": 2, + "cryptoFunctions": [ + "sign", + "unknown" + ], + "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", + "executionEnvironment": "software-plain-ram", + "implementationPlatform": "generic", + "mode": "ecb", + "nistQuantumSecurityLevel": 2, + "padding": "pkcs7", + "parameterSetIdentifier": "a-parameter-set-id", + "primitive": "kem" + }, + "assetType": "algorithm", + "oid": "an-oid-here" + }, + "name": "My Algorithm", + "tags": [ + "algorithm" + ], + "type": "cryptographic-asset", + "version": "1.0" + }, + { + "author": "Test Author", + "bom-ref": "some-library", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "name": "setuptools", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "type": "library", + "version": "50.3.2" + }, + { + "bom-ref": "crypto-library", + "externalReferences": [ + { + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "type": "distribution", + "url": "https://cyclonedx.org" + } + ], + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "name": "toml", + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "type": "library", + "version": "0.10.2" + } + ], + "dependencies": [ + { + "ref": "crypto-algorithm" + }, + { + "dependsOn": [ + "some-library" + ], + "provides": [ + "crypto-algorithm" + ], + "ref": "crypto-library" + }, + { + "ref": "some-library" + } + ], + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin new file mode 100644 index 00000000..5722dbf4 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin @@ -0,0 +1,77 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + + + My Algorithm + 1.0 + + algorithm + + kem + a-parameter-set-id + 9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj + software-plain-ram + generic + fips140-1-l1 + fips140-2-l3 + other + ecb + pkcs7 + + sign + unknown + + 2 + 2 + + an-oid-here + + + algorithm + + + + Test Author + setuptools + 50.3.2 + + + MIT + + + pkg:pypi/setuptools@50.3.2?extension=tar.gz + + + toml + 0.10.2 + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + pkg:pypi/toml@0.10.2?extension=tar.gz + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + + + + + + + + + + val1 + val2 + + From bd370af2ee9fab8de74406f30c8d52bbac4ae128 Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Sun, 17 Nov 2024 19:09:08 -0500 Subject: [PATCH 6/9] fix: rename test to apply only for v1.6 Signed-off-by: Uzair Chhapra --- tests/_data/models.py | 2 +- ...lid-1.6.json.bin => get_bom_v1_6_with_provides-1.6.json.bin} | 0 ...valid-1.6.xml.bin => get_bom_v1_6_with_provides-1.6.xml.bin} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename tests/_data/snapshots/{get_bom_with_provides_valid-1.6.json.bin => get_bom_v1_6_with_provides-1.6.json.bin} (100%) rename tests/_data/snapshots/{get_bom_with_provides_valid-1.6.xml.bin => get_bom_v1_6_with_provides-1.6.xml.bin} (100%) diff --git a/tests/_data/models.py b/tests/_data/models.py index d34414f9..cfdb9e21 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -1310,7 +1310,7 @@ def get_bom_with_definitions_standards() -> Bom: ) -def get_bom_with_provides_valid() -> Bom: +def get_bom_v1_6_with_provides() -> Bom: c1 = get_component_toml_with_hashes_with_references('crypto-library') c2 = get_component_setuptools_simple('some-library') c3 = get_component_crypto_asset_algorithm('crypto-algorithm') diff --git a/tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin similarity index 100% rename from tests/_data/snapshots/get_bom_with_provides_valid-1.6.json.bin rename to tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin diff --git a/tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin similarity index 100% rename from tests/_data/snapshots/get_bom_with_provides_valid-1.6.xml.bin rename to tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin From 7b6498568c38f09e7dd6ec41d6c6d1fe57997d71 Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Thu, 3 Apr 2025 19:14:29 -0400 Subject: [PATCH 7/9] chore(test): add test `get_bom_with_provides` Signed-off-by: Uzair Chhapra --- tests/_data/models.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/_data/models.py b/tests/_data/models.py index 6a25c552..66c1bda5 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -1406,6 +1406,28 @@ def get_bom_with_definitions_and_detailed_standards() -> Bom: ])) +def get_bom_with_provides() -> Bom: + c1 = get_component_toml_with_hashes_with_references('crypto-library') + c2 = get_component_setuptools_simple('some-library') + c3 = get_component_crypto_asset_algorithm('crypto-algorithm') + return _make_bom( + components=[c1, c2, c3], + dependencies=[ + Dependency( + ref=c1.bom_ref, + dependencies=[Dependency(ref=c2.bom_ref)], + provides=[Dependency(ref=c3.bom_ref)] + ), + Dependency( + ref=c2.bom_ref + ), + Dependency( + ref=c3.bom_ref + ), + ], + ) + + def get_bom_for_issue540_duplicate_components() -> Bom: # tests https://github.com/CycloneDX/cyclonedx-python-lib/issues/540 bom = _make_bom() From 3b4f7902149d5707ee050163c84bc47cd0e80eef Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Thu, 3 Apr 2025 19:27:13 -0400 Subject: [PATCH 8/9] chore(test): add snapshots for `get_bom_with_provides` Signed-off-by: Uzair Chhapra --- .../get_bom_with_provides-1.6.json.bin | 113 ++++++++++++++++++ .../get_bom_with_provides-1.6.xml.bin | 77 ++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.6.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin diff --git a/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin new file mode 100644 index 00000000..5aa6bc69 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin @@ -0,0 +1,113 @@ +{ + "components": [ + { + "bom-ref": "crypto-algorithm", + "cryptoProperties": { + "algorithmProperties": { + "certificationLevel": [ + "fips140-1-l1", + "fips140-2-l3", + "other" + ], + "classicalSecurityLevel": 2, + "cryptoFunctions": [ + "sign", + "unknown" + ], + "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", + "executionEnvironment": "software-plain-ram", + "implementationPlatform": "generic", + "mode": "ecb", + "nistQuantumSecurityLevel": 2, + "padding": "pkcs7", + "parameterSetIdentifier": "a-parameter-set-id", + "primitive": "kem" + }, + "assetType": "algorithm", + "oid": "an-oid-here" + }, + "name": "My Algorithm", + "tags": [ + "algorithm" + ], + "type": "cryptographic-asset", + "version": "1.0" + }, + { + "author": "Test Author", + "bom-ref": "some-library", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "name": "setuptools", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "type": "library", + "version": "50.3.2" + }, + { + "bom-ref": "crypto-library", + "externalReferences": [ + { + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "type": "distribution", + "url": "https://cyclonedx.org" + } + ], + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "name": "toml", + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "type": "library", + "version": "0.10.2" + } + ], + "dependencies": [ + { + "ref": "crypto-algorithm" + }, + { + "dependsOn": [ + "some-library" + ], + "provides": [ + "crypto-algorithm" + ], + "ref": "crypto-library" + }, + { + "ref": "some-library" + } + ], + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.6" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin new file mode 100644 index 00000000..5722dbf4 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin @@ -0,0 +1,77 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + + + My Algorithm + 1.0 + + algorithm + + kem + a-parameter-set-id + 9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj + software-plain-ram + generic + fips140-1-l1 + fips140-2-l3 + other + ecb + pkcs7 + + sign + unknown + + 2 + 2 + + an-oid-here + + + algorithm + + + + Test Author + setuptools + 50.3.2 + + + MIT + + + pkg:pypi/setuptools@50.3.2?extension=tar.gz + + + toml + 0.10.2 + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + pkg:pypi/toml@0.10.2?extension=tar.gz + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + + + + + + + + + + val1 + val2 + + From 39a5f8f689967e4937ffb073e189e24c9b75af0b Mon Sep 17 00:00:00 2001 From: Uzair Chhapra Date: Fri, 4 Apr 2025 09:22:42 -0400 Subject: [PATCH 9/9] chore(test): updated model `get_bom_with_provides` Signed-off-by: Uzair Chhapra --- tests/_data/models.py | 39 +++--- .../get_bom_v1_6_with_provides-1.6.json.bin | 113 ------------------ .../get_bom_v1_6_with_provides-1.6.xml.bin | 77 ------------ .../get_bom_with_provides-1.0.xml.bin | 15 +++ .../get_bom_with_provides-1.1.xml.bin | 13 ++ .../get_bom_with_provides-1.2.json.bin | 44 +++++++ .../get_bom_with_provides-1.2.xml.bin | 27 +++++ .../get_bom_with_provides-1.3.json.bin | 44 +++++++ .../get_bom_with_provides-1.3.xml.bin | 27 +++++ .../get_bom_with_provides-1.4.json.bin | 41 +++++++ .../get_bom_with_provides-1.4.xml.bin | 24 ++++ .../get_bom_with_provides-1.5.json.bin | 51 ++++++++ .../get_bom_with_provides-1.5.xml.bin | 28 +++++ .../get_bom_with_provides-1.6.json.bin | 95 +++------------ .../get_bom_with_provides-1.6.xml.bin | 73 ++--------- 15 files changed, 365 insertions(+), 346 deletions(-) delete mode 100644 tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin delete mode 100644 tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.0.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.1.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.2.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.2.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.3.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.3.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.4.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.4.xml.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.5.json.bin create mode 100644 tests/_data/snapshots/get_bom_with_provides-1.5.xml.bin diff --git a/tests/_data/models.py b/tests/_data/models.py index 66c1bda5..f07ca8c2 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -1407,25 +1407,26 @@ def get_bom_with_definitions_and_detailed_standards() -> Bom: def get_bom_with_provides() -> Bom: - c1 = get_component_toml_with_hashes_with_references('crypto-library') - c2 = get_component_setuptools_simple('some-library') - c3 = get_component_crypto_asset_algorithm('crypto-algorithm') - return _make_bom( - components=[c1, c2, c3], - dependencies=[ - Dependency( - ref=c1.bom_ref, - dependencies=[Dependency(ref=c2.bom_ref)], - provides=[Dependency(ref=c3.bom_ref)] - ), - Dependency( - ref=c2.bom_ref - ), - Dependency( - ref=c3.bom_ref - ), - ], - ) + bom = _make_bom() + bom.metadata.component = root_component = Component(name='app A', bom_ref='A', type=ComponentType.APPLICATION) + bom.components.add( + c1 := Component(name='device B', bom_ref='B', type=ComponentType.DEVICE)) + bom.components.add( + c2 := Component(name='device C', bom_ref='C', type=ComponentType.DEVICE)) + bom.dependencies = [ + Dependency( + ref=c2.bom_ref + ), + Dependency( + ref=c1.bom_ref, + provides=[Dependency(ref=c2.bom_ref)] + ), + Dependency( + ref=root_component.bom_ref, + dependencies=[Dependency(ref=c2.bom_ref)] + ), + ] + return bom def get_bom_for_issue540_duplicate_components() -> Bom: diff --git a/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin deleted file mode 100644 index 5aa6bc69..00000000 --- a/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.json.bin +++ /dev/null @@ -1,113 +0,0 @@ -{ - "components": [ - { - "bom-ref": "crypto-algorithm", - "cryptoProperties": { - "algorithmProperties": { - "certificationLevel": [ - "fips140-1-l1", - "fips140-2-l3", - "other" - ], - "classicalSecurityLevel": 2, - "cryptoFunctions": [ - "sign", - "unknown" - ], - "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", - "executionEnvironment": "software-plain-ram", - "implementationPlatform": "generic", - "mode": "ecb", - "nistQuantumSecurityLevel": 2, - "padding": "pkcs7", - "parameterSetIdentifier": "a-parameter-set-id", - "primitive": "kem" - }, - "assetType": "algorithm", - "oid": "an-oid-here" - }, - "name": "My Algorithm", - "tags": [ - "algorithm" - ], - "type": "cryptographic-asset", - "version": "1.0" - }, - { - "author": "Test Author", - "bom-ref": "some-library", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "crypto-library", - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "name": "toml", - "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" - } - ], - "dependencies": [ - { - "ref": "crypto-algorithm" - }, - { - "dependsOn": [ - "some-library" - ], - "provides": [ - "crypto-algorithm" - ], - "ref": "crypto-library" - }, - { - "ref": "some-library" - } - ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, - { - "name": "key2", - "value": "val2" - } - ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, - "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", - "bomFormat": "CycloneDX", - "specVersion": "1.6" -} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin deleted file mode 100644 index 5722dbf4..00000000 --- a/tests/_data/snapshots/get_bom_v1_6_with_provides-1.6.xml.bin +++ /dev/null @@ -1,77 +0,0 @@ - - - - 2023-01-07T13:44:32.312678+00:00 - - - - My Algorithm - 1.0 - - algorithm - - kem - a-parameter-set-id - 9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj - software-plain-ram - generic - fips140-1-l1 - fips140-2-l3 - other - ecb - pkcs7 - - sign - unknown - - 2 - 2 - - an-oid-here - - - algorithm - - - - Test Author - setuptools - 50.3.2 - - - MIT - - - pkg:pypi/setuptools@50.3.2?extension=tar.gz - - - toml - 0.10.2 - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - pkg:pypi/toml@0.10.2?extension=tar.gz - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - - - - - - - - - - val1 - val2 - - diff --git a/tests/_data/snapshots/get_bom_with_provides-1.0.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.0.xml.bin new file mode 100644 index 00000000..ec2a2753 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.0.xml.bin @@ -0,0 +1,15 @@ + + + + + device B + + false + + + device C + + false + + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.1.xml.bin new file mode 100644 index 00000000..c1fc58db --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.1.xml.bin @@ -0,0 +1,13 @@ + + + + + device B + + + + device C + + + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.2.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.2.json.bin new file mode 100644 index 00000000..e811633a --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.2.json.bin @@ -0,0 +1,44 @@ +{ + "components": [ + { + "bom-ref": "B", + "name": "device B", + "type": "device", + "version": "" + }, + { + "bom-ref": "C", + "name": "device C", + "type": "device", + "version": "" + } + ], + "dependencies": [ + { + "dependsOn": [ + "C" + ], + "ref": "A" + }, + { + "ref": "B" + }, + { + "ref": "C" + } + ], + "metadata": { + "component": { + "bom-ref": "A", + "name": "app A", + "type": "application", + "version": "" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "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" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.2.xml.bin new file mode 100644 index 00000000..bcbe4d3c --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.2.xml.bin @@ -0,0 +1,27 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + app A + + + + + + device B + + + + device C + + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.3.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.3.json.bin new file mode 100644 index 00000000..e36390d1 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.3.json.bin @@ -0,0 +1,44 @@ +{ + "components": [ + { + "bom-ref": "B", + "name": "device B", + "type": "device", + "version": "" + }, + { + "bom-ref": "C", + "name": "device C", + "type": "device", + "version": "" + } + ], + "dependencies": [ + { + "dependsOn": [ + "C" + ], + "ref": "A" + }, + { + "ref": "B" + }, + { + "ref": "C" + } + ], + "metadata": { + "component": { + "bom-ref": "A", + "name": "app A", + "type": "application", + "version": "" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "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" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.3.xml.bin new file mode 100644 index 00000000..6dbfe0ac --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.3.xml.bin @@ -0,0 +1,27 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + app A + + + + + + device B + + + + device C + + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.4.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.4.json.bin new file mode 100644 index 00000000..ac399a6b --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.4.json.bin @@ -0,0 +1,41 @@ +{ + "components": [ + { + "bom-ref": "B", + "name": "device B", + "type": "device" + }, + { + "bom-ref": "C", + "name": "device C", + "type": "device" + } + ], + "dependencies": [ + { + "dependsOn": [ + "C" + ], + "ref": "A" + }, + { + "ref": "B" + }, + { + "ref": "C" + } + ], + "metadata": { + "component": { + "bom-ref": "A", + "name": "app A", + "type": "application" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "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" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.4.xml.bin new file mode 100644 index 00000000..90c727eb --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.4.xml.bin @@ -0,0 +1,24 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + app A + + + + + device B + + + device C + + + + + + + + + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.5.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.5.json.bin new file mode 100644 index 00000000..484b469b --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.5.json.bin @@ -0,0 +1,51 @@ +{ + "components": [ + { + "bom-ref": "B", + "name": "device B", + "type": "device" + }, + { + "bom-ref": "C", + "name": "device C", + "type": "device" + } + ], + "dependencies": [ + { + "dependsOn": [ + "C" + ], + "ref": "A" + }, + { + "ref": "B" + }, + { + "ref": "C" + } + ], + "metadata": { + "component": { + "bom-ref": "A", + "name": "app A", + "type": "application" + }, + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} \ No newline at end of file diff --git a/tests/_data/snapshots/get_bom_with_provides-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.5.xml.bin new file mode 100644 index 00000000..da72fa10 --- /dev/null +++ b/tests/_data/snapshots/get_bom_with_provides-1.5.xml.bin @@ -0,0 +1,28 @@ + + + + 2023-01-07T13:44:32.312678+00:00 + + app A + + + + + device B + + + device C + + + + + + + + + + + val1 + val2 + + diff --git a/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin b/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin index 5aa6bc69..01f0a807 100644 --- a/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_provides-1.6.json.bin @@ -1,98 +1,39 @@ { "components": [ { - "bom-ref": "crypto-algorithm", - "cryptoProperties": { - "algorithmProperties": { - "certificationLevel": [ - "fips140-1-l1", - "fips140-2-l3", - "other" - ], - "classicalSecurityLevel": 2, - "cryptoFunctions": [ - "sign", - "unknown" - ], - "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", - "executionEnvironment": "software-plain-ram", - "implementationPlatform": "generic", - "mode": "ecb", - "nistQuantumSecurityLevel": 2, - "padding": "pkcs7", - "parameterSetIdentifier": "a-parameter-set-id", - "primitive": "kem" - }, - "assetType": "algorithm", - "oid": "an-oid-here" - }, - "name": "My Algorithm", - "tags": [ - "algorithm" - ], - "type": "cryptographic-asset", - "version": "1.0" - }, - { - "author": "Test Author", - "bom-ref": "some-library", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "bom-ref": "B", + "name": "device B", + "type": "device" }, { - "bom-ref": "crypto-library", - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "name": "toml", - "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "bom-ref": "C", + "name": "device C", + "type": "device" } ], "dependencies": [ - { - "ref": "crypto-algorithm" - }, { "dependsOn": [ - "some-library" + "C" ], + "ref": "A" + }, + { "provides": [ - "crypto-algorithm" + "C" ], - "ref": "crypto-library" + "ref": "B" }, { - "ref": "some-library" + "ref": "C" } ], "metadata": { + "component": { + "bom-ref": "A", + "name": "app A", + "type": "application" + }, "timestamp": "2023-01-07T13:44:32.312678+00:00" }, "properties": [ diff --git a/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin index 5722dbf4..d6e85b0f 100644 --- a/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_provides-1.6.xml.bin @@ -2,73 +2,26 @@ 2023-01-07T13:44:32.312678+00:00 + + app A + - - My Algorithm - 1.0 - - algorithm - - kem - a-parameter-set-id - 9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj - software-plain-ram - generic - fips140-1-l1 - fips140-2-l3 - other - ecb - pkcs7 - - sign - unknown - - 2 - 2 - - an-oid-here - - - algorithm - - - - Test Author - setuptools - 50.3.2 - - - MIT - - - pkg:pypi/setuptools@50.3.2?extension=tar.gz + + device B - - toml - 0.10.2 - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - pkg:pypi/toml@0.10.2?extension=tar.gz - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - + + device C - - - - + + + + + - + val1