diff --git a/cyclonedx/model/__init__.py b/cyclonedx/model/__init__.py index f949e10ce..9174e0700 100644 --- a/cyclonedx/model/__init__.py +++ b/cyclonedx/model/__init__.py @@ -22,46 +22,61 @@ from a `cyclonedx.parser.BaseParser` implementation. """ +from ..exception.model import InvalidLocaleTypeException, InvalidUriException +from ..serialization import VERSIONS_1_1_AND_LATER +from .bom_ref import BomRef +from ..serialization import ( + ALL_VERSIONS, + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_2_AND_LATER, + VERSIONS_1_3_AND_LATER, + VERSIONS_1_4_AND_LATER, + VERSIONS_1_5_AND_LATER, + VERSIONS_1_6_AND_LATER, + VERSIONS_1_7_AND_LATER, +) +from ..schema import SchemaVersion +from ..exception.serialization import CycloneDxDeserializationException, SerializationOfUnexpectedValueException import re import sys -from collections.abc import Generator, Iterable +from collections.abc import Iterable from datetime import datetime from enum import Enum from functools import reduce -from json import loads as json_loads -from typing import Any, Optional, Union +from typing import TYPE_CHECKING, Any, ClassVar, Optional, Union from urllib.parse import quote as url_quote from uuid import UUID from warnings import warn -from xml.etree.ElementTree import Element as XmlElement # nosec B405 if sys.version_info >= (3, 13): from warnings import deprecated else: from typing_extensions import deprecated -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet from .._internal.compare import ComparableTuple as _ComparableTuple -from ..exception.model import InvalidLocaleTypeException, InvalidUriException -from ..exception.serialization import CycloneDxDeserializationException, SerializationOfUnexpectedValueException -from ..schema.schema import ( - SchemaVersion1Dot0, - SchemaVersion1Dot1, - SchemaVersion1Dot2, - SchemaVersion1Dot3, - SchemaVersion1Dot4, - SchemaVersion1Dot5, - SchemaVersion1Dot6, - SchemaVersion1Dot7, -) -from .bom_ref import BomRef + + +def _sortedset_converter(value: Any) -> SortedSet: + """Converter to ensure values are always SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) + _BOM_LINK_PREFIX = 'urn:cdx:' -@serializable.serializable_enum class DataFlow(str, Enum): """ This is our internal representation of the dataFlowType simple type within the CycloneDX standard. @@ -75,7 +90,7 @@ class DataFlow(str, Enum): UNKNOWN = 'unknown' -@serializable.serializable_class +@attrs.define class DataClassification: """ This is our internal representation of the `dataClassificationType` complex type within the CycloneDX standard. @@ -87,78 +102,22 @@ class DataClassification: See the CycloneDX Schema for dataClassificationType: https://cyclonedx.org/docs/1.7/xml/#type_dataClassificationType """ - - def __init__( - self, *, - flow: DataFlow, - classification: str, - ) -> None: - self.flow = flow - self.classification = classification - - @property - @serializable.xml_attribute() - def flow(self) -> DataFlow: - """ - Specifies the flow direction of the data. - - Valid values are: inbound, outbound, bi-directional, and unknown. - - Direction is relative to the service. - - - Inbound flow states that data enters the service - - Outbound flow states that data leaves the service - - Bi-directional states that data flows both ways - - Unknown states that the direction is not known - - Returns: - `DataFlow` - """ - return self._flow - - @flow.setter - def flow(self, flow: DataFlow) -> None: - self._flow = flow - - @property - @serializable.xml_name('.') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def classification(self) -> str: - """ - Data classification tags data according to its type, sensitivity, and value if altered, stolen, or destroyed. - - Returns: - `str` - """ - return self._classification - - @classification.setter - def classification(self, classification: str) -> None: - self._classification = classification - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.flow, self.classification - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, DataClassification): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + flow: DataFlow = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + classification: str = attrs.field( + metadata={METADATA_KEY_XML_NAME: '.'} + ) def __lt__(self, other: object) -> bool: if isinstance(other, DataClassification): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.flow, self.classification) < (other.flow, other.classification) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' + return hash((self.flow, self.classification)) -@serializable.serializable_enum class Encoding(str, Enum): """ This is our internal representation of the encoding simple type within the CycloneDX standard. @@ -169,7 +128,7 @@ class Encoding(str, Enum): BASE_64 = 'base64' -@serializable.serializable_class +@attrs.define class AttachedText: """ This is our internal representation of the `attachedTextType` complex type within the CycloneDX standard. @@ -180,89 +139,37 @@ class AttachedText: DEFAULT_CONTENT_TYPE = 'text/plain' - def __init__( - self, *, - content: str, - content_type: str = DEFAULT_CONTENT_TYPE, - encoding: Optional[Encoding] = None, - ) -> None: - self.content_type = content_type - self.encoding = encoding - self.content = content - - @property - @serializable.xml_attribute() - @serializable.xml_name('content-type') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def content_type(self) -> str: - """ - Specifies the content type of the text. Defaults to text/plain if not specified. - - Returns: - `str` - """ - return self._content_type - - @content_type.setter - def content_type(self, content_type: str) -> None: - self._content_type = content_type - - @property - @serializable.xml_attribute() - def encoding(self) -> Optional[Encoding]: - """ - Specifies the optional encoding the text is represented in. - - Returns: - `Encoding` if set else `None` - """ - return self._encoding - - @encoding.setter - def encoding(self, encoding: Optional[Encoding]) -> None: - self._encoding = encoding - - @property - @serializable.xml_name('.') - def content(self) -> str: - """ - The attachment data. - - Proactive controls such as input validation and sanitization should be employed to prevent misuse of attachment - text. - - Returns: - `str` - """ - return self._content - - @content.setter - def content(self, content: str) -> None: - self._content = content - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.content_type, self.encoding, self.content, - )) + content: str = attrs.field( + metadata={METADATA_KEY_XML_NAME: '.'} + ) + content_type: str = attrs.field( + default=DEFAULT_CONTENT_TYPE, + metadata={ + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'content-type', + METADATA_KEY_JSON_NAME: 'contentType', + } + ) + encoding: Optional[Encoding] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_ATTR: True} + ) - def __eq__(self, other: object) -> bool: - if isinstance(other, AttachedText): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, AttachedText): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.content_type), self._cmp(self.encoding), self.content) < ( + self._cmp(other.content_type), self._cmp(other.encoding), other.content) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.content_type, self.encoding, self.content)) - def __repr__(self) -> str: - return f'' - -@serializable.serializable_enum class HashAlgorithm(str, Enum): """ This is our internal representation of the hashAlg simple type within the CycloneDX standard. @@ -270,7 +177,6 @@ class HashAlgorithm(str, Enum): .. note:: See the CycloneDX Schema: https://cyclonedx.org/docs/1.7/xml/#type_hashAlg """ - # see `_HashTypeRepositorySerializationHelper.__CASES` for view/case map BLAKE2B_256 = 'BLAKE2b-256' # Only supported in >= 1.2 BLAKE2B_384 = 'BLAKE2b-384' # Only supported in >= 1.2 BLAKE2B_512 = 'BLAKE2b-512' # Only supported in >= 1.2 @@ -287,92 +193,31 @@ class HashAlgorithm(str, Enum): STREEBOG_512 = 'Streebog-512' # Only supported in >= 1.7 -class _HashTypeRepositorySerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - __CASES: dict[type[serializable.ViewType], frozenset[HashAlgorithm]] = dict() - __CASES[SchemaVersion1Dot0] = frozenset({ - HashAlgorithm.MD5, - HashAlgorithm.SHA_1, - HashAlgorithm.SHA_256, - HashAlgorithm.SHA_384, - HashAlgorithm.SHA_512, - HashAlgorithm.SHA3_256, - HashAlgorithm.SHA3_512, - }) - __CASES[SchemaVersion1Dot1] = __CASES[SchemaVersion1Dot0] - __CASES[SchemaVersion1Dot2] = __CASES[SchemaVersion1Dot1] | { - HashAlgorithm.BLAKE2B_256, - HashAlgorithm.BLAKE2B_384, - HashAlgorithm.BLAKE2B_512, - HashAlgorithm.BLAKE3, - HashAlgorithm.SHA3_384, - } - __CASES[SchemaVersion1Dot3] = __CASES[SchemaVersion1Dot2] - __CASES[SchemaVersion1Dot4] = __CASES[SchemaVersion1Dot3] - __CASES[SchemaVersion1Dot5] = __CASES[SchemaVersion1Dot4] - __CASES[SchemaVersion1Dot6] = __CASES[SchemaVersion1Dot5] - __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] | { - HashAlgorithm.STREEBOG_256, - HashAlgorithm.STREEBOG_512, - } - - @classmethod - def __prep(cls, hts: Iterable['HashType'], view: type[serializable.ViewType]) -> Generator['HashType', None, None]: - cases = cls.__CASES.get(view, ()) - for ht in hts: - if ht.alg in cases: - yield ht - else: - warn(f'serialization omitted due to unsupported HashAlgorithm: {ht!r}', - category=UserWarning, stacklevel=0) - - @classmethod - def json_normalize(cls, o: Iterable['HashType'], *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> list[Any]: - assert view is not None - return [ - json_loads( - ht.as_json( # type:ignore[attr-defined] - view_=view) - ) for ht in cls.__prep(o, view) - ] - - @classmethod - def xml_normalize(cls, o: Iterable['HashType'], *, - element_name: str, - view: Optional[type[serializable.ViewType]], - xmlns: Optional[str], - **__: Any) -> XmlElement: - assert view is not None - elem = XmlElement(element_name) - elem.extend( - ht.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='hash', xmlns=xmlns - ) for ht in cls.__prep(o, view) - ) - return elem +# Hash algorithm support by schema version +HASH_ALG_VERSIONS: dict[HashAlgorithm, set[SchemaVersion]] = { + HashAlgorithm.MD5: ALL_VERSIONS, + HashAlgorithm.SHA_1: ALL_VERSIONS, + HashAlgorithm.SHA_256: ALL_VERSIONS, + HashAlgorithm.SHA_384: ALL_VERSIONS, + HashAlgorithm.SHA_512: ALL_VERSIONS, + HashAlgorithm.SHA3_256: ALL_VERSIONS, + HashAlgorithm.SHA3_512: ALL_VERSIONS, + HashAlgorithm.BLAKE2B_256: VERSIONS_1_2_AND_LATER, + HashAlgorithm.BLAKE2B_384: VERSIONS_1_2_AND_LATER, + HashAlgorithm.BLAKE2B_512: VERSIONS_1_2_AND_LATER, + HashAlgorithm.BLAKE3: VERSIONS_1_2_AND_LATER, + HashAlgorithm.SHA3_384: VERSIONS_1_2_AND_LATER, + HashAlgorithm.STREEBOG_256: VERSIONS_1_7_AND_LATER, + HashAlgorithm.STREEBOG_512: VERSIONS_1_7_AND_LATER, +} - @classmethod - def json_denormalize(cls, o: Any, - **__: Any) -> list['HashType']: - return [ - HashType.from_json( # type:ignore[attr-defined] - ht) for ht in o - ] - @classmethod - def xml_denormalize(cls, o: 'XmlElement', *, - default_ns: Optional[str], - **__: Any) -> list['HashType']: - return [ - HashType.from_xml( # type:ignore[attr-defined] - ht, default_ns) for ht in o - ] +def is_hash_alg_supported(alg: HashAlgorithm, version: SchemaVersion) -> bool: + """Check if a hash algorithm is supported in a schema version.""" + return version in HASH_ALG_VERSIONS.get(alg, set()) -@serializable.serializable_class +@attrs.define class HashType: """ This is our internal representation of the hashType complex type within the CycloneDX standard. @@ -380,19 +225,22 @@ class HashType: .. note:: See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_hashType """ + alg: HashAlgorithm = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + content: str = attrs.field( + metadata={METADATA_KEY_XML_NAME: '.'} + ) @staticmethod @deprecated('Deprecated - use cyclonedx.contrib.hash.factories.HashTypeFactory().from_hashlib_alg() instead') def from_hashlib_alg(hashlib_alg: str, content: str) -> 'HashType': """Deprecated — Alias of :func:`cyclonedx.contrib.hash.factories.HashTypeFactory.from_hashlib_alg`. - Attempts to convert a hashlib-algorithm to our internal model classes. - .. deprecated:: next Use ``cyclonedx.contrib.hash.factories.HashTypeFactory().from_hashlib_alg()`` instead. """ from ..contrib.hash.factories import HashTypeFactory - return HashTypeFactory().from_hashlib_alg(hashlib_alg, content) @staticmethod @@ -400,78 +248,24 @@ def from_hashlib_alg(hashlib_alg: str, content: str) -> 'HashType': def from_composite_str(composite_hash: str) -> 'HashType': """Deprecated — Alias of :func:`cyclonedx.contrib.hash.factories.HashTypeFactory.from_composite_str`. - Attempts to convert a string which includes both the Hash Algorithm and Hash Value and represent using our - internal model classes. - .. deprecated:: next Use ``cyclonedx.contrib.hash.factories.HashTypeFactory().from_composite_str()`` instead. """ from ..contrib.hash.factories import HashTypeFactory - return HashTypeFactory().from_composite_str(composite_hash) - def __init__( - self, *, - alg: HashAlgorithm, - content: str, - ) -> None: - self.alg = alg - self.content = content - - @property - @serializable.xml_attribute() - def alg(self) -> HashAlgorithm: - """ - Specifies the algorithm used to create the hash. - - Returns: - `HashAlgorithm` - """ - return self._alg - - @alg.setter - def alg(self, alg: HashAlgorithm) -> None: - self._alg = alg - - @property - @serializable.xml_name('.') - @serializable.xml_string(serializable.XmlStringSerializationType.TOKEN) - def content(self) -> str: - """ - Hash value content. - - Returns: - `str` - """ - return self._content - - @content.setter - def content(self, content: str) -> None: - self._content = content - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.alg, self.content - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, HashType): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - def __lt__(self, other: Any) -> bool: if isinstance(other, HashType): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.alg, self.content) < (other.alg, other.content) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.alg, self.content)) def __repr__(self) -> str: return f'' -@serializable.serializable_enum class ExternalReferenceType(str, Enum): """ Enum object that defines the permissible 'types' for an External Reference according to the CycloneDX schema. @@ -479,7 +273,6 @@ class ExternalReferenceType(str, Enum): .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_externalReferenceType """ - # see `_ExternalReferenceSerializationHelper.__CASES` for view/case map ADVERSARY_MODEL = 'adversary-model' # Only supported in >= 1.5 ADVISORIES = 'advisories' ATTESTATION = 'attestation' # Only supported in >= 1.5 @@ -527,103 +320,76 @@ class ExternalReferenceType(str, Enum): VCS = 'vcs' VULNERABILITY_ASSERTION = 'vulnerability-assertion' # Only supported in >= 1.5 WEBSITE = 'website' - # -- OTHER = 'other' -class _ExternalReferenceSerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - __CASES: dict[type[serializable.ViewType], frozenset[ExternalReferenceType]] = dict() - __CASES[SchemaVersion1Dot1] = frozenset({ - ExternalReferenceType.VCS, - ExternalReferenceType.ISSUE_TRACKER, - ExternalReferenceType.WEBSITE, - ExternalReferenceType.ADVISORIES, - ExternalReferenceType.BOM, - ExternalReferenceType.MAILING_LIST, - ExternalReferenceType.SOCIAL, - ExternalReferenceType.CHAT, - ExternalReferenceType.DOCUMENTATION, - ExternalReferenceType.SUPPORT, - ExternalReferenceType.DISTRIBUTION, - ExternalReferenceType.LICENSE, - ExternalReferenceType.BUILD_META, - ExternalReferenceType.BUILD_SYSTEM, - ExternalReferenceType.OTHER, - }) - __CASES[SchemaVersion1Dot2] = __CASES[SchemaVersion1Dot1] - __CASES[SchemaVersion1Dot3] = __CASES[SchemaVersion1Dot2] - __CASES[SchemaVersion1Dot4] = __CASES[SchemaVersion1Dot3] | { - ExternalReferenceType.RELEASE_NOTES - } - __CASES[SchemaVersion1Dot5] = __CASES[SchemaVersion1Dot4] | { - ExternalReferenceType.DISTRIBUTION_INTAKE, - ExternalReferenceType.SECURITY_CONTACT, - ExternalReferenceType.MODEL_CARD, - ExternalReferenceType.LOG, - ExternalReferenceType.CONFIGURATION, - ExternalReferenceType.EVIDENCE, - ExternalReferenceType.FORMULATION, - ExternalReferenceType.ATTESTATION, - ExternalReferenceType.THREAT_MODEL, - ExternalReferenceType.ADVERSARY_MODEL, - ExternalReferenceType.RISK_ASSESSMENT, - ExternalReferenceType.VULNERABILITY_ASSERTION, - ExternalReferenceType.EXPLOITABILITY_STATEMENT, - ExternalReferenceType.PENTEST_REPORT, - ExternalReferenceType.STATIC_ANALYSIS_REPORT, - ExternalReferenceType.DYNAMIC_ANALYSIS_REPORT, - ExternalReferenceType.RUNTIME_ANALYSIS_REPORT, - ExternalReferenceType.COMPONENT_ANALYSIS_REPORT, - ExternalReferenceType.MATURITY_REPORT, - ExternalReferenceType.CERTIFICATION_REPORT, - ExternalReferenceType.QUALITY_METRICS, - ExternalReferenceType.CODIFIED_INFRASTRUCTURE, - ExternalReferenceType.POAM, - } - __CASES[SchemaVersion1Dot6] = __CASES[SchemaVersion1Dot5] | { - ExternalReferenceType.SOURCE_DISTRIBUTION, - ExternalReferenceType.ELECTRONIC_SIGNATURE, - ExternalReferenceType.DIGITAL_SIGNATURE, - ExternalReferenceType.RFC_9166, - } - __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] | { - ExternalReferenceType.CITATION, - ExternalReferenceType.PATENT, - ExternalReferenceType.PATENT_ASSERTION, - ExternalReferenceType.PATENT_FAMILY, - } - - @classmethod - def __normalize(cls, extref: ExternalReferenceType, view: type[serializable.ViewType]) -> str: - return ( - extref - if extref in cls.__CASES.get(view, ()) - else ExternalReferenceType.OTHER - ).value - - @classmethod - def json_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> str: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def xml_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> str: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def deserialize(cls, o: Any) -> ExternalReferenceType: - return ExternalReferenceType(o) +# External reference type support by schema version + +EXTREF_TYPE_VERSIONS: dict[ExternalReferenceType, set[SchemaVersion]] = { + ExternalReferenceType.VCS: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.ISSUE_TRACKER: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.WEBSITE: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.ADVISORIES: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.BOM: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.MAILING_LIST: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.SOCIAL: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.CHAT: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.DOCUMENTATION: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.SUPPORT: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.DISTRIBUTION: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.LICENSE: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.BUILD_META: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.BUILD_SYSTEM: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.OTHER: VERSIONS_1_1_AND_LATER, + ExternalReferenceType.RELEASE_NOTES: VERSIONS_1_4_AND_LATER, + ExternalReferenceType.DISTRIBUTION_INTAKE: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.SECURITY_CONTACT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.MODEL_CARD: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.LOG: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.CONFIGURATION: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.EVIDENCE: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.FORMULATION: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.ATTESTATION: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.THREAT_MODEL: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.ADVERSARY_MODEL: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.RISK_ASSESSMENT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.VULNERABILITY_ASSERTION: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.EXPLOITABILITY_STATEMENT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.PENTEST_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.STATIC_ANALYSIS_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.DYNAMIC_ANALYSIS_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.RUNTIME_ANALYSIS_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.COMPONENT_ANALYSIS_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.MATURITY_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.CERTIFICATION_REPORT: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.QUALITY_METRICS: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.CODIFIED_INFRASTRUCTURE: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.POAM: VERSIONS_1_5_AND_LATER, + ExternalReferenceType.SOURCE_DISTRIBUTION: VERSIONS_1_6_AND_LATER, + ExternalReferenceType.ELECTRONIC_SIGNATURE: VERSIONS_1_6_AND_LATER, + ExternalReferenceType.DIGITAL_SIGNATURE: VERSIONS_1_6_AND_LATER, + ExternalReferenceType.RFC_9166: VERSIONS_1_6_AND_LATER, + ExternalReferenceType.CITATION: VERSIONS_1_7_AND_LATER, + ExternalReferenceType.PATENT: VERSIONS_1_7_AND_LATER, + ExternalReferenceType.PATENT_ASSERTION: VERSIONS_1_7_AND_LATER, + ExternalReferenceType.PATENT_FAMILY: VERSIONS_1_7_AND_LATER, +} + + +def get_extref_type_for_version( + extref_type: ExternalReferenceType, + version: SchemaVersion +) -> ExternalReferenceType: + """Get the appropriate external reference type for a schema version. + + Returns OTHER if the type is not supported in the given version. + """ + if version in EXTREF_TYPE_VERSIONS.get(extref_type, set()): + return extref_type + return ExternalReferenceType.OTHER -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class XsUri(serializable.helpers.BaseHelper): +class XsUri: """ Helper class that allows us to perform validation on data strings that are defined as xs:anyURI in CycloneDX schema. @@ -661,11 +427,6 @@ def _spec_migrate(cls, o: str) -> str: - JSON::iri-reference spec. BEST EFFORT IMPLEMENTATION - - @see http://www.w3.org/TR/xmlschema-2/#anyURI - @see http://www.datypic.com/sc/xsd/t-xsd_anyURI.html - @see https://datatracker.ietf.org/doc/html/rfc2396 - @see https://datatracker.ietf.org/doc/html/rfc3987 """ return reduce(cls.__spec_replace, cls.__SPEC_REPLACEMENTS, o) @@ -696,8 +457,6 @@ def __str__(self) -> str: return self._uri @property - @serializable.json_name('.') - @serializable.xml_name('.') def uri(self) -> str: return self._uri @@ -726,29 +485,16 @@ def make_bom_link( ) -> 'XsUri': """ Generate a BOM-Link URI. - - Args: - serial_number: The unique serial number of the BOM. - version: The version of the BOM. The default version is 1. - bom_ref: The unique identifier of the component, service, or vulnerability within the BOM. - - Returns: - XsUri: Instance of XsUri with the generated BOM-Link URI. """ bom_ref_part = f'#{url_quote(str(bom_ref))}' if bom_ref else '' return cls(f'{_BOM_LINK_PREFIX}{serial_number}/{version}{bom_ref_part}') def is_bom_link(self) -> bool: - """ - Check if the URI is a BOM-Link. - - Returns: - `bool` - """ + """Check if the URI is a BOM-Link.""" return self._uri.startswith(_BOM_LINK_PREFIX) -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class ExternalReference: """ This is our internal representation of an ExternalReference complex type that can be used in multiple places within @@ -757,130 +503,42 @@ class ExternalReference: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_externalReference """ + type: ExternalReferenceType = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + url: XsUri = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + comment: Optional[str] = attrs.field(default=None) + hashes: 'SortedSet[HashType]' = attrs.field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={METADATA_KEY_VERSIONS: VERSIONS_1_3_AND_LATER} + ) + properties: 'SortedSet[Property]' = attrs.field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={METADATA_KEY_VERSIONS: VERSIONS_1_7_AND_LATER} + ) - def __init__( - self, *, - type: ExternalReferenceType, - url: XsUri, - comment: Optional[str] = None, - hashes: Optional[Iterable[HashType]] = None, - properties: Optional[Iterable['Property']] = None, - ) -> None: - self.url = url - self.comment = comment - self.type = type - self.hashes = hashes or [] - self.properties = properties or [] - - @property - @serializable.xml_sequence(1) - def url(self) -> XsUri: - """ - The URL to the external reference. - - Returns: - `XsUri` - """ - return self._url - - @url.setter - def url(self, url: XsUri) -> None: - self._url = url - - @property - def comment(self) -> Optional[str]: - """ - An optional comment describing the external reference. - - Returns: - `str` if set else `None` - """ - return self._comment - - @comment.setter - def comment(self, comment: Optional[str]) -> None: - self._comment = comment - - @property - @serializable.type_mapping(_ExternalReferenceSerializationHelper) - @serializable.xml_attribute() - def type(self) -> ExternalReferenceType: - """ - Specifies the type of external reference. - - There are built-in types to describe common references. If a type does not exist for the reference being - referred to, use the "other" type. - - Returns: - `ExternalReferenceType` - """ - return self._type - - @type.setter - def type(self, type: ExternalReferenceType) -> None: - self._type = type - - @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(_HashTypeRepositorySerializationHelper) - def hashes(self) -> 'SortedSet[HashType]': - """ - The hashes of the external reference (if applicable). - - Returns: - Set of `HashType` - """ - return self._hashes - - @hashes.setter - def hashes(self, hashes: Iterable[HashType]) -> None: - self._hashes = SortedSet(hashes) - - @property - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Return: - Set of `Property` - """ - return self._properties - - @properties.setter - def properties(self, properties: Iterable['Property']) -> None: - self._properties = SortedSet(properties) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self._type, self._url, self._comment, - _ComparableTuple(self._hashes), _ComparableTuple(self.properties), - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, ExternalReference): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, ExternalReference): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.type, self.url, self._cmp(self.comment)) < (other.type, other.url, self._cmp(other.comment)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.type, self.url, self.comment, tuple(self.hashes), tuple(self.properties))) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Property: """ This is our internal representation of `propertyType` complex type that can be used in multiple places within @@ -891,71 +549,27 @@ class Property: Specifies an individual property with a name and value. """ - - def __init__( - self, *, - name: str, - value: Optional[str] = None, - ) -> None: - self.name = name - self.value = value - - @property - @serializable.xml_attribute() - def name(self) -> str: - """ - The name of the property. - - Duplicate names are allowed, each potentially having a different value. - - Returns: - `str` - """ - return self._name - - @name.setter - def name(self, name: str) -> None: - self._name = name - - @property - @serializable.xml_name('.') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def value(self) -> Optional[str]: - """ - Value of this Property. - - Returns: - `str` - """ - return self._value - - @value.setter - def value(self, value: Optional[str]) -> None: - self._value = value - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, self.value - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Property): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + name: str = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + value: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_NAME: '.'} + ) def __lt__(self, other: Any) -> bool: if isinstance(other, Property): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.name, self.value) < (other.name, other.value) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.name, self.value)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class NoteText: """ This is our internal representation of the Note.text complex type that can be used in multiple places within @@ -965,89 +579,43 @@ class NoteText: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_releaseNotesType """ - DEFAULT_CONTENT_TYPE: str = 'text/plain' - - def __init__( - self, *, - content: str, - content_type: Optional[str] = None, - encoding: Optional[Encoding] = None, - ) -> None: - self.content = content - self.content_type = content_type or NoteText.DEFAULT_CONTENT_TYPE - self.encoding = encoding - - @property - @serializable.xml_name('.') - def content(self) -> str: - """ - Get the text content of this Note. - - Returns: - `str` note content - """ - return self._content - - @content.setter - def content(self, content: str) -> None: - self._content = content - - @property - @serializable.xml_attribute() - @serializable.xml_name('content-type') - def content_type(self) -> Optional[str]: - """ - Get the content-type of this Note. - - Defaults to 'text/plain' if one was not explicitly specified. - - Returns: - `str` content-type - """ - return self._content_type - - @content_type.setter - def content_type(self, content_type: str) -> None: - self._content_type = content_type - - @property - @serializable.xml_attribute() - def encoding(self) -> Optional[Encoding]: - """ - Get the encoding method used for the note's content. - - Returns: - `Encoding` if set else `None` - """ - return self._encoding + DEFAULT_CONTENT_TYPE: ClassVar[str] = 'text/plain' - @encoding.setter - def encoding(self, encoding: Optional[Encoding]) -> None: - self._encoding = encoding - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.content, self.content_type, self.encoding - )) + content: str = attrs.field( + metadata={METADATA_KEY_XML_NAME: '.'} + ) + content_type: Optional[str] = attrs.field( + default=DEFAULT_CONTENT_TYPE, + metadata={ + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'content-type', + METADATA_KEY_JSON_NAME: 'contentType', + } + ) + encoding: Optional[Encoding] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_ATTR: True} + ) - def __eq__(self, other: object) -> bool: - if isinstance(other, NoteText): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, NoteText): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.content, self.content_type, self._cmp(self.encoding)) < ( + other.content, other.content_type, self._cmp(other.encoding)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.content, self.content_type, self.encoding)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Note: """ This is our internal representation of the Note complex type that can be used in multiple places within @@ -1055,84 +623,40 @@ class Note: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_releaseNotesType - - @todo: Replace ``NoteText`` with ``AttachedText``? """ _LOCALE_TYPE_REGEX = re.compile(r'^[a-z]{2}(?:\-[A-Z]{2})?$') - def __init__( - self, *, - text: NoteText, - locale: Optional[str] = None, - ) -> None: - self.text = text - self.locale = locale + text: NoteText + locale: Optional[str] = attrs.field(default=None, metadata={METADATA_KEY_XML_SEQUENCE: 1}) - @property - def text(self) -> NoteText: - """ - Specifies the full content of the release note. - - Returns: - `NoteText` - """ - return self._text - - @text.setter - def text(self, text: NoteText) -> None: - self._text = text - - @property - @serializable.xml_sequence(1) - def locale(self) -> Optional[str]: - """ - Get the ISO locale of this Note. - - The ISO-639 (or higher) language code and optional ISO-3166 (or higher) country code. - - Examples include: "en", "en-US", "fr" and "fr-CA". + @locale.validator + def _validate_locale(self, attribute: attrs.Attribute, value: Optional[str]) -> None: + if value is not None and not re.search(Note._LOCALE_TYPE_REGEX, value): + raise InvalidLocaleTypeException( + f'Supplied locale {value!r} is not a valid locale.' + ' Locale string should be formatted as the ISO-639 (or higher) language code and optional' + " ISO-3166 (or higher) country code. Examples include: 'en', 'en-US'." + ) - Returns: - `str` locale if set else `None` - """ - return self._locale - - @locale.setter - def locale(self, locale: Optional[str]) -> None: - self._locale = locale - if isinstance(locale, str): - if not re.search(Note._LOCALE_TYPE_REGEX, locale): - self._locale = None - raise InvalidLocaleTypeException( - f'Supplied locale {locale!r} is not a valid locale.' - ' Locale string should be formatted as the ISO-639 (or higher) language code and optional' - " ISO-3166 (or higher) country code. according to ISO-639 format. Examples include: 'en', 'en-US'." - ) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.locale, self.text - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Note): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Note): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.locale), self.text) < (self._cmp(other.locale), other.text) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.locale, self.text)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class IdentifiableAction: """ This is our internal representation of the `identifiableActionType` complex type. @@ -1140,85 +664,29 @@ class IdentifiableAction: .. note:: See the CycloneDX specification: https://cyclonedx.org/docs/1.7/xml/#type_identifiableActionType """ + timestamp: Optional[datetime] = attrs.field(default=None) + name: Optional[str] = attrs.field(default=None) + email: Optional[str] = attrs.field(default=None) - def __init__( - self, *, - timestamp: Optional[datetime] = None, - name: Optional[str] = None, - email: Optional[str] = None, - ) -> None: - self.timestamp = timestamp - self.name = name - self.email = email - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - def timestamp(self) -> Optional[datetime]: - """ - The timestamp in which the action occurred. - - Returns: - `datetime` if set else `None` - """ - return self._timestamp - - @timestamp.setter - def timestamp(self, timestamp: Optional[datetime]) -> None: - self._timestamp = timestamp - - @property - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - The name of the individual who performed the action. - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def email(self) -> Optional[str]: - """ - The email address of the individual who performed the action. - - Returns: - `str` if set else `None` - """ - return self._email - - @email.setter - def email(self, email: Optional[str]) -> None: - self._email = email - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.timestamp, self.name, self.email - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, IdentifiableAction): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, IdentifiableAction): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.timestamp), self._cmp(self.name), self._cmp(self.email)) < ( + self._cmp(other.timestamp), self._cmp(other.name), self._cmp(other.email)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.timestamp, self.name, self.email)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Copyright: """ This is our internal representation of the `copyrightsType` complex type. @@ -1226,40 +694,17 @@ class Copyright: .. note:: See the CycloneDX specification: https://cyclonedx.org/docs/1.7/xml/#type_copyrightsType """ - - def __init__( - self, *, - text: str, - ) -> None: - self.text = text - - @property - @serializable.xml_name('.') - def text(self) -> str: - """ - Copyright statement. - - Returns: - `str` if set else `None` - """ - return self._text - - @text.setter - def text(self, text: str) -> None: - self._text = text - - def __eq__(self, other: object) -> bool: - if isinstance(other, Copyright): - return self._text == other._text - return False + text: str = attrs.field( + metadata={METADATA_KEY_XML_NAME: '.'} + ) def __lt__(self, other: Any) -> bool: if isinstance(other, Copyright): - return self._text < other._text + return self.text < other.text return NotImplemented def __hash__(self) -> int: - return hash(self._text) + return hash(self.text) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/bom.py b/cyclonedx/model/bom.py index 08e838773..859c155fd 100644 --- a/cyclonedx/model/bom.py +++ b/cyclonedx/model/bom.py @@ -20,44 +20,61 @@ from datetime import datetime from enum import Enum from itertools import chain -from typing import TYPE_CHECKING, Optional, Union +from typing import TYPE_CHECKING, Any, Optional, Union from uuid import UUID, uuid4 from warnings import warn -import py_serializable as serializable +from attrs import Factory, define, field from sortedcontainers import SortedSet from .._internal.compare import ComparableTuple as _ComparableTuple from .._internal.time import get_now_utc as _get_now_utc from ..exception.model import LicenseExpressionAlongWithOthersException, UnknownComponentDependencyException -from ..schema.schema import ( - SchemaVersion1Dot0, - SchemaVersion1Dot1, - SchemaVersion1Dot2, - SchemaVersion1Dot3, - SchemaVersion1Dot4, - SchemaVersion1Dot5, - SchemaVersion1Dot6, - SchemaVersion1Dot7, -) -from ..serialization import UrnUuidHelper +from ..schema import SchemaVersion from . import _BOM_LINK_PREFIX, ExternalReference, Property from .bom_ref import BomRef from .component import Component from .contact import OrganizationalContact, OrganizationalEntity from .definition import Definitions from .dependency import Dependable, Dependency -from .license import License, LicenseExpression, LicenseRepository, _LicenseRepositorySerializationHelper -from .lifecycle import Lifecycle, LifecycleRepository, _LifecycleRepositoryHelper +from .license import License, LicenseExpression, LicenseRepository +from .lifecycle import Lifecycle, LifecycleRepository from .service import Service -from .tool import Tool, ToolRepository, _ToolRepositoryHelper +from .tool import Tool, ToolRepository from .vulnerability import Vulnerability if TYPE_CHECKING: # pragma: no cover from packageurl import PackageURL -@serializable.serializable_enum +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) + + +def _license_repository_converter(value: Any) -> 'LicenseRepository': + if value is None: + return LicenseRepository() + if isinstance(value, LicenseRepository): + return value + # Convert generators, lists, etc. to LicenseRepository + return LicenseRepository(value) + + +def _lifecycle_repository_converter(value: Any) -> 'LifecycleRepository': + if value is None: + return LifecycleRepository() + if isinstance(value, LifecycleRepository): + return value + # Convert generators, lists, etc. to LifecycleRepository + return LifecycleRepository(value) + + class TlpClassification(str, Enum): """ Enum object that defines the Traffic Light Protocol (TLP) classification that controls the sharing and distribution @@ -77,7 +94,7 @@ class TlpClassification(str, Enum): RED = 'RED' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class DistributionConstraints: """ Our internal representation of the `distributionConstraints` complex type. @@ -90,49 +107,26 @@ class DistributionConstraints: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_metadata """ - def __init__( - self, *, - tlp: Optional[TlpClassification] = None, - ) -> None: - self.tlp = tlp or TlpClassification.CLEAR - - @property - @serializable.xml_sequence(0) - def tlp(self) -> TlpClassification: - """ - The Traffic Light Protocol (TLP) classification that controls the sharing and distribution of the data that the - BOM describes. - - Returns: - `TlpClassification` enum value - """ - return self._tlp - - @tlp.setter - def tlp(self, tlp: TlpClassification) -> None: - self._tlp = tlp + tlp: TlpClassification = field( + default=TlpClassification.CLEAR, + metadata={'json_name': 'tlp', 'xml_name': 'tlp', 'xml_sequence': 0, + 'min_schema_version': SchemaVersion.V1_7} + ) + """ + The Traffic Light Protocol (TLP) classification that controls the sharing and distribution of the data that the + BOM describes. + """ - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(self.tlp) + def __hash__(self) -> int: + return hash(self.tlp) - def __eq__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, DistributionConstraints): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __lt__(self, other: object) -> bool: - if isinstance(other, DistributionConstraints): - return self.__comparable_tuple() < other.__comparable_tuple() + return self.tlp < other.tlp return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class BomMetaData: """ This is our internal representation of the metadata complex type within the CycloneDX standard. @@ -141,63 +135,86 @@ class BomMetaData: See the CycloneDX Schema for Bom metadata: https://cyclonedx.org/docs/1.7/xml/#type_metadata """ - def __init__( - self, *, - tools: Optional[Union[Iterable[Tool], ToolRepository]] = None, - authors: Optional[Iterable[OrganizationalContact]] = None, - component: Optional[Component] = None, - supplier: Optional[OrganizationalEntity] = None, - licenses: Optional[Iterable[License]] = None, - properties: Optional[Iterable[Property]] = None, - timestamp: Optional[datetime] = None, - manufacturer: Optional[OrganizationalEntity] = None, - lifecycles: Optional[Iterable[Lifecycle]] = None, - distribution_constraints: Optional[DistributionConstraints] = None, - # Deprecated as of v1.6 - manufacture: Optional[OrganizationalEntity] = None, - ) -> None: - self.timestamp = timestamp or _get_now_utc() - self.tools = tools or [] - self.authors = authors or [] - self.component = component - self.supplier = supplier - self.licenses = licenses or [] - self.properties = properties or [] - self.manufacturer = manufacturer - self.lifecycles = lifecycles or [] - self.distribution_constraints = distribution_constraints - # deprecated properties below - self.manufacture = manufacture + timestamp: datetime = field( + factory=_get_now_utc, + metadata={'json_name': 'timestamp', 'xml_name': 'timestamp', 'xml_sequence': 1} + ) + """The date and time (in UTC) when this BomMetaData was created.""" + + _lifecycles: LifecycleRepository = field( + factory=LifecycleRepository, + converter=_lifecycle_repository_converter, + metadata={'json_name': 'lifecycles', 'xml_name': 'lifecycles', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_5} + ) + """An optional list of BOM lifecycle stages.""" + + _tools: ToolRepository = field( + factory=ToolRepository, + converter=lambda v: v if isinstance(v, ToolRepository) else ToolRepository(tools=v) if v else ToolRepository(), + metadata={'json_name': 'tools', 'xml_name': 'tools', 'xml_sequence': 3} + ) + """Tools used to create this BOM.""" + + _authors: 'SortedSet[OrganizationalContact]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'authors', 'xml_name': 'authors', 'xml_item_name': 'author', 'xml_sequence': 4} + ) + """The person(s) who created the BOM.""" + + component: Optional[Component] = field( + default=None, + metadata={'json_name': 'component', 'xml_name': 'component', 'xml_sequence': 5} + ) + """The (optional) component that the BOM describes.""" + + _manufacture: Optional[OrganizationalEntity] = field( + default=None, + metadata={'json_name': 'manufacture', 'xml_name': 'manufacture', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_2, 'max_schema_version': SchemaVersion.V1_7} + ) + """The organization that manufactured the component that the BOM describes.""" + + manufacturer: Optional[OrganizationalEntity] = field( + default=None, + metadata={'json_name': 'manufacturer', 'xml_name': 'manufacturer', 'xml_sequence': 7, + 'min_schema_version': SchemaVersion.V1_6} + ) + """The organization that created the BOM.""" + + supplier: Optional[OrganizationalEntity] = field( + default=None, + metadata={'json_name': 'supplier', 'xml_name': 'supplier', 'xml_sequence': 8} + ) + """The organization that supplied the component that the BOM describes.""" + + _licenses: LicenseRepository = field( + factory=LicenseRepository, + converter=_license_repository_converter, + metadata={'json_name': 'licenses', 'xml_name': 'licenses', 'xml_sequence': 9, + 'min_schema_version': SchemaVersion.V1_3} + ) + """A optional list of statements about how this BOM is licensed.""" + + _properties: 'SortedSet[Property]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'properties', 'xml_name': 'properties', 'xml_item_name': 'property', 'xml_sequence': 10, + 'min_schema_version': SchemaVersion.V1_3} + ) + """Provides the ability to document properties in a key/value store.""" + + distribution_constraints: Optional[DistributionConstraints] = field( + default=None, + metadata={'json_name': 'distributionConstraints', 'xml_name': 'distributionConstraints', 'xml_sequence': 11, + 'min_schema_version': SchemaVersion.V1_7} + ) + """Conditions and constraints governing the sharing and distribution of the data.""" @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(1) - def timestamp(self) -> datetime: - """ - The date and time (in UTC) when this BomMetaData was created. - - Returns: - `datetime` instance in UTC timezone - """ - return self._timestamp - - @timestamp.setter - def timestamp(self, timestamp: datetime) -> None: - self._timestamp = timestamp - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(_LifecycleRepositoryHelper) - @serializable.xml_sequence(2) def lifecycles(self) -> LifecycleRepository: - """ - An optional list of BOM lifecycle stages. - - Returns: - Set of `Lifecycle` - """ + """An optional list of BOM lifecycle stages.""" return self._lifecycles @lifecycles.setter @@ -205,37 +222,17 @@ def lifecycles(self, lifecycles: Iterable[Lifecycle]) -> None: self._lifecycles = LifecycleRepository(lifecycles) @property - @serializable.type_mapping(_ToolRepositoryHelper) - @serializable.xml_sequence(3) def tools(self) -> ToolRepository: - """ - Tools used to create this BOM. - - Returns: - :class:`ToolRepository` object. - """ + """Tools used to create this BOM.""" return self._tools @tools.setter def tools(self, tools: Union[Iterable[Tool], ToolRepository]) -> None: - self._tools = tools \ - if isinstance(tools, ToolRepository) \ - else ToolRepository(tools=tools) + self._tools = tools if isinstance(tools, ToolRepository) else ToolRepository(tools=tools) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'author') - @serializable.xml_sequence(4) def authors(self) -> 'SortedSet[OrganizationalContact]': - """ - The person(s) who created the BOM. - - Authors are common in BOMs created through manual processes. - - BOMs created through automated means may not have authors. - - Returns: - Set of `OrganizationalContact` - """ + """The person(s) who created the BOM.""" return self._authors @authors.setter @@ -243,53 +240,12 @@ def authors(self, authors: Iterable[OrganizationalContact]) -> None: self._authors = SortedSet(authors) @property - @serializable.xml_sequence(5) - def component(self) -> Optional[Component]: - """ - The (optional) component that the BOM describes. - - Returns: - `cyclonedx.model.component.Component` instance for this Bom Metadata. - """ - return self._component - - @component.setter - def component(self, component: Optional[Component]) -> None: - """ - The (optional) component that the BOM describes. - - Args: - component - `cyclonedx.model.component.Component` instance to add to this Bom Metadata. - - Returns: - None - """ - self._component = component - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(6) def manufacture(self) -> Optional[OrganizationalEntity]: - """ - The organization that manufactured the component that the BOM describes. - - Returns: - `OrganizationalEntity` if set else `None` - """ + """The organization that manufactured the component that the BOM describes (deprecated).""" return self._manufacture @manufacture.setter def manufacture(self, manufacture: Optional[OrganizationalEntity]) -> None: - """ - @todo Based on https://github.com/CycloneDX/specification/issues/346, - we should set this data on `.component.manufacturer`. - """ if manufacture is not None: warn( '`bom.metadata.manufacture` is deprecated from CycloneDX v1.6 onwards. ' @@ -298,56 +254,8 @@ def manufacture(self, manufacture: Optional[OrganizationalEntity]) -> None: self._manufacture = manufacture @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(7) - def manufacturer(self) -> Optional[OrganizationalEntity]: - """ - The organization that created the BOM. - Manufacturer is common in BOMs created through automated processes. BOMs created through manual means may have - `@.authors` instead. - - Returns: - `OrganizationalEntity` if set else `None` - """ - return self._manufacturer - - @manufacturer.setter - def manufacturer(self, manufacturer: Optional[OrganizationalEntity]) -> None: - self._manufacturer = manufacturer - - @property - @serializable.xml_sequence(8) - def supplier(self) -> Optional[OrganizationalEntity]: - """ - The organization that supplied the component that the BOM describes. - - The supplier may often be the manufacturer, but may also be a distributor or repackager. - - Returns: - `OrganizationalEntity` if set else `None` - """ - return self._supplier - - @supplier.setter - def supplier(self, supplier: Optional[OrganizationalEntity]) -> None: - self._supplier = supplier - - @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(_LicenseRepositorySerializationHelper) - @serializable.xml_sequence(9) def licenses(self) -> LicenseRepository: - """ - A optional list of statements about how this BOM is licensed. - - Returns: - Set of `LicenseChoice` - """ + """A optional list of statements about how this BOM is licensed.""" return self._licenses @licenses.setter @@ -355,47 +263,14 @@ def licenses(self, licenses: Iterable[License]) -> None: self._licenses = LicenseRepository(licenses) @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(10) def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Property names of interest to the general public are encouraged to be registered in the CycloneDX Property - Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. Formal registration is OPTIONAL. - - Return: - Set of `Property` - """ + """Provides the ability to document properties in a key/value store.""" return self._properties @properties.setter def properties(self, properties: Iterable[Property]) -> None: self._properties = SortedSet(properties) - @property - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(11) - def distribution_constraints(self) -> Optional[DistributionConstraints]: - """ - Conditions and constraints governing the sharing and distribution of the data or components described by this - BOM. - - Returns: - `DistributionConstraints` or `None` - """ - return self._distribution_constraints - - @distribution_constraints.setter - def distribution_constraints(self, distribution_constraints: Optional[DistributionConstraints]) -> None: - self._distribution_constraints = distribution_constraints - def __comparable_tuple(self) -> _ComparableTuple: return _ComparableTuple(( _ComparableTuple(self.authors), self.component, _ComparableTuple(self.licenses), self.manufacture, @@ -416,16 +291,8 @@ def __lt__(self, other: object) -> bool: def __hash__(self) -> int: return hash(self.__comparable_tuple()) - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class( - ignore_during_deserialization={ - '$schema', 'bom_format', 'spec_version', # JSON-implementation's format hints - }, - ignore_unknown_during_deserialization=True -) +@define class Bom: """ This is our internal representation of a bill-of-materials (BOM). @@ -434,105 +301,84 @@ class Bom: `cyclonedx.output.BaseOutput` to produce a CycloneDX document according to a specific schema version and format. """ - def __init__( - self, *, - components: Optional[Iterable[Component]] = None, - services: Optional[Iterable[Service]] = None, - external_references: Optional[Iterable[ExternalReference]] = None, - serial_number: Optional[UUID] = None, - version: int = 1, - metadata: Optional[BomMetaData] = None, - dependencies: Optional[Iterable[Dependency]] = None, - vulnerabilities: Optional[Iterable[Vulnerability]] = None, - properties: Optional[Iterable[Property]] = None, - definitions: Optional[Definitions] = None, - ) -> None: - """ - Create a new Bom that you can manually/programmatically add data to later. - - Returns: - New, empty `cyclonedx.model.bom.Bom` instance. - """ - self.serial_number = serial_number or uuid4() - self.version = version - self.metadata = metadata or BomMetaData() - self.components = components or [] - self.services = services or [] - self.external_references = external_references or [] - self.vulnerabilities = vulnerabilities or [] - self.dependencies = dependencies or [] - self.properties = properties or [] - self.definitions = definitions or Definitions() + serial_number: UUID = field( + factory=uuid4, + metadata={'json_name': 'serialNumber', 'xml_name': 'serialNumber', 'xml_attribute': True, + 'min_schema_version': SchemaVersion.V1_1} + ) + """Unique UUID for this BOM.""" + + version: int = field( + default=1, + metadata={'json_name': 'version', 'xml_name': 'version', 'xml_attribute': True} + ) + """The version of this BOM.""" + + metadata: BomMetaData = field( + factory=BomMetaData, + metadata={'json_name': 'metadata', 'xml_name': 'metadata', 'xml_sequence': 10, + 'min_schema_version': SchemaVersion.V1_2} + ) + """Metadata for this BOM.""" + + _components: 'SortedSet[Component]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'components', 'xml_name': 'components', 'xml_item_name': 'component', + 'xml_sequence': 20} + ) + """Components in this BOM.""" + + _services: 'SortedSet[Service]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'services', 'xml_name': 'services', 'xml_item_name': 'service', + 'xml_sequence': 30, 'min_schema_version': SchemaVersion.V1_2} + ) + """Services in this BOM.""" + + _external_references: 'SortedSet[ExternalReference]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'externalReferences', 'xml_name': 'externalReferences', 'xml_item_name': 'reference', + 'xml_sequence': 40, 'min_schema_version': SchemaVersion.V1_1} + ) + """External references related to the BOM.""" + + _dependencies: 'SortedSet[Dependency]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'dependencies', 'xml_name': 'dependencies', 'xml_item_name': 'dependency', + 'xml_sequence': 50, 'min_schema_version': SchemaVersion.V1_2} + ) + """Dependencies in this BOM.""" + + _properties: 'SortedSet[Property]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'properties', 'xml_name': 'properties', 'xml_item_name': 'property', + 'xml_sequence': 70, 'min_schema_version': SchemaVersion.V1_5} + ) + """Properties for this BOM.""" + + _vulnerabilities: 'SortedSet[Vulnerability]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'vulnerabilities', 'xml_name': 'vulnerabilities', 'xml_item_name': 'vulnerability', + 'xml_sequence': 80, 'min_schema_version': SchemaVersion.V1_4} + ) + """Vulnerabilities in this BOM.""" + + definitions: Optional[Definitions] = field( + default=None, + metadata={'json_name': 'definitions', 'xml_name': 'definitions', 'xml_sequence': 110, + 'min_schema_version': SchemaVersion.V1_6} + ) + """Definitions for this BOM.""" @property - @serializable.type_mapping(UrnUuidHelper) - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_attribute() - def serial_number(self) -> UUID: - """ - Unique UUID for this BOM - - Returns: - `UUID` instance - `UUID` instance - """ - return self._serial_number - - @serial_number.setter - def serial_number(self, serial_number: UUID) -> None: - self._serial_number = serial_number - - @property - @serializable.xml_attribute() - def version(self) -> int: - return self._version - - @version.setter - def version(self, version: int) -> None: - self._version = version - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(10) - def metadata(self) -> BomMetaData: - """ - Get our internal metadata object for this Bom. - - Returns: - Metadata object instance for this Bom. - - .. note:: - See the CycloneDX Schema for Bom metadata: https://cyclonedx.org/docs/1.7/xml/#type_metadata - """ - return self._metadata - - @metadata.setter - def metadata(self, metadata: BomMetaData) -> None: - self._metadata = metadata - - @property - @serializable.include_none(SchemaVersion1Dot0) - @serializable.include_none(SchemaVersion1Dot1) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component') - @serializable.xml_sequence(20) def components(self) -> 'SortedSet[Component]': - """ - Get all the Components currently in this Bom. - - Returns: - Set of `Component` in this Bom - """ + """Get all the Components currently in this Bom.""" return self._components @components.setter @@ -540,21 +386,8 @@ def components(self, components: Iterable[Component]) -> None: self._components = SortedSet(components) @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'service') - @serializable.xml_sequence(30) def services(self) -> 'SortedSet[Service]': - """ - Get all the Services currently in this Bom. - - Returns: - Set of `Service` in this BOM - """ + """Get all the Services currently in this Bom.""" return self._services @services.setter @@ -562,22 +395,8 @@ def services(self, services: Iterable[Service]) -> None: self._services = SortedSet(services) @property - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(40) def external_references(self) -> 'SortedSet[ExternalReference]': - """ - Provides the ability to document external references related to the BOM or to the project the BOM describes. - - Returns: - Set of `ExternalReference` - """ + """Provides the ability to document external references related to the BOM.""" return self._external_references @external_references.setter @@ -585,52 +404,17 @@ def external_references(self, external_references: Iterable[ExternalReference]) self._external_references = SortedSet(external_references) @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'dependency') - @serializable.xml_sequence(50) def dependencies(self) -> 'SortedSet[Dependency]': + """Dependencies in this BOM.""" return self._dependencies @dependencies.setter def dependencies(self, dependencies: Iterable[Dependency]) -> None: self._dependencies = SortedSet(dependencies) - # @property - # ... - # @serializable.view(SchemaVersion1Dot3) - # @serializable.view(SchemaVersion1Dot4) - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(6) - # def compositions(self) -> ...: - # ... # TODO Since CDX 1.3 - # - # @compositions.setter - # def compositions(self, ...) -> None: - # ... # TODO Since CDX 1.3 - @property - # @serializable.view(SchemaVersion1Dot3) @todo: Update py-serializable to support view by OutputFormat filtering - # @serializable.view(SchemaVersion1Dot4) @todo: Update py-serializable to support view by OutputFormat filtering - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(70) def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a name/value store. This provides flexibility to include data - not officially supported in the standard without having to use additional namespaces or create extensions. - Property names of interest to the general public are encouraged to be registered in the CycloneDX Property - Taxonomy - https://github.com/CycloneDX/cyclonedx-property-taxonomy. Formal registration is OPTIONAL. - - Return: - Set of `Property` - """ + """Properties for this BOM.""" return self._properties @properties.setter @@ -638,64 +422,14 @@ def properties(self, properties: Iterable[Property]) -> None: self._properties = SortedSet(properties) @property - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'vulnerability') - @serializable.xml_sequence(80) def vulnerabilities(self) -> 'SortedSet[Vulnerability]': - """ - Get all the Vulnerabilities in this BOM. - - Returns: - Set of `Vulnerability` - """ + """Get all the Vulnerabilities in this BOM.""" return self._vulnerabilities @vulnerabilities.setter def vulnerabilities(self, vulnerabilities: Iterable[Vulnerability]) -> None: self._vulnerabilities = SortedSet(vulnerabilities) - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(9) - # def annotations(self) -> ...: - # ... # TODO Since CDX 1.5 - # - # @annotations.setter - # def annotations(self, ...) -> None: - # ... # TODO Since CDX 1.5 - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @formulation.xml_sequence(10) - # def formulation(self) -> ...: - # ... # TODO Since CDX 1.5 - # - # @formulation.setter - # def formulation(self, ...) -> None: - # ... # TODO Since CDX 1.5 - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(110) - def definitions(self) -> Optional[Definitions]: - """ - The repository for definitions - - Returns: - `Definitions` - """ - return self._definitions if len(self._definitions.standards) > 0 else None - - @definitions.setter - def definitions(self, definitions: Definitions) -> None: - self._definitions = definitions - def get_component_by_purl(self, purl: Optional['PackageURL']) -> Optional[Component]: """ Get a Component already in the Bom by its PURL @@ -785,12 +519,12 @@ def register_dependency(self, target: Dependable, depends_on: Optional[Iterable[ 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)) + _d.dependencies.update([Dependency(ref=_d.bom_ref) for _d in depends_on]) 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 [] + dependencies=[Dependency(ref=_dep.bom_ref) for _dep in depends_on] if depends_on else [] )) if depends_on: @@ -867,22 +601,354 @@ def validate(self) -> bool: return True - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.serial_number, self.version, self.metadata, _ComparableTuple( - self.components), _ComparableTuple(self.services), - _ComparableTuple(self.external_references), _ComparableTuple( - self.dependencies), _ComparableTuple(self.properties), - _ComparableTuple(self.vulnerabilities), + def __hash__(self) -> int: + return hash(( + self.serial_number, self.version, self.metadata, + tuple(self.components), tuple(self.services), + tuple(self.external_references), tuple(self.dependencies), + tuple(self.properties), tuple(self.vulnerabilities), )) - def __eq__(self, other: object) -> bool: - if isinstance(other, Bom): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @classmethod + def from_json(cls, data: Union[dict, str, bytes]) -> 'Bom': + """ + Create a Bom from JSON data. - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + Args: + data: JSON data as a dict, string, or bytes - def __repr__(self) -> str: - return f'' + Returns: + A new Bom instance + """ + import json + + from ..serialization import make_converter + + if isinstance(data, (str, bytes)): + data = json.loads(data) + + # Determine schema version from data + spec_version = data.get('specVersion', '1.4') + version_map = { + '1.0': SchemaVersion.V1_0, + '1.1': SchemaVersion.V1_1, + '1.2': SchemaVersion.V1_2, + '1.3': SchemaVersion.V1_3, + '1.4': SchemaVersion.V1_4, + '1.5': SchemaVersion.V1_5, + '1.6': SchemaVersion.V1_6, + '1.7': SchemaVersion.V1_7, + } + schema_version = version_map.get(spec_version, SchemaVersion.V1_4) + + converter = make_converter(schema_version) + return converter.structure(data, cls) + + @classmethod + def from_xml(cls, data: Union['Element', str, bytes, Any]) -> 'Bom': + """ + Create a Bom from XML data. + + Args: + data: XML data as an Element, string, bytes, or file-like object + + Returns: + A new Bom instance + """ + from xml.etree.ElementTree import Element, fromstring, parse + + from ..serialization import make_converter + + if isinstance(data, (str, bytes)): + data = fromstring(data) + elif hasattr(data, 'read'): + # Handle file-like objects + data = parse(data).getroot() + + # Determine schema version from namespace + ns = data.tag.split('}')[0].strip('{') if data.tag.startswith('{') else '' + version_map = { + 'http://cyclonedx.org/schema/bom/1.0': SchemaVersion.V1_0, + 'http://cyclonedx.org/schema/bom/1.1': SchemaVersion.V1_1, + 'http://cyclonedx.org/schema/bom/1.2': SchemaVersion.V1_2, + 'http://cyclonedx.org/schema/bom/1.3': SchemaVersion.V1_3, + 'http://cyclonedx.org/schema/bom/1.4': SchemaVersion.V1_4, + 'http://cyclonedx.org/schema/bom/1.5': SchemaVersion.V1_5, + 'http://cyclonedx.org/schema/bom/1.6': SchemaVersion.V1_6, + 'http://cyclonedx.org/schema/bom/1.7': SchemaVersion.V1_7, + } + schema_version = version_map.get(ns, SchemaVersion.V1_4) + + # Convert XML to dict and then structure + xml_dict = cls._xml_to_dict(data) + converter = make_converter(schema_version) + return converter.structure(xml_dict, cls) + + @staticmethod + def _xml_to_dict(element: 'Element') -> dict: + """Convert an XML element to a dictionary. + + Handles XML container patterns like ... + by unwrapping to arrays that match the JSON structure. + """ + from xml.etree.ElementTree import Element + + result: dict = {} + + # Handle attributes + for key, value in element.attrib.items(): + # Remove namespace prefix from attribute names + if '}' in key: + key = key.split('}')[1] + # Convert hyphen to underscore for Python field names + key = key.replace('-', '_') + result[key] = value + + # Handle child elements + for child in element: + # Remove namespace prefix from tag names + tag = child.tag.split('}')[1] if '}' in child.tag else child.tag + + if len(child) == 0 and not child.attrib: + # Simple text content + value = child.text + else: + # Complex element + value = Bom._xml_to_dict(child) + + # Handle lists (multiple elements with same tag) + if tag in result: + if not isinstance(result[tag], list): + result[tag] = [result[tag]] + result[tag].append(value) + else: + result[tag] = value + + # If element has only text content (no attributes, no children) + if not result and element.text: + return element.text # type: ignore[return-value] + + # Handle elements with both attributes and text content + # e.g., content here + # This should produce {"content-type": "text/plain", "content": "content here"} + if result and element.text and element.text.strip(): + # Check if there are no child elements (only attributes) + has_child_elements = any(True for _ in element) + if not has_child_elements: + result['content'] = element.text + + # Unwrap XML container patterns to match JSON structure + # e.g., {"components": {"component": [...]}} -> {"components": [...]} + result = Bom._unwrap_xml_containers(result) + + return result + + @staticmethod + def _unwrap_xml_containers(data: dict) -> dict: + """Unwrap XML container patterns to match JSON structure. + + XML uses patterns like ... + while JSON uses direct arrays: "components": [...] + + This detects containers where the only child key is a singular form + and unwraps them to direct arrays. + """ + # Known container mappings (plural -> singular) + container_mappings = { + 'components': 'component', + 'dependencies': 'dependency', + 'properties': 'property', + 'hashes': 'hash', + 'licenses': 'license', + 'externalReferences': 'reference', + 'vulnerabilities': 'vulnerability', + 'services': 'service', + 'tools': 'tool', + 'authors': 'author', + 'patches': 'patch', + 'commits': 'commit', + 'compositions': 'composition', + 'annotations': 'annotation', + 'formulation': 'formula', + 'methods': 'method', + 'identities': 'identity', + 'occurrences': 'occurrence', + 'callstack': 'frame', + 'algorithms': 'algorithm', + 'identifiers': 'identifier', + 'cipherSuites': 'cipherSuite', + 'cryptoRefArray': 'cryptoRef', + 'subjectAlternativeNames': 'name', + 'manufacturers': 'manufacturer', + 'constraints': 'constraint', + 'targets': 'target', + 'affects': 'target', + 'credits': 'organizationalContact', + 'workarounds': 'workaround', + 'references': 'reference', # Vulnerability references use 'reference' as child + 'advisories': 'advisory', + 'ratings': 'rating', + 'cwes': 'cwe', + 'declarations': 'standards', + # 'definitions' is a complex object, not a simple container + # It contains 'standards' which contains 'standard' children + 'standards': 'standard', + # Standard contains levels and requirements containers + 'levels': 'level', + 'requirements': 'requirement', + # Requirement contains descriptions container + 'descriptions': 'description', + # Affects target contains versions + 'versions': 'version', + # Credits containers + 'organizations': 'organization', + 'contacts': 'contact', + 'individuals': 'individual', + 'claims': 'claim', + 'evidence': 'evidence', + 'counters': 'counter', + 'assessors': 'assessor', + 'attestations': 'attestation', + 'encr': 'ref', + 'prf': 'ref', + 'integ': 'ref', + # Service data classifications + 'data': 'classification', + 'endpoints': 'endpoint', + 'ke': 'ref', + 'auth': 'ref', + # Pedigree component containers + 'ancestors': 'component', + 'descendants': 'component', + 'variants': 'component', + # Callstack frames + 'frames': 'frame', + 'parameters': 'parameter', + # Metadata lifecycles + 'lifecycles': 'lifecycle', + # ReleaseNotes fields + 'resolves': 'issue', + 'notes': 'note', + 'aliases': 'alias', + 'tags': 'tag', + # Crypto fields + 'cryptoFunctions': 'cryptoFunction', + 'certificationLevel': 'certification', + # Vulnerability analysis responses + 'responses': 'response', + } + + # XML element names that need to be renamed to JSON names + # When XML has elements directly (no container), we need to use the JSON name + xml_to_json_name = { + 'cryptoRef': 'cryptoRefArray', # ... -> cryptoRefArray + 'responses': 'response', # XML container name -> JSON field name for VulnerabilityAnalysis + } + + unwrapped = {} + for key, value in data.items(): + # Rename XML element names to JSON names if needed + out_key = xml_to_json_name.get(key, key) + if isinstance(value, dict): + # Special handling for licenses which can contain both 'license' and 'expression' + if key == 'licenses': + result: list = [] + # Collect license children (DisjunctiveLicense) + if 'license' in value: + license_val = value['license'] + if isinstance(license_val, list): + for lic in license_val: + if isinstance(lic, dict): + result.append(Bom._unwrap_xml_containers(lic)) + else: + result.append(lic) + else: + if isinstance(license_val, dict): + result.append(Bom._unwrap_xml_containers(license_val)) + else: + result.append(license_val) + # Collect expression children (LicenseExpression) + if 'expression' in value: + expr_val = value['expression'] + if isinstance(expr_val, list): + for expr in expr_val: + # Keep the 'expression' wrapper for structuring + if isinstance(expr, dict): + result.append({'expression': expr}) + else: + result.append({'expression': expr}) + else: + # Single expression - keep the 'expression' wrapper + if isinstance(expr_val, dict): + result.append({'expression': expr_val}) + else: + result.append({'expression': expr_val}) + # If we found licenses, use the collected result + if result: + unwrapped[out_key] = result + else: + # No recognized children, pass through + unwrapped[out_key] = Bom._unwrap_xml_containers(value) + continue + + # Special handling for copyright which contains 'text' children + # that should become Copyright objects + if key == 'copyright' and 'text' in value: + text_val = value['text'] + if isinstance(text_val, list): + # Multiple text elements -> list of Copyright objects + unwrapped[out_key] = [{'text': t} for t in text_val] + else: + # Single text element -> list with one Copyright object + unwrapped[out_key] = [{'text': text_val}] + continue + + # Special handling for references in issues - contains 'url' children + # that should become a list of URLs (XsUri) + if key == 'references' and 'url' in value and len(value) == 1: + url_val = value['url'] + if isinstance(url_val, list): + unwrapped[out_key] = url_val + else: + unwrapped[out_key] = [url_val] + continue + + # Special handling for tools in identity - contains 'tool' with 'ref' attr + # that should become a list of ref strings (BomRef) + if key == 'tools' and 'tool' in value: + tool_val = value['tool'] + if not isinstance(tool_val, list): + tool_val = [tool_val] + # Extract ref values from tool dicts + refs = [] + for t in tool_val: + if isinstance(t, dict) and 'ref' in t: + refs.append(t['ref']) + elif isinstance(t, str): + refs.append(t) + if refs: + unwrapped[out_key] = refs + continue + + # Check if this is a container that should be unwrapped + singular = container_mappings.get(key) + if singular and singular in value and len(value) == 1: + # Unwrap: {"components": {"component": [...]}} -> {"components": [...]} + inner = value[singular] + # Ensure it's a list + if not isinstance(inner, list): + inner = [inner] + unwrapped[out_key] = inner + else: + # Recursively unwrap nested structures + unwrapped[out_key] = Bom._unwrap_xml_containers(value) + elif isinstance(value, list): + # Recursively unwrap items in lists + unwrapped[out_key] = [ + Bom._unwrap_xml_containers(item) if isinstance(item, dict) else item + for item in value + ] + else: + unwrapped[out_key] = value + + return unwrapped diff --git a/cyclonedx/model/bom_ref.py b/cyclonedx/model/bom_ref.py index edde98efe..14388664f 100644 --- a/cyclonedx/model/bom_ref.py +++ b/cyclonedx/model/bom_ref.py @@ -18,18 +18,14 @@ from typing import TYPE_CHECKING, Any, Optional -import py_serializable as serializable - from ..exception.serialization import CycloneDxDeserializationException, SerializationOfUnexpectedValueException if TYPE_CHECKING: # pragma: no cover from typing import TypeVar - _T_BR = TypeVar('_T_BR', bound='BomRef') -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class BomRef(serializable.helpers.BaseHelper): +class BomRef: """ An identifier that can be used to reference objects elsewhere in the BOM. @@ -40,11 +36,10 @@ class BomRef(serializable.helpers.BaseHelper): """ def __init__(self, value: Optional[str] = None) -> None: - self.value = value + # empty strings become `None` + self._value = value or None @property - @serializable.json_name('.') - @serializable.xml_name('.') def value(self) -> Optional[str]: return self._value @@ -80,8 +75,6 @@ def __str__(self) -> str: def __bool__(self) -> bool: return self._value is not None - # region impl BaseHelper - @classmethod def serialize(cls, o: Any) -> Optional[str]: if isinstance(o, cls): @@ -97,5 +90,3 @@ def deserialize(cls: 'type[_T_BR]', o: Any) -> '_T_BR': raise CycloneDxDeserializationException( f'BomRef string supplied does not parse: {o!r}' ) from err - - # endregion impl BaseHelper diff --git a/cyclonedx/model/component.py b/cyclonedx/model/component.py index 47702ed00..329faa0a3 100644 --- a/cyclonedx/model/component.py +++ b/cyclonedx/model/component.py @@ -15,6 +15,35 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) OWASP Foundation. All Rights Reserved. +from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str +from ..serialization import ALL_VERSIONS, VERSIONS_1_1_AND_LATER +from ..schema import SchemaVersion +from .release_note import ReleaseNotes +from .license import License, LicenseRepository +from .issue import IssueType +from .dependency import Dependable +from .crypto import CryptoProperties +from .contact import OrganizationalContact, OrganizationalEntity +from .component_evidence import ComponentEvidence +from .bom_ref import BomRef +from . import AttachedText, ExternalReference, HashAlgorithm, HashType, IdentifiableAction, Property, XsUri +from ..serialization import ( + METADATA_KEY_INCLUDE_NONE, + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_0_THROUGH_1_3, + VERSIONS_1_1_AND_LATER, + VERSIONS_1_2_AND_LATER, + VERSIONS_1_3_AND_LATER, + VERSIONS_1_4_AND_LATER, + VERSIONS_1_6_AND_LATER, +) +from ..exception.serialization import CycloneDxDeserializationException, SerializationOfUnexpectedValueException +from ..exception.model import InvalidOmniBorIdException, InvalidSwhidException +from .._internal.compare import ComparablePackageURL as _ComparablePackageURL import re import sys from collections.abc import Iterable @@ -27,176 +56,92 @@ else: from typing_extensions import deprecated -# See https://github.com/package-url/packageurl-python/issues/65 -import py_serializable as serializable +import attrs from packageurl import PackageURL from sortedcontainers import SortedSet -from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str -from .._internal.compare import ComparablePackageURL as _ComparablePackageURL, ComparableTuple as _ComparableTuple -from ..exception.model import InvalidOmniBorIdException, InvalidSwhidException -from ..exception.serialization import ( - CycloneDxDeserializationException, - SerializationOfUnexpectedValueException, - SerializationOfUnsupportedComponentTypeException, -) -from ..schema.schema import ( - SchemaVersion1Dot0, - SchemaVersion1Dot1, - SchemaVersion1Dot2, - SchemaVersion1Dot3, - SchemaVersion1Dot4, - SchemaVersion1Dot5, - SchemaVersion1Dot6, - SchemaVersion1Dot7, -) -from ..serialization import PackageUrl as PackageUrlSH -from . import ( - AttachedText, - ExternalReference, - HashAlgorithm, - HashType, - IdentifiableAction, - Property, - XsUri, - _HashTypeRepositorySerializationHelper, -) -from .bom_ref import BomRef -from .component_evidence import ComponentEvidence, _ComponentEvidenceSerializationHelper -from .contact import OrganizationalContact, OrganizationalEntity -from .crypto import CryptoProperties -from .dependency import Dependable -from .issue import IssueType -from .license import License, LicenseRepository, _LicenseRepositorySerializationHelper -from .release_note import ReleaseNotes +def _sortedset_converter(value: Any) -> SortedSet: + """Converter to ensure values are always SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class Commit: - """ - Our internal representation of the `commitType` complex type. - .. note:: - See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_commitType - """ - - def __init__( - self, *, - uid: Optional[str] = None, - url: Optional[XsUri] = None, - author: Optional[IdentifiableAction] = None, - committer: Optional[IdentifiableAction] = None, - message: Optional[str] = None, - ) -> None: - self.uid = uid - self.url = url - self.author = author - self.committer = committer - self.message = message - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def uid(self) -> Optional[str]: - """ - A unique identifier of the commit. This may be version control specific. For example, Subversion uses revision - numbers whereas git uses commit hashes. - - Returns: - `str` if set else `None` - """ - return self._uid - - @uid.setter - def uid(self, uid: Optional[str]) -> None: - self._uid = uid - - @property - @serializable.xml_sequence(2) - def url(self) -> Optional[XsUri]: - """ - The URL to the commit. This URL will typically point to a commit in a version control system. +def _bom_ref_converter(value: Optional[Union[str, BomRef]]) -> BomRef: + """Convert string or BomRef to BomRef.""" + return _bom_ref_from_str(value) - Returns: - `XsUri` if set else `None` - """ - return self._url - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url +def _sortedset_factory() -> SortedSet: + return SortedSet() - @property - @serializable.xml_sequence(3) - def author(self) -> Optional[IdentifiableAction]: - """ - The author who created the changes in the commit. - Returns: - `IdentifiableAction` if set else `None` - """ - return self._author +def _license_repository_factory() -> LicenseRepository: + return LicenseRepository() - @author.setter - def author(self, author: Optional[IdentifiableAction]) -> None: - self._author = author - @property - @serializable.xml_sequence(4) - def committer(self) -> Optional[IdentifiableAction]: - """ - The person who committed or pushed the commit +def _license_repository_converter(value: Any) -> LicenseRepository: + if value is None: + return LicenseRepository() + if isinstance(value, LicenseRepository): + return value + # Convert generators, lists, etc. to LicenseRepository + return LicenseRepository(value) - Returns: - `IdentifiableAction` if set else `None` - """ - return self._committer - @committer.setter - def committer(self, committer: Optional[IdentifiableAction]) -> None: - self._committer = committer +@attrs.define +class Commit: + """ + Our internal representation of the `commitType` complex type. - @property - @serializable.xml_sequence(5) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def message(self) -> Optional[str]: - """ - The text description of the contents of the commit. - - Returns: - `str` if set else `None` - """ - return self._message - - @message.setter - def message(self, message: Optional[str]) -> None: - self._message = message - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.uid, self.url, - self.author, self.committer, - self.message - )) + .. note:: + See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_commitType + """ + uid: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + url: Optional[XsUri] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + author: Optional[IdentifiableAction] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + committer: Optional[IdentifiableAction] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + message: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) - def __eq__(self, other: object) -> bool: - if isinstance(other, Commit): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Commit): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return (c(self.uid), c(self.url), c(self.author), c(self.committer), c(self.message)) < ( + c(other.uid), c(other.url), c(other.author), c(other.committer), c(other.message)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.uid, self.url, self.author, self.committer, self.message)) def __repr__(self) -> str: return f'' -@serializable.serializable_enum class ComponentScope(str, Enum): """ Enum object that defines the permissable 'scopes' for a Component according to the CycloneDX schema. @@ -204,56 +149,19 @@ class ComponentScope(str, Enum): .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_scope """ - # see `_ComponentScopeSerializationHelper.__CASES` for view/case map REQUIRED = 'required' OPTIONAL = 'optional' EXCLUDED = 'excluded' # Only supported in >= 1.1 -class _ComponentScopeSerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - __CASES: dict[type[serializable.ViewType], frozenset[ComponentScope]] = dict() - __CASES[SchemaVersion1Dot0] = frozenset({ - ComponentScope.REQUIRED, - ComponentScope.OPTIONAL, - }) - __CASES[SchemaVersion1Dot1] = __CASES[SchemaVersion1Dot0] | { - ComponentScope.EXCLUDED, - } - __CASES[SchemaVersion1Dot2] = __CASES[SchemaVersion1Dot1] - __CASES[SchemaVersion1Dot3] = __CASES[SchemaVersion1Dot2] - __CASES[SchemaVersion1Dot4] = __CASES[SchemaVersion1Dot3] - __CASES[SchemaVersion1Dot5] = __CASES[SchemaVersion1Dot4] - __CASES[SchemaVersion1Dot6] = __CASES[SchemaVersion1Dot5] - __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] +# Component scope support by schema version +COMPONENT_SCOPE_VERSIONS: dict[ComponentScope, set[SchemaVersion]] = { + ComponentScope.REQUIRED: ALL_VERSIONS, + ComponentScope.OPTIONAL: ALL_VERSIONS, + ComponentScope.EXCLUDED: VERSIONS_1_1_AND_LATER, +} - @classmethod - def __normalize(cls, cs: ComponentScope, view: type[serializable.ViewType]) -> Optional[str]: - return cs.value \ - if cs in cls.__CASES.get(view, ()) \ - else None - @classmethod - def json_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> Optional[str]: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def xml_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> Optional[str]: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def deserialize(cls, o: Any) -> ComponentScope: - return ComponentScope(o) - - -@serializable.serializable_enum class ComponentType(str, Enum): """ Enum object that defines the permissible 'types' for a Component according to the CycloneDX schema. @@ -261,7 +169,6 @@ class ComponentType(str, Enum): .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_classification """ - # see `_ComponentTypeSerializationHelper.__CASES` for view/case map APPLICATION = 'application' CONTAINER = 'container' # Only supported in >= 1.2 CRYPTOGRAPHIC_ASSET = 'cryptographic-asset' # Only supported in >= 1.6 @@ -277,63 +184,7 @@ class ComponentType(str, Enum): PLATFORM = 'platform' # Only supported in >= 1.5 -class _ComponentTypeSerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - __CASES: dict[type[serializable.ViewType], frozenset[ComponentType]] = dict() - __CASES[SchemaVersion1Dot0] = frozenset({ - ComponentType.APPLICATION, - ComponentType.DEVICE, - ComponentType.FRAMEWORK, - ComponentType.LIBRARY, - ComponentType.OPERATING_SYSTEM, - }) - __CASES[SchemaVersion1Dot1] = __CASES[SchemaVersion1Dot0] | { - ComponentType.FILE, - } - __CASES[SchemaVersion1Dot2] = __CASES[SchemaVersion1Dot1] | { - ComponentType.CONTAINER, - ComponentType.FIRMWARE, - } - __CASES[SchemaVersion1Dot3] = __CASES[SchemaVersion1Dot2] - __CASES[SchemaVersion1Dot4] = __CASES[SchemaVersion1Dot3] - __CASES[SchemaVersion1Dot5] = __CASES[SchemaVersion1Dot4] | { - ComponentType.DATA, - ComponentType.DEVICE_DRIVER, - ComponentType.MACHINE_LEARNING_MODEL, - ComponentType.PLATFORM, - } - __CASES[SchemaVersion1Dot6] = __CASES[SchemaVersion1Dot5] | { - ComponentType.CRYPTOGRAPHIC_ASSET, - } - __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] - - @classmethod - def __normalize(cls, ct: ComponentType, view: type[serializable.ViewType]) -> Optional[str]: - if ct in cls.__CASES.get(view, ()): - return ct.value - raise SerializationOfUnsupportedComponentTypeException(f'unsupported {ct!r} for view {view!r}') - - @classmethod - def json_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> Optional[str]: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def xml_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> Optional[str]: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def deserialize(cls, o: Any) -> ComponentType: - return ComponentType(o) - - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Diff: """ Our internal representation of the `diffType` complex type. @@ -341,67 +192,26 @@ class Diff: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_diffType """ + text: Optional[AttachedText] = attrs.field(default=None) + url: Optional[XsUri] = attrs.field(default=None) - def __init__( - self, *, - text: Optional[AttachedText] = None, - url: Optional[XsUri] = None, - ) -> None: - self.text = text - self.url = url - - @property - def text(self) -> Optional[AttachedText]: - """ - Specifies the optional text of the diff. - - Returns: - `AttachedText` if set else `None` - """ - return self._text - - @text.setter - def text(self, text: Optional[AttachedText]) -> None: - self._text = text - - @property - def url(self) -> Optional[XsUri]: - """ - Specifies the URL to the diff. - - Returns: - `XsUri` if set else `None` - """ - return self._url - - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.url, - self.text, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Diff): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Diff): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.url), self._cmp(self.text)) < (self._cmp(other.url), self._cmp(other.text)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.url, self.text)) def __repr__(self) -> str: return f'' -@serializable.serializable_enum class PatchClassification(str, Enum): """ Enum object that defines the permissible `patchClassification`s. @@ -415,7 +225,7 @@ class PatchClassification(str, Enum): UNOFFICIAL = 'unofficial' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Patch: """ Our internal representation of the `patchType` complex type. @@ -423,258 +233,100 @@ class Patch: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_patchType """ - - def __init__( - self, *, - type: PatchClassification, - diff: Optional[Diff] = None, - resolves: Optional[Iterable[IssueType]] = None, - ) -> None: - self.type = type - self.diff = diff - self.resolves = resolves or [] - - @property - @serializable.xml_attribute() - def type(self) -> PatchClassification: - """ - Specifies the purpose for the patch including the resolution of defects, security issues, or new behavior or - functionality. - - Returns: - `PatchClassification` - """ - return self._type - - @type.setter - def type(self, type: PatchClassification) -> None: - self._type = type - - @property - def diff(self) -> Optional[Diff]: - """ - The patch file (or diff) that show changes. - - .. note:: - Refer to https://en.wikipedia.org/wiki/Diff. - - Returns: - `Diff` if set else `None` - """ - return self._diff - - @diff.setter - def diff(self, diff: Optional[Diff]) -> None: - self._diff = diff - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'issue') - def resolves(self) -> 'SortedSet[IssueType]': - """ - Optional list of issues resolved by this patch. - - Returns: - Set of `IssueType` - """ - return self._resolves - - @resolves.setter - def resolves(self, resolves: Iterable[IssueType]) -> None: - self._resolves = SortedSet(resolves) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, self.diff, - _ComparableTuple(self.resolves) - )) + type: PatchClassification = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + diff: Optional[Diff] = attrs.field(default=None) + resolves: 'SortedSet[IssueType]' = attrs.field(factory=_sortedset_factory, converter=_sortedset_converter) def __eq__(self, other: object) -> bool: if isinstance(other, Patch): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + return (self.type, self.diff, tuple(self.resolves)) == ( + other.type, other.diff, tuple(other.resolves)) + return NotImplemented + + @staticmethod + def _cmp_patch(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Patch): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp_patch + return (self.type, c(self.diff), tuple(self.resolves)) < ( + other.type, c(other.diff), tuple(other.resolves)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.type, self.diff, tuple(self.resolves))) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Pedigree: """ Our internal representation of the `pedigreeType` complex type. - Component pedigree is a way to document complex supply chain scenarios where components are created, distributed, - modified, redistributed, combined with other components, etc. Pedigree supports viewing this complex chain from the - beginning, the end, or anywhere in the middle. It also provides a way to document variants where the exact relation - may not be known. - .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_pedigreeType """ - - def __init__( - self, *, - ancestors: Optional[Iterable['Component']] = None, - descendants: Optional[Iterable['Component']] = None, - variants: Optional[Iterable['Component']] = None, - commits: Optional[Iterable[Commit]] = None, - patches: Optional[Iterable[Patch]] = None, - notes: Optional[str] = None, - ) -> None: - self.ancestors = ancestors or [] - self.descendants = descendants or [] - self.variants = variants or [] - self.commits = commits or [] - self.patches = patches or [] - self.notes = notes - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component') - @serializable.xml_sequence(1) - def ancestors(self) -> "SortedSet['Component']": - """ - Describes zero or more components in which a component is derived from. This is commonly used to describe forks - from existing projects where the forked version contains a ancestor node containing the original component it - was forked from. - - For example, Component A is the original component. Component B is the component being used and documented in - the BOM. However, Component B contains a pedigree node with a single ancestor documenting Component A - the - original component from which Component B is derived from. - - Returns: - Set of `Component` - """ - return self._ancestors - - @ancestors.setter - def ancestors(self, ancestors: Iterable['Component']) -> None: - self._ancestors = SortedSet(ancestors) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component') - @serializable.xml_sequence(2) - def descendants(self) -> "SortedSet['Component']": - """ - Descendants are the exact opposite of ancestors. This provides a way to document all forks (and their forks) of - an original or root component. - - Returns: - Set of `Component` - """ - return self._descendants - - @descendants.setter - def descendants(self, descendants: Iterable['Component']) -> None: - self._descendants = SortedSet(descendants) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component') - @serializable.xml_sequence(3) - def variants(self) -> "SortedSet['Component']": - """ - Variants describe relations where the relationship between the components are not known. For example, if - Component A contains nearly identical code to Component B. They are both related, but it is unclear if one is - derived from the other, or if they share a common ancestor. - - Returns: - Set of `Component` - """ - return self._variants - - @variants.setter - def variants(self, variants: Iterable['Component']) -> None: - self._variants = SortedSet(variants) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'commit') - @serializable.xml_sequence(4) - def commits(self) -> 'SortedSet[Commit]': - """ - A list of zero or more commits which provide a trail describing how the component deviates from an ancestor, - descendant, or variant. - - Returns: - Set of `Commit` - """ - return self._commits - - @commits.setter - def commits(self, commits: Iterable[Commit]) -> None: - self._commits = SortedSet(commits) - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'patch') - @serializable.xml_sequence(5) - def patches(self) -> 'SortedSet[Patch]': - """ - A list of zero or more patches describing how the component deviates from an ancestor, descendant, or variant. - Patches may be complimentary to commits or may be used in place of commits. - - Returns: - Set of `Patch` - """ - return self._patches - - @patches.setter - def patches(self, patches: Iterable[Patch]) -> None: - self._patches = SortedSet(patches) - - @property - @serializable.xml_sequence(6) - def notes(self) -> Optional[str]: - """ - Notes, observations, and other non-structured commentary describing the components pedigree. - - Returns: - `str` if set else `None` - """ - return self._notes - - @notes.setter - def notes(self, notes: Optional[str]) -> None: - self._notes = notes - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self.ancestors), - _ComparableTuple(self.descendants), - _ComparableTuple(self.variants), - _ComparableTuple(self.commits), - _ComparableTuple(self.patches), - self.notes - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Pedigree): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + ancestors: 'SortedSet[Component]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + descendants: 'SortedSet[Component]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + variants: 'SortedSet[Component]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + commits: 'SortedSet[Commit]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + patches: 'SortedSet[Patch]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_2_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 5, + } + ) + notes: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 6} + ) def __lt__(self, other: object) -> bool: if isinstance(other, Pedigree): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + tuple(self.ancestors), tuple(self.descendants), tuple(self.variants), + tuple(self.commits), tuple(self.patches), self.notes + ) < ( + tuple(other.ancestors), tuple(other.descendants), tuple(other.variants), + tuple(other.commits), tuple(other.patches), other.notes + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + tuple(self.ancestors), tuple(self.descendants), tuple(self.variants), + tuple(self.commits), tuple(self.patches), self.notes + )) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Swid: """ Our internal representation of the `swidType` complex type. @@ -682,161 +334,46 @@ class Swid: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_swidType """ + tag_id: str = attrs.field(metadata={METADATA_KEY_JSON_NAME: 'tagId', METADATA_KEY_XML_ATTR: True}) + name: str = attrs.field(metadata={METADATA_KEY_XML_ATTR: True}) + version: Optional[str] = attrs.field(default=None, metadata={METADATA_KEY_XML_ATTR: True}) + tag_version: Optional[int] = attrs.field( + default=None, metadata={METADATA_KEY_JSON_NAME: 'tagVersion', METADATA_KEY_XML_ATTR: True}) + patch: Optional[bool] = attrs.field(default=None, metadata={METADATA_KEY_XML_ATTR: True}) + text: Optional[AttachedText] = attrs.field(default=None) + url: Optional[XsUri] = attrs.field(default=None) - def __init__( - self, *, - tag_id: str, - name: str, - version: Optional[str] = None, - tag_version: Optional[int] = None, - patch: Optional[bool] = None, - text: Optional[AttachedText] = None, - url: Optional[XsUri] = None, - ) -> None: - self.tag_id = tag_id - self.name = name - self.version = version - self.tag_version = tag_version - self.patch = patch - self.text = text - self.url = url - - @property - @serializable.xml_attribute() - def tag_id(self) -> str: - """ - Maps to the tagId of a SoftwareIdentity. - - Returns: - `str` - """ - return self._tag_id - - @tag_id.setter - def tag_id(self, tag_id: str) -> None: - self._tag_id = tag_id - - @property - @serializable.xml_attribute() - def name(self) -> str: - """ - Maps to the name of a SoftwareIdentity. - - Returns: - `str` - """ - return self._name - - @name.setter - def name(self, name: str) -> None: - self._name = name - - @property - @serializable.xml_attribute() - def version(self) -> Optional[str]: - """ - Maps to the version of a SoftwareIdentity. - - Returns: - `str` if set else `None`. - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version - - @property - @serializable.xml_attribute() - def tag_version(self) -> Optional[int]: - """ - Maps to the tagVersion of a SoftwareIdentity. - - Returns: - `int` if set else `None` - """ - return self._tag_version - - @tag_version.setter - def tag_version(self, tag_version: Optional[int]) -> None: - self._tag_version = tag_version - - @property - @serializable.xml_attribute() - def patch(self) -> Optional[bool]: - """ - Maps to the patch of a SoftwareIdentity. - - Returns: - `bool` if set else `None` - """ - return self._patch - - @patch.setter - def patch(self, patch: Optional[bool]) -> None: - self._patch = patch - - @property - def text(self) -> Optional[AttachedText]: - """ - Specifies the full content of the SWID tag. - - Returns: - `AttachedText` if set else `None` - """ - return self._text - - @text.setter - def text(self, text: Optional[AttachedText]) -> None: - self._text = text - - @property - def url(self) -> Optional[XsUri]: - """ - The URL to the SWID file. - - Returns: - `XsUri` if set else `None` - """ - return self._url - - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.tag_id, - self.name, self.version, - self.tag_version, - self.patch, - self.url, - self.text, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Swid): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: object) -> bool: if isinstance(other, Swid): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return ( + self.tag_id, self.name, c(self.version), c(self.tag_version), + c(self.patch), c(self.url), c(self.text) + ) < ( + other.tag_id, other.name, c(other.version), c(other.tag_version), + c(other.patch), c(other.url), c(other.text) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.tag_id, self.name, self.version, self.tag_version, + self.patch, self.url, self.text + )) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class OmniborId(serializable.helpers.BaseHelper): +class OmniborId: """ Helper class that allows us to perform validation on data strings that must conform to https://www.iana.org/assignments/uri-schemes/prov/gitoid. - """ _VALID_OMNIBOR_ID_REGEX = re.compile(r'^gitoid:(blob|tree|commit|tag):sha(1|256):([a-z0-9]+)$') @@ -849,8 +386,6 @@ def __init__(self, id: str) -> None: self._id = id @property - @serializable.json_name('.') - @serializable.xml_name('.') def id(self) -> str: return self._id @@ -890,12 +425,10 @@ def __str__(self) -> str: return self._id -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class Swhid(serializable.helpers.BaseHelper): +class Swhid: """ Helper class that allows us to perform validation on data strings that must conform to https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html. - """ _VALID_SWHID_REGEX = re.compile(r'^swh:1:(cnp|rel|rev|dir|cnt):([0-9a-z]{40})(.*)?$') @@ -908,8 +441,6 @@ def __init__(self, id: str) -> None: self._id = id @property - @serializable.json_name('.') - @serializable.xml_name('.') def id(self) -> str: return self._id @@ -949,7 +480,7 @@ def __str__(self) -> str: return self._id -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Component(Dependable): """ This is our internal representation of a Component within a Bom. @@ -957,709 +488,202 @@ class Component(Dependable): .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_component """ + name: str = attrs.field(metadata={METADATA_KEY_XML_SEQUENCE: 7}) + type: ComponentType = attrs.field( + default=ComponentType.LIBRARY, + metadata={METADATA_KEY_XML_ATTR: True} + ) + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_1_AND_LATER, + METADATA_KEY_JSON_NAME: 'bom-ref', + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + } + ) + mime_type: Optional[str] = attrs.field(default=None) + supplier: Optional[OrganizationalEntity] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_2_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 1, + } + ) + manufacturer: Optional[OrganizationalEntity] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 2, + } + ) + authors: 'SortedSet[OrganizationalContact]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 3, + } + ) + author: Optional[str] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_2_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 4, + } + ) + publisher: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) + group: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 6} + ) + version: Optional[str] = attrs.field( + default=None, + metadata={ + METADATA_KEY_XML_SEQUENCE: 8, + METADATA_KEY_INCLUDE_NONE: VERSIONS_1_0_THROUGH_1_3, # Required in older schemas + } + ) + description: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 9} + ) + scope: Optional[ComponentScope] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 10} + ) + hashes: 'SortedSet[HashType]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 11} + ) + licenses: LicenseRepository = attrs.field( + factory=_license_repository_factory, + converter=_license_repository_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_1_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 12, + } + ) + copyright: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 13} + ) + cpe: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 14} + ) + purl: Optional[PackageURL] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 15} + ) + omnibor_ids: 'SortedSet[OmniborId]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_JSON_NAME: 'omniborId', + METADATA_KEY_XML_SEQUENCE: 16, + } + ) + swhids: 'SortedSet[Swhid]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_JSON_NAME: 'swhid', + METADATA_KEY_XML_SEQUENCE: 17, + } + ) + swid: Optional[Swid] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_2_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 18, + } + ) + modified: bool = attrs.field( + default=False, + metadata={METADATA_KEY_XML_SEQUENCE: 19} + ) + pedigree: Optional[Pedigree] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_1_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 20, + } + ) + external_references: 'SortedSet[ExternalReference]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_1_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 21, + } + ) + properties: 'SortedSet[Property]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_3_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 22, + } + ) + components: 'SortedSet[Component]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 23} + ) + evidence: Optional[ComponentEvidence] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_3_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 24, + } + ) + release_notes: Optional[ReleaseNotes] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_4_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 25, + } + ) + crypto_properties: Optional[CryptoProperties] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 30, + } + ) + tags: 'SortedSet[str]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 31, + } + ) @staticmethod @deprecated('Deprecated - use cyclonedx.contrib.component.builders.ComponentBuilder().make_for_file() instead') def for_file(absolute_file_path: str, path_for_bom: Optional[str]) -> 'Component': - """Deprecated — Wrapper of :func:`cyclonedx.contrib.component.builders.ComponentBuilder.make_for_file`. - - Helper method to create a Component that represents the provided local file as a Component. - - .. deprecated:: next - Use ``cyclonedx.contrib.component.builders.ComponentBuilder().make_for_file()`` instead. - """ + """Deprecated — Wrapper of :func:`cyclonedx.contrib.component.builders.ComponentBuilder.make_for_file`.""" from ..contrib.component.builders import ComponentBuilder component = ComponentBuilder().make_for_file(absolute_file_path, name=path_for_bom) sha1_hash = next((h.content for h in component.hashes if h.alg is HashAlgorithm.SHA_1), None) assert sha1_hash is not None component.version = f'0.0.0-{sha1_hash[0:12]}' - component.purl = PackageURL( # DEPRECATED: a file has no PURL! + component.purl = PackageURL( type='generic', name=path_for_bom if path_for_bom else absolute_file_path, version=f'0.0.0-{sha1_hash[0:12]}' ) return component - def __init__( - self, *, - name: str, - type: ComponentType = ComponentType.LIBRARY, - mime_type: Optional[str] = None, - bom_ref: Optional[Union[str, BomRef]] = None, - supplier: Optional[OrganizationalEntity] = None, - publisher: Optional[str] = None, - group: Optional[str] = None, - version: Optional[str] = None, - description: Optional[str] = None, - scope: Optional[ComponentScope] = None, - hashes: Optional[Iterable[HashType]] = None, - licenses: Optional[Iterable[License]] = None, - copyright: Optional[str] = None, - purl: Optional[PackageURL] = None, - external_references: Optional[Iterable[ExternalReference]] = None, - properties: Optional[Iterable[Property]] = None, - release_notes: Optional[ReleaseNotes] = None, - cpe: Optional[str] = None, - swid: Optional[Swid] = None, - pedigree: Optional[Pedigree] = None, - components: Optional[Iterable['Component']] = None, - evidence: Optional[ComponentEvidence] = None, - modified: bool = False, - manufacturer: Optional[OrganizationalEntity] = None, - authors: Optional[Iterable[OrganizationalContact]] = None, - omnibor_ids: Optional[Iterable[OmniborId]] = None, - swhids: Optional[Iterable[Swhid]] = None, - crypto_properties: Optional[CryptoProperties] = None, - tags: Optional[Iterable[str]] = None, - # Deprecated in v1.6 - author: Optional[str] = None, - ) -> None: - self.type = type - self.mime_type = mime_type - self._bom_ref = _bom_ref_from_str(bom_ref) - self.supplier = supplier - self.manufacturer = manufacturer - self.authors = authors or [] - self.publisher = publisher - self.group = group - self.name = name - self.description = description - self.scope = scope - self.hashes = hashes or [] - self.licenses = licenses or [] - self.copyright = copyright - self.cpe = cpe - self.purl = purl - self.omnibor_ids = omnibor_ids or [] - self.swhids = swhids or [] - self.swid = swid - self.pedigree = pedigree - self.external_references = external_references or [] - self.properties = properties or [] - self.components = components or [] - self.evidence = evidence - self.release_notes = release_notes - self.crypto_properties = crypto_properties - self.tags = tags or [] - # spec-deprecated properties below - self.author = author - self.modified = modified - self.version = version - - @property - @serializable.type_mapping(_ComponentTypeSerializationHelper) - @serializable.xml_attribute() - def type(self) -> ComponentType: - """ - Get the type of this Component. - - Returns: - Declared type of this Component as `ComponentType`. - """ - return self._type - - @type.setter - def type(self, type: ComponentType) -> None: - self._type = type - - @property - @serializable.xml_string(serializable.XmlStringSerializationType.TOKEN) - def mime_type(self) -> Optional[str]: - """ - Get any declared mime-type for this Component. - - When used on file components, the mime-type can provide additional context about the kind of file being - represented such as an image, font, or executable. Some library or framework components may also have an - associated mime-type. - - Returns: - `str` if set else `None` - """ - return self._mime_type - - @mime_type.setter - def mime_type(self, mime_type: Optional[str]) -> None: - self._mime_type = mime_type - - @property - @serializable.json_name('bom-ref') - @serializable.type_mapping(BomRef) - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(1) - def supplier(self) -> Optional[OrganizationalEntity]: - """ - The organization that supplied the component. The supplier may often be the manufacture, but may also be a - distributor or repackager. - - Returns: - `OrganizationalEntity` if set else `None` - """ - return self._supplier - - @supplier.setter - def supplier(self, supplier: Optional[OrganizationalEntity]) -> None: - self._supplier = supplier - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(2) - def manufacturer(self) -> Optional[OrganizationalEntity]: - """ - The organization that created the component. - Manufacturer is common in components created through automated processes. - Components created through manual means may have `@.authors` instead. - - Returns: - `OrganizationalEntity` if set else `None` - """ - return self._manufacturer - - @manufacturer.setter - def manufacturer(self, manufacturer: Optional[OrganizationalEntity]) -> None: - self._manufacturer = manufacturer - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'author') - @serializable.xml_sequence(3) - def authors(self) -> 'SortedSet[OrganizationalContact]': - """ - The person(s) who created the component. - Authors are common in components created through manual processes. - Components created through automated means may have `@.manufacturer` instead. - - Returns: - `Iterable[OrganizationalContact]` if set else `None` - """ - return self._authors - - @authors.setter - def authors(self, authors: Iterable[OrganizationalContact]) -> None: - self._authors = SortedSet(authors) - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(4) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def author(self) -> Optional[str]: - """ - The person(s) or organization(s) that authored the component. - - Returns: - `str` if set else `None` - """ - return self._author - - @author.setter - def author(self, author: Optional[str]) -> None: - if author is not None: - warn('`@.author` is deprecated from CycloneDX v1.6 onwards. ' - 'Please use `@.authors` or `@.manufacturer` instead.', DeprecationWarning) - self._author = author - - @property - @serializable.xml_sequence(5) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def publisher(self) -> Optional[str]: - """ - The person(s) or organization(s) that published the component - - Returns: - `str` if set else `None` - """ - return self._publisher - - @publisher.setter - def publisher(self, publisher: Optional[str]) -> None: - self._publisher = publisher - - @property - @serializable.xml_sequence(6) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def group(self) -> Optional[str]: - """ - The grouping name or identifier. This will often be a shortened, single name of the company or project that - produced the component, or the source package or domain name. Whitespace and special characters should be - avoided. - - Examples include: `apache`, `org.apache.commons`, and `apache.org`. - - Returns: - `str` if set else `None` - """ - return self._group - - @group.setter - def group(self, group: Optional[str]) -> None: - self._group = group - - @property - @serializable.xml_sequence(7) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> str: - """ - The name of the component. - - This will often be a shortened, single name of the component. - - Examples: `commons-lang3` and `jquery`. - - Returns: - `str` - """ - return self._name - - @name.setter - def name(self, name: str) -> None: - self._name = name - - @property - @serializable.include_none(SchemaVersion1Dot0, '') - @serializable.include_none(SchemaVersion1Dot1, '') - @serializable.include_none(SchemaVersion1Dot2, '') - @serializable.include_none(SchemaVersion1Dot3, '') - @serializable.xml_sequence(8) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def version(self) -> Optional[str]: - """ - The component version. The version should ideally comply with semantic versioning but is not enforced. - - This is NOT optional for CycloneDX Schema Version < 1.4 but was agreed to default to an empty string where a - version was not supplied for schema versions < 1.4 - - Returns: - Declared version of this Component as `str` or `None` - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - if version and len(version) > 1024: - warn('`@.version`has a maximum length of 1024 from CycloneDX v1.6 onwards.', UserWarning) - self._version = version - - @property - @serializable.xml_sequence(9) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def description(self) -> Optional[str]: - """ - Get the description of this Component. - - Returns: - `str` if set, else `None`. - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.type_mapping(_ComponentScopeSerializationHelper) - @serializable.xml_sequence(10) - def scope(self) -> Optional[ComponentScope]: - """ - Specifies the scope of the component. - - If scope is not specified, 'required' scope should be assumed by the consumer of the BOM. - - Returns: - `ComponentScope` or `None` - """ - return self._scope - - @scope.setter - def scope(self, scope: Optional[ComponentScope]) -> None: - self._scope = scope - - @property - @serializable.type_mapping(_HashTypeRepositorySerializationHelper) - @serializable.xml_sequence(11) - def hashes(self) -> 'SortedSet[HashType]': - """ - Optional list of hashes that help specify the integrity of this Component. - - Returns: - Set of `HashType` - """ - return self._hashes - - @hashes.setter - def hashes(self, hashes: Iterable[HashType]) -> None: - self._hashes = SortedSet(hashes) - - @property - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(_LicenseRepositorySerializationHelper) - @serializable.xml_sequence(12) - def licenses(self) -> LicenseRepository: - """ - A optional list of statements about how this Component is licensed. - - Returns: - Set of `LicenseChoice` - """ - return self._licenses - - @licenses.setter - def licenses(self, licenses: Iterable[License]) -> None: - self._licenses = LicenseRepository(licenses) - - @property - @serializable.xml_sequence(13) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def copyright(self) -> Optional[str]: - """ - An optional copyright notice informing users of the underlying claims to copyright ownership in a published - work. - - Returns: - `str` or `None` - """ - return self._copyright - - @copyright.setter - def copyright(self, copyright: Optional[str]) -> None: - self._copyright = copyright - - @property - @serializable.xml_sequence(14) - def cpe(self) -> Optional[str]: - """ - Specifies a well-formed CPE name that conforms to the CPE 2.2 or 2.3 specification. - See https://nvd.nist.gov/products/cpe - - Returns: - `str` if set else `None` - """ - return self._cpe - - @cpe.setter - def cpe(self, cpe: Optional[str]) -> None: - self._cpe = cpe - - @property - @serializable.type_mapping(PackageUrlSH) - @serializable.xml_sequence(15) - def purl(self) -> Optional[PackageURL]: - """ - Specifies the package-url (PURL). - - The purl, if specified, must be valid and conform to the specification defined at: - https://github.com/package-url/purl-spec - - Returns: - `PackageURL` or `None` - """ - return self._purl - - @purl.setter - def purl(self, purl: Optional[PackageURL]) -> None: - self._purl = purl - - @property - @serializable.json_name('omniborId') - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, child_name='omniborId') - @serializable.xml_sequence(16) - def omnibor_ids(self) -> 'SortedSet[OmniborId]': - """ - Specifies the OmniBOR Artifact ID. The OmniBOR, if specified, MUST be valid and conform to the specification - defined at: https://www.iana.org/assignments/uri-schemes/prov/gitoid - - Returns: - `Iterable[str]` or `None` - """ - - return self._omnibor_ids - - @omnibor_ids.setter - def omnibor_ids(self, omnibor_ids: Iterable[OmniborId]) -> None: - self._omnibor_ids = SortedSet(omnibor_ids) - - @property - @serializable.json_name('swhid') - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, child_name='swhid') - @serializable.xml_sequence(17) - def swhids(self) -> 'SortedSet[Swhid]': - """ - Specifies the Software Heritage persistent identifier (SWHID). The SWHID, if specified, MUST be valid and - conform to the specification defined at: - https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html - - Returns: - `Iterable[Swhid]` if set else `None` - """ - return self._swhids - - @swhids.setter - def swhids(self, swhids: Iterable[Swhid]) -> None: - self._swhids = SortedSet(swhids) - - @property - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(18) - def swid(self) -> Optional[Swid]: - """ - Specifies metadata and content for ISO-IEC 19770-2 Software Identification (SWID) Tags. - - Returns: - `Swid` if set else `None` - """ - return self._swid - - @swid.setter - def swid(self, swid: Optional[Swid]) -> None: - self._swid = swid - - @property - @serializable.view(SchemaVersion1Dot0) # todo: Deprecated in v1.3 - @serializable.xml_sequence(19) - def modified(self) -> bool: - return self._modified - - @modified.setter - def modified(self, modified: bool) -> None: - if modified: - warn('`@.modified` is deprecated from CycloneDX v1.3 onwards. ' - 'Please use `@.pedigree` instead.', DeprecationWarning) - self._modified = modified - - @property - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(20) - def pedigree(self) -> Optional[Pedigree]: - """ - Component pedigree is a way to document complex supply chain scenarios where components are created, - distributed, modified, redistributed, combined with other components, etc. - - Returns: - `Pedigree` if set else `None` - """ - return self._pedigree - - @pedigree.setter - def pedigree(self, pedigree: Optional[Pedigree]) -> None: - self._pedigree = pedigree - - @property - @serializable.view(SchemaVersion1Dot1) - @serializable.view(SchemaVersion1Dot2) - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(21) - def external_references(self) -> 'SortedSet[ExternalReference]': - """ - Provides the ability to document external references related to the component or to the project the component - describes. - - Returns: - Set of `ExternalReference` - """ - return self._external_references - - @external_references.setter - def external_references(self, external_references: Iterable[ExternalReference]) -> None: - self._external_references = SortedSet(external_references) - - @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(22) - def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Return: - Set of `Property` - """ - return self._properties - - @properties.setter - def properties(self, properties: Iterable[Property]) -> None: - self._properties = SortedSet(properties) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component') - @serializable.xml_sequence(23) - def components(self) -> "SortedSet['Component']": - """ - A list of software and hardware components included in the parent component. This is not a dependency tree. It - provides a way to specify a hierarchical representation of component assemblies, similar to system -> subsystem - -> parts assembly in physical supply chains. - - Returns: - Set of `Component` - """ - return self._components - - @components.setter - def components(self, components: Iterable['Component']) -> None: - self._components = SortedSet(components) - - @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(24) - @serializable.type_mapping(_ComponentEvidenceSerializationHelper) - def evidence(self) -> Optional[ComponentEvidence]: - """ - Provides the ability to document evidence collected through various forms of extraction or analysis. - - Returns: - `ComponentEvidence` if set else `None` - """ - return self._evidence - - @evidence.setter - def evidence(self, evidence: Optional[ComponentEvidence]) -> None: - self._evidence = evidence - - @property - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(25) - def release_notes(self) -> Optional[ReleaseNotes]: - """ - Specifies optional release notes. - - Returns: - `ReleaseNotes` or `None` - """ - return self._release_notes - - @release_notes.setter - def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None: - self._release_notes = release_notes - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(22) - # def model_card(self) -> ...: - # ... # TODO since CDX1.5 - # - # @model_card.setter - # def model_card(self, ...) -> None: - # ... # TODO since CDX1.5 - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(23) - # def data(self) -> ...: - # ... # TODO since CDX1.5 - # - # @data.setter - # def data(self, ...) -> None: - # ... # TODO since CDX1.5 - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(30) - def crypto_properties(self) -> Optional[CryptoProperties]: - """ - Cryptographic assets have properties that uniquely define them and that make them actionable for further - reasoning. As an example, it makes a difference if one knows the algorithm family (e.g. AES) or the specific - variant or instantiation (e.g. AES-128-GCM). This is because the security level and the algorithm primitive - (authenticated encryption) is only defined by the definition of the algorithm variant. The presence of a weak - cryptographic algorithm like SHA1 vs. HMAC-SHA1 also makes a difference. - - Returns: - `CryptoProperties` or `None` - """ - return self._crypto_properties - - @crypto_properties.setter - def crypto_properties(self, crypto_properties: Optional[CryptoProperties]) -> None: - self._crypto_properties = crypto_properties - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tag') - @serializable.xml_sequence(31) - def tags(self) -> 'SortedSet[str]': - """ - Textual strings that aid in discovery, search, and retrieval of the associated object. - Tags often serve as a way to group or categorize similar or related objects by various attributes. - - Returns: - `Iterable[str]` - """ - return self._tags - - @tags.setter - def tags(self, tags: Iterable[str]) -> None: - self._tags = SortedSet(tags) - def get_all_nested_components(self, include_self: bool = False) -> set['Component']: components = set() if include_self: @@ -1676,36 +700,75 @@ def get_pypi_url(self) -> str: else: return f'https://pypi.org/project/{self.name}' - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, self.group, self.name, self.version, - self.bom_ref.value, - None if self.purl is None else _ComparablePackageURL(self.purl), - self.swid, self.cpe, _ComparableTuple(self.swhids), - self.supplier, self.author, self.publisher, - self.description, - self.mime_type, self.scope, _ComparableTuple(self.hashes), - _ComparableTuple(self.licenses), self.copyright, - self.pedigree, - _ComparableTuple(self.external_references), _ComparableTuple(self.properties), - _ComparableTuple(self.components), self.evidence, self.release_notes, self.modified, - _ComparableTuple(self.authors), _ComparableTuple(self.omnibor_ids), self.manufacturer, - self.crypto_properties, _ComparableTuple(self.tags), - )) - def __eq__(self, other: object) -> bool: if isinstance(other, Component): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + return ( + self.type, self.group, self.name, self.version, self.bom_ref.value, + None if self.purl is None else str(self.purl), + self.swid, self.cpe, tuple(self.swhids), self.supplier, self.author, + self.publisher, self.description, self.mime_type, self.scope, + tuple(self.hashes), tuple(self.licenses), self.copyright, self.pedigree, + tuple(self.external_references), tuple(self.properties), + tuple(self.components), self.evidence, self.release_notes, self.modified, + tuple(self.authors), tuple(self.omnibor_ids), self.manufacturer, + self.crypto_properties, tuple(self.tags) + ) == ( + other.type, other.group, other.name, other.version, other.bom_ref.value, + None if other.purl is None else str(other.purl), + other.swid, other.cpe, tuple(other.swhids), other.supplier, other.author, + other.publisher, other.description, other.mime_type, other.scope, + tuple(other.hashes), tuple(other.licenses), other.copyright, other.pedigree, + tuple(other.external_references), tuple(other.properties), + tuple(other.components), other.evidence, other.release_notes, other.modified, + tuple(other.authors), tuple(other.omnibor_ids), other.manufacturer, + other.crypto_properties, tuple(other.tags) + ) + return NotImplemented + + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Component): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return ( + c(self.type), c(self.group), self.name, c(self.version), c(self.bom_ref.value), + c(None if self.purl is None else _ComparablePackageURL(self.purl)), + c(self.swid), c(self.cpe), tuple(self.swhids), c(self.supplier), c(self.author), + c(self.publisher), c(self.description), c(self.mime_type), c(self.scope), + tuple(self.hashes), tuple(self.licenses), c(self.copyright), c(self.pedigree), + tuple(self.external_references), tuple(self.properties), + tuple(self.components), c(self.evidence), c(self.release_notes), c(self.modified), + tuple(self.authors), tuple(self.omnibor_ids), c(self.manufacturer), + c(self.crypto_properties), tuple(self.tags) + ) < ( + c(other.type), c(other.group), other.name, c(other.version), c(other.bom_ref.value), + c(None if other.purl is None else _ComparablePackageURL(other.purl)), + c(other.swid), c(other.cpe), tuple(other.swhids), c(other.supplier), c(other.author), + c(other.publisher), c(other.description), c(other.mime_type), c(other.scope), + tuple(other.hashes), tuple(other.licenses), c(other.copyright), c(other.pedigree), + tuple(other.external_references), tuple(other.properties), + tuple(other.components), c(other.evidence), c(other.release_notes), c(other.modified), + tuple(other.authors), tuple(other.omnibor_ids), c(other.manufacturer), + c(other.crypto_properties), tuple(other.tags) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.type, self.group, self.name, self.version, self.bom_ref.value, + None if self.purl is None else str(self.purl), + self.swid, self.cpe, tuple(self.swhids), self.supplier, self.author, + self.publisher, self.description, self.mime_type, self.scope, + tuple(self.hashes), tuple(self.licenses), self.copyright, self.pedigree, + tuple(self.external_references), tuple(self.properties), + tuple(self.components), self.evidence, self.release_notes, self.modified, + tuple(self.authors), tuple(self.omnibor_ids), self.manufacturer, + self.crypto_properties, tuple(self.tags) + )) def __repr__(self) -> str: - return f'' + return (f'') diff --git a/cyclonedx/model/component_evidence.py b/cyclonedx/model/component_evidence.py index f68956b35..13a0fe801 100644 --- a/cyclonedx/model/component_evidence.py +++ b/cyclonedx/model/component_evidence.py @@ -19,25 +19,27 @@ from collections.abc import Iterable from decimal import Decimal from enum import Enum -from json import loads as json_loads from typing import Any, List, Optional, Union -from warnings import warn -from xml.etree.ElementTree import Element as XmlElement # nosec B405 -# See https://github.com/package-url/packageurl-python/issues/65 -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str -from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import InvalidConfidenceException, InvalidValueException -from ..schema.schema import SchemaVersion1Dot5, SchemaVersion1Dot6, SchemaVersion1Dot7 +from ..serialization import ( + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_5_AND_LATER, + VERSIONS_1_6_AND_LATER, +) from . import Copyright from .bom_ref import BomRef -from .license import License, LicenseRepository, _LicenseRepositorySerializationHelper +from .license import License, LicenseRepository -@serializable.serializable_enum class IdentityField(str, Enum): """ Enum object that defines the permissible field types for Identity. @@ -57,7 +59,6 @@ class IdentityField(str, Enum): HASH = 'hash' -@serializable.serializable_enum class AnalysisTechnique(str, Enum): """ Enum object that defines the permissible analysis techniques. @@ -75,7 +76,46 @@ class AnalysisTechnique(str, Enum): OTHER = 'other' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _validate_confidence(instance: Any, attribute: attrs.Attribute, value: Optional[Decimal]) -> None: + """Validator for confidence field.""" + if value is not None and not (0 <= value <= 1): + raise InvalidConfidenceException(f'confidence {value!r} is invalid') + + +def _validate_line(instance: Any, attribute: attrs.Attribute, value: Optional[int]) -> None: + """Validator for line field.""" + if value is not None and value < 0: + raise InvalidValueException(f'line {value!r} must not be lower than zero') + + +def _validate_offset(instance: Any, attribute: attrs.Attribute, value: Optional[int]) -> None: + """Validator for offset field.""" + if value is not None and value < 0: + raise InvalidValueException(f'offset {value!r} must not be lower than zero') + + +def _sortedset_factory() -> SortedSet: + return SortedSet() + + +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + # Handle single objects that aren't iterable sequences + if hasattr(value, '__iter__') and not isinstance(value, (str, bytes)): + return SortedSet(value) + # Wrap single object in a list + return SortedSet([value]) + + +def _bom_ref_converter(value: Optional[Union[str, BomRef]]) -> BomRef: + """Convert string or BomRef to BomRef.""" + return _bom_ref_from_str(value) + + +@attrs.define class Method: """ Represents a method used to extract and/or analyze evidence. @@ -84,108 +124,32 @@ class Method: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_evidence_identity_oneOf_i0_items_methods """ - - def __init__( - self, *, - technique: AnalysisTechnique, - confidence: Decimal, - value: Optional[str] = None, - ) -> None: - self.technique = technique - self.confidence = confidence - self.value = value - - @property - @serializable.xml_sequence(1) - def technique(self) -> AnalysisTechnique: - return self._technique - - @technique.setter - def technique(self, technique: AnalysisTechnique) -> None: - self._technique = technique - - @property - @serializable.xml_sequence(2) - def confidence(self) -> Decimal: - """ - The confidence of the evidence from 0 - 1, where 1 is 100% confidence. - Confidence is specific to the technique used. Each technique of analysis can have independent confidence. - """ - return self._confidence - - @confidence.setter - def confidence(self, confidence: Decimal) -> None: - if not (0 <= confidence <= 1): - raise InvalidConfidenceException(f'confidence {confidence!r} is invalid') - self._confidence = confidence - - @property - @serializable.xml_sequence(3) - def value(self) -> Optional[str]: - return self._value - - @value.setter - def value(self, value: Optional[str]) -> None: - self._value = value - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.technique, - self.confidence, - self.value, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Method): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + technique: AnalysisTechnique = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + confidence: Decimal = attrs.field( + validator=_validate_confidence, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + value: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) def __lt__(self, other: Any) -> bool: if isinstance(other, Method): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.technique, self.confidence, self.value) < ( + other.technique, other.confidence, other.value) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.technique, self.confidence, self.value)) def __repr__(self) -> str: return f'' -class _IdentityToolRepositorySerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - @classmethod - def json_serialize(cls, o: Iterable['BomRef']) -> list[str]: - return [t.value for t in o if t.value] - - @classmethod - def json_deserialize(cls, o: Iterable[str]) -> list[BomRef]: - return [BomRef(value=t) for t in o] - - @classmethod - def xml_normalize(cls, o: Iterable[BomRef], *, - xmlns: Optional[str], - **kwargs: Any) -> Optional[XmlElement]: - o = tuple(o) - if len(o) == 0: - return None - elem_s = XmlElement(f'{{{xmlns}}}tools' if xmlns else 'tools') - tool_name = f'{{{xmlns}}}tool' if xmlns else 'tool' - ref_name = f'{{{xmlns}}}ref' if xmlns else 'ref' - elem_s.extend( - XmlElement(tool_name, {ref_name: t.value}) - for t in o if t.value) - return elem_s - - @classmethod - def xml_denormalize(cls, o: 'XmlElement', *, - default_ns: Optional[str], - **__: Any) -> list[BomRef]: - return [BomRef(value=t.get('ref')) for t in o] - - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Identity: """ Our internal representation of the `identityType` complex type. @@ -193,107 +157,56 @@ class Identity: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_evidence_identity """ - - def __init__( - self, *, - field: IdentityField, - confidence: Optional[Decimal] = None, - concluded_value: Optional[str] = None, - methods: Optional[Iterable[Method]] = None, - tools: Optional[Iterable[BomRef]] = None, - ) -> None: - self.field = field - self.confidence = confidence - self.concluded_value = concluded_value - self.methods = methods or [] - self.tools = tools or [] - - @property - @serializable.xml_sequence(1) - def field(self) -> IdentityField: - return self._field - - @field.setter - def field(self, field: IdentityField) -> None: - self._field = field - - @property - @serializable.xml_sequence(2) - def confidence(self) -> Optional[Decimal]: - """ - The overall confidence of the evidence from 0 - 1, where 1 is 100% confidence. - """ - return self._confidence - - @confidence.setter - def confidence(self, confidence: Optional[Decimal]) -> None: - if confidence is not None and not (0 <= confidence <= 1): - raise InvalidConfidenceException(f'{confidence} in invalid') - self._confidence = confidence - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(3) - def concluded_value(self) -> Optional[str]: - return self._concluded_value - - @concluded_value.setter - def concluded_value(self, concluded_value: Optional[str]) -> None: - self._concluded_value = concluded_value - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'method') - @serializable.xml_sequence(4) - def methods(self) -> 'SortedSet[Method]': - return self._methods - - @methods.setter - def methods(self, methods: Iterable[Method]) -> None: - self._methods = SortedSet(methods) - - @property - @serializable.type_mapping(_IdentityToolRepositorySerializationHelper) - @serializable.xml_sequence(5) - def tools(self) -> 'SortedSet[BomRef]': - """ - References to the tools used to perform analysis and collect evidence. - """ - return self._tools - - @tools.setter - def tools(self, tools: Iterable[BomRef]) -> None: - self._tools = SortedSet(tools) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.field, - self.confidence, - self.concluded_value, - _ComparableTuple(self.methods), - _ComparableTuple(self.tools), - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Identity): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + field: IdentityField = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + confidence: Optional[Decimal] = attrs.field( + default=None, + validator=attrs.validators.optional(_validate_confidence), + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + concluded_value: Optional[str] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 3, + } + ) + methods: 'SortedSet[Method]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + tools: 'SortedSet[BomRef]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) def __lt__(self, other: Any) -> bool: if isinstance(other, Identity): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + self.field, self.confidence, self.concluded_value, + tuple(self.methods), tuple(self.tools) + ) < ( + other.field, other.confidence, other.concluded_value, + tuple(other.methods), tuple(other.tools) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.field, self.confidence, self.concluded_value, + tuple(self.methods), tuple(self.tools) + )) def __repr__(self) -> str: - return f'' + return (f'') -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Occurrence: """ Our internal representation of the `occurrenceType` complex type. @@ -301,138 +214,71 @@ class Occurrence: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_evidence_occurrences """ - - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - location: str, - line: Optional[int] = None, - offset: Optional[int] = None, - symbol: Optional[str] = None, - additional_context: Optional[str] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.location = location - self.line = line - self.offset = offset - self.symbol = symbol - self.additional_context = additional_context - - @property - @serializable.type_mapping(BomRef) - @serializable.json_name('bom-ref') - @serializable.xml_name('bom-ref') - @serializable.xml_attribute() - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the requirement elsewhere in the BOM. - Every bom-ref MUST be unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_sequence(1) - def location(self) -> str: - """ - Location can be a file path, URL, or a unique identifier from a component discovery tool - """ - return self._location - - @location.setter - def location(self, location: str) -> None: - self._location = location - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(2) - def line(self) -> Optional[int]: - """ - The line number in the file where the dependency or reference was detected. - """ - return self._line - - @line.setter - def line(self, line: Optional[int]) -> None: - if line is not None and line < 0: - raise InvalidValueException(f'line {line!r} must not be lower than zero') - self._line = line - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(3) - def offset(self) -> Optional[int]: - """ - The offset location within the file where the dependency or reference was detected. - """ - return self._offset - - @offset.setter - def offset(self, offset: Optional[int]) -> None: - if offset is not None and offset < 0: - raise InvalidValueException(f'offset {offset!r} must not be lower than zero') - self._offset = offset - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(4) - def symbol(self) -> Optional[str]: - """ - Programming language symbol or import name. - """ - return self._symbol - - @symbol.setter - def symbol(self, symbol: Optional[str]) -> None: - self._symbol = symbol - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(5) - def additional_context(self) -> Optional[str]: - """ - Additional context about the occurrence of the component. - """ - return self._additional_context - - @additional_context.setter - def additional_context(self, additional_context: Optional[str]) -> None: - self._additional_context = additional_context - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.bom_ref, - self.location, - self.line, - self.offset, - self.symbol, - self.additional_context, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Occurrence): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + location: str = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_JSON_NAME: 'bom-ref', + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_XML_ATTR: True, + } + ) + line: Optional[int] = attrs.field( + default=None, + validator=attrs.validators.optional(_validate_line), + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 2, + } + ) + offset: Optional[int] = attrs.field( + default=None, + validator=attrs.validators.optional(_validate_offset), + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 3, + } + ) + symbol: Optional[str] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 4, + } + ) + additional_context: Optional[str] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 5, + } + ) def __lt__(self, other: Any) -> bool: if isinstance(other, Occurrence): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + self.bom_ref, self.location, self.line, self.offset, + self.symbol, self.additional_context + ) < ( + other.bom_ref, other.location, other.line, other.offset, + other.symbol, other.additional_context + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.bom_ref, self.location, self.line, self.offset, + self.symbol, self.additional_context + )) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class CallStackFrame: """ Represents an individual frame in a call stack. @@ -440,148 +286,59 @@ class CallStackFrame: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_evidence_callstack """ - - def __init__( - self, *, - module: str, - package: Optional[str] = None, - function: Optional[str] = None, - parameters: Optional[Iterable[str]] = None, - line: Optional[int] = None, - column: Optional[int] = None, - full_filename: Optional[str] = None, - ) -> None: - self.package = package - self.module = module - self.function = function - self.parameters = parameters or [] - self.line = line - self.column = column - self.full_filename = full_filename - - @property - @serializable.xml_sequence(1) - def package(self) -> Optional[str]: - """ - The package name. - """ - return self._package - - @package.setter - def package(self, package: Optional[str]) -> None: - """ - Sets the package name. - """ - self._package = package - - @property - @serializable.xml_sequence(2) - def module(self) -> str: - """ - The module name - """ - return self._module - - @module.setter - def module(self, module: str) -> None: - self._module = module - - @property - @serializable.xml_sequence(3) - def function(self) -> Optional[str]: - """ - The function name. - """ - return self._function - - @function.setter - def function(self, function: Optional[str]) -> None: - """ - Sets the function name. - """ - self._function = function - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'parameter') - @serializable.xml_sequence(4) - def parameters(self) -> 'SortedSet[str]': - """ - Function parameters - """ - return self._parameters - - @parameters.setter - def parameters(self, parameters: Iterable[str]) -> None: - self._parameters = SortedSet(parameters) - - @property - @serializable.xml_sequence(5) - def line(self) -> Optional[int]: - """ - The line number - """ - return self._line - - @line.setter - def line(self, line: Optional[int]) -> None: - self._line = line - - @property - @serializable.xml_sequence(6) - def column(self) -> Optional[int]: - """ - The column number - """ - return self._column - - @column.setter - def column(self, column: Optional[int]) -> None: - self._column = column - - @property - @serializable.xml_sequence(7) - def full_filename(self) -> Optional[str]: - """ - The full file path - """ - return self._full_filename - - @full_filename.setter - def full_filename(self, full_filename: Optional[str]) -> None: - self._full_filename = full_filename - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.package, - self.module, - self.function, - _ComparableTuple(self.parameters), - self.line, - self.column, - self.full_filename, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, CallStackFrame): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + module: str = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + package: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + function: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + parameters: 'SortedSet[str]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + line: Optional[int] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) + column: Optional[int] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 6} + ) + full_filename: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 7} + ) def __lt__(self, other: object) -> bool: if isinstance(other, CallStackFrame): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + self.package, self.module, self.function, tuple(self.parameters), + self.line, self.column, self.full_filename + ) < ( + other.package, other.module, other.function, tuple(other.parameters), + other.line, other.column, other.full_filename + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.package, self.module, self.function, tuple(self.parameters), + self.line, self.column, self.full_filename + )) def __repr__(self) -> str: - return '' + return (f'') -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class CallStack: """ Our internal representation of the `callStackType` complex type. @@ -590,53 +347,38 @@ class CallStack: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_evidence_callstack """ - - def __init__( - self, *, - frames: Optional[Iterable[CallStackFrame]] = None, - ) -> None: - self.frames = frames or [] - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'frame') - @serializable.xml_sequence(1) - def frames(self) -> 'List[CallStackFrame]': - """ - Array of stack frames - """ - return self._frames - - @frames.setter - def frames(self, frames: Iterable[CallStackFrame]) -> None: - self._frames = list(frames) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self.frames), - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, CallStack): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + frames: list[CallStackFrame] = attrs.field( + factory=list, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) def __lt__(self, other: Any) -> bool: if isinstance(other, CallStack): - return self.__comparable_tuple() < other.__comparable_tuple() + return tuple(self.frames) < tuple(other.frames) return NotImplemented def __hash__(self) -> int: - h = self.__comparable_tuple() - try: - return hash(h) - except TypeError as e: - raise e + return hash(tuple(self.frames)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _license_repository_factory() -> LicenseRepository: + return LicenseRepository() + + +def _license_repository_converter(value: Any) -> LicenseRepository: + """Convert a value to LicenseRepository.""" + if value is None: + return LicenseRepository() + if isinstance(value, LicenseRepository): + return value + # Convert generators, lists, etc. to LicenseRepository + return LicenseRepository(value) + + +@attrs.define class ComponentEvidence: """ Our internal representation of the `componentEvidenceType` complex type. @@ -646,171 +388,56 @@ class ComponentEvidence: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_componentEvidenceType """ - - def __init__( - self, *, - identity: Optional[Union[Iterable[Identity], Identity]] = None, - occurrences: Optional[Iterable[Occurrence]] = None, - callstack: Optional[CallStack] = None, - licenses: Optional[Iterable[License]] = None, - copyright: Optional[Iterable[Copyright]] = None, - ) -> None: - self.identity = identity or [] - self.occurrences = occurrences or [] - self.callstack = callstack - self.licenses = licenses or [] - self.copyright = copyright or [] - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(1) - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'identity') - def identity(self) -> 'SortedSet[Identity]': - """ - Provides a way to identify components via various methods. - Returns SortedSet of identities. - """ - return self._identity - - @identity.setter - def identity(self, identity: Union[Iterable[Identity], Identity]) -> None: - self._identity = SortedSet( - (identity,) - if isinstance(identity, Identity) - else identity - ) - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'occurrence') - @serializable.xml_sequence(2) - def occurrences(self) -> 'SortedSet[Occurrence]': - """A list of locations where evidence was obtained from.""" - return self._occurrences - - @occurrences.setter - def occurrences(self, occurrences: Iterable[Occurrence]) -> None: - self._occurrences = SortedSet(occurrences) - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(3) - def callstack(self) -> Optional[CallStack]: - """ - A representation of a call stack from when the component was identified. - """ - return self._callstack - - @callstack.setter - def callstack(self, callstack: Optional[CallStack]) -> None: - self._callstack = callstack - - @property - @serializable.type_mapping(_LicenseRepositorySerializationHelper) - @serializable.xml_sequence(4) - def licenses(self) -> LicenseRepository: - """ - Optional list of licenses obtained during analysis. - - Returns: - Set of `LicenseChoice` - """ - return self._licenses - - @licenses.setter - def licenses(self, licenses: Iterable[License]) -> None: - self._licenses = LicenseRepository(licenses) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'text') - @serializable.xml_sequence(5) - def copyright(self) -> 'SortedSet[Copyright]': - """ - Optional list of copyright statements. - - Returns: - Set of `Copyright` - """ - return self._copyright - - @copyright.setter - def copyright(self, copyright: Iterable[Copyright]) -> None: - self._copyright = SortedSet(copyright) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self.licenses), - _ComparableTuple(self.copyright), - self.callstack, - _ComparableTuple(self.identity), - _ComparableTuple(self.occurrences), - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, ComponentEvidence): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + identity: 'SortedSet[Identity]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 1, + } + ) + occurrences: 'SortedSet[Occurrence]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 2, + } + ) + callstack: Optional[CallStack] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 3, + } + ) + licenses: LicenseRepository = attrs.field( + factory=_license_repository_factory, + converter=_license_repository_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + copyright: 'SortedSet[Copyright]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) def __lt__(self, other: object) -> bool: if isinstance(other, ComponentEvidence): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + tuple(self.licenses), tuple(self.copyright), self.callstack, + tuple(self.identity), tuple(self.occurrences) + ) < ( + tuple(other.licenses), tuple(other.copyright), other.callstack, + tuple(other.identity), tuple(other.occurrences) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + tuple(self.licenses), tuple(self.copyright), self.callstack, + tuple(self.identity), tuple(self.occurrences) + )) def __repr__(self) -> str: return f'' - - -class _ComponentEvidenceSerializationHelper(serializable.helpers.BaseHelper): - """THIS CLASS IS NON-PUBLIC API - - This helper takes care of :attr:`ComponentEvidence.identity`. - """ - - @classmethod - def json_normalize(cls, o: ComponentEvidence, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> dict[str, Any]: - data: dict[str, Any] = json_loads(o.as_json(view)) # type:ignore[attr-defined] - if view is SchemaVersion1Dot5: - identities = data.get('identity', []) - if identities: - if (il := len(identities)) > 1: - warn(f'CycloneDX 1.5 does not support multiple identity items; dropping {il - 1} items.') - data['identity'] = identities[0] - return data - - @classmethod - def json_denormalize(cls, o: dict[str, Any], **__: Any) -> Any: - if isinstance(identity := o.get('identity'), dict): - o = {**o, 'identity': [identity]} - return ComponentEvidence.from_json(o) # type:ignore[attr-defined] - - @classmethod - def xml_normalize(cls, o: ComponentEvidence, *, - element_name: str, - view: Optional[type['serializable.ViewType']], - xmlns: Optional[str], - **__: Any) -> Optional['XmlElement']: - normalized: 'XmlElement' = o.as_xml(view, False, element_name, xmlns) # type:ignore[attr-defined] - if view is SchemaVersion1Dot5: - identities = normalized.findall(f'./{{{xmlns}}}identity' if xmlns else './identity') - if (il := len(identities)) > 1: - warn(f'CycloneDX 1.5 does not support multiple identity items; dropping {il - 1} items.') - for i in identities[1:]: - normalized.remove(i) - return normalized - - @classmethod - def xml_denormalize(cls, o: 'XmlElement', *, - default_ns: Optional[str], - **__: Any) -> Any: - return ComponentEvidence.from_xml(o, default_ns) # type:ignore[attr-defined] diff --git a/cyclonedx/model/contact.py b/cyclonedx/model/contact.py index cb26af212..a1c7d2d88 100644 --- a/cyclonedx/model/contact.py +++ b/cyclonedx/model/contact.py @@ -19,17 +19,46 @@ from collections.abc import Iterable from typing import Any, Optional, Union -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str from .._internal.compare import ComparableTuple as _ComparableTuple -from ..schema.schema import SchemaVersion1Dot5, SchemaVersion1Dot6, SchemaVersion1Dot7 +from ..serialization import ( + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_5_AND_LATER, + VERSIONS_1_6_AND_LATER, +) from . import XsUri from .bom_ref import BomRef -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _bom_ref_converter(value: Optional[Union[str, BomRef]]) -> BomRef: + """Convert string or BomRef to BomRef.""" + return _bom_ref_from_str(value) + + +def _sortedset_factory() -> SortedSet: + """Factory for creating empty SortedSet.""" + return SortedSet() + + +def _sortedset_converter(value: Any) -> SortedSet: + """Convert a value to SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) + + +@attrs.define class PostalAddress: """ This is our internal representation of the `postalAddressType` complex type that can be used in multiple places @@ -38,156 +67,68 @@ class PostalAddress: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_postalAddressType """ - - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - country: Optional[str] = None, - region: Optional[str] = None, - locality: Optional[str] = None, - post_office_box_number: Optional[str] = None, - postal_code: Optional[str] = None, - street_address: Optional[str] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.country = country - self.region = region - self.locality = locality - self.post_office_box_number = post_office_box_number - self.postal_code = postal_code - self.street_address = street_address - - @property - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - @serializable.json_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_sequence(10) - def country(self) -> Optional[str]: - """ - The country name or the two-letter ISO 3166-1 country code. - - Returns: - `str` or `None` - """ - return self._country - - @country.setter - def country(self, country: Optional[str]) -> None: - self._country = country - - @property - @serializable.xml_sequence(20) - def region(self) -> Optional[str]: - """ - The region or state in the country. For example, Texas. - - Returns: - `str` or `None` - """ - return self._region - - @region.setter - def region(self, region: Optional[str]) -> None: - self._region = region - - @property - @serializable.xml_sequence(30) - def locality(self) -> Optional[str]: - """ - The locality or city within the country. For example, Austin. - - Returns: - `str` or `None` - """ - return self._locality - - @locality.setter - def locality(self, locality: Optional[str]) -> None: - self._locality = locality - - @property - @serializable.xml_sequence(40) - def post_office_box_number(self) -> Optional[str]: - """ - The post office box number. For example, 901. - - Returns: - `str` or `None` - """ - return self._post_office_box_number - - @post_office_box_number.setter - def post_office_box_number(self, post_office_box_number: Optional[str]) -> None: - self._post_office_box_number = post_office_box_number - - @property - @serializable.xml_sequence(60) - def postal_code(self) -> Optional[str]: - """ - The postal code. For example, 78758. - - Returns: - `str` or `None` - """ - return self._postal_code - - @postal_code.setter - def postal_code(self, postal_code: Optional[str]) -> None: - self._postal_code = postal_code - - @property - @serializable.xml_sequence(70) - def street_address(self) -> Optional[str]: - """ - The street address. For example, 100 Main Street. - - Returns: - `str` or `None` - """ - return self._street_address - - @street_address.setter - def street_address(self, street_address: Optional[str]) -> None: - self._street_address = street_address - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.country, self.region, self.locality, self.postal_code, - self.post_office_box_number, - self.street_address, - self._bom_ref.value, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, PostalAddress): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_JSON_NAME: 'bom-ref', + } + ) + country: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 10} + ) + region: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 20} + ) + locality: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 30} + ) + post_office_box_number: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 40} + ) + postal_code: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 60} + ) + street_address: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 70} + ) + + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, PostalAddress): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return ( + c(self.country), c(self.region), c(self.locality), c(self.postal_code), + c(self.post_office_box_number), c(self.street_address), c(self.bom_ref.value) + ) < ( + c(other.country), c(other.region), c(other.locality), c(other.postal_code), + c(other.post_office_box_number), c(other.street_address), c(other.bom_ref.value) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.country, self.region, self.locality, self.postal_code, + self.post_office_box_number, self.street_address, self.bom_ref.value + )) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class OrganizationalContact: """ This is our internal representation of the `organizationalContact` complex type that can be used in multiple places @@ -196,109 +137,54 @@ class OrganizationalContact: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_organizationalContact """ - - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - name: Optional[str] = None, - phone: Optional[str] = None, - email: Optional[str] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.name = name - self.email = email - self.phone = phone - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - @serializable.json_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - Get the name of the contact. - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.xml_sequence(2) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def email(self) -> Optional[str]: - """ - Get the email of the contact. - - Returns: - `str` if set else `None` - """ - return self._email - - @email.setter - def email(self, email: Optional[str]) -> None: - self._email = email - - @property - @serializable.xml_sequence(3) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def phone(self) -> Optional[str]: - """ - Get the phone of the contact. - - Returns: - `str` if set else `None` - """ - return self._phone - - @phone.setter - def phone(self, phone: Optional[str]) -> None: - self._phone = phone - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, self.email, self.phone, - self._bom_ref.value, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, OrganizationalContact): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_JSON_NAME: 'bom-ref', + } + ) + name: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + email: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + phone: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, OrganizationalContact): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.name), self._cmp(self.email), self._cmp(self.phone), + self._cmp(self.bom_ref.value)) < ( + self._cmp(other.name), self._cmp(other.email), self._cmp(other.phone), + self._cmp(other.bom_ref.value)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.name, self.email, self.phone, self.bom_ref.value)) def __repr__(self) -> str: return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _sortedset_factory() -> SortedSet: + return SortedSet() + + +@attrs.define class OrganizationalEntity: """ This is our internal representation of the `organizationalEntity` complex type that can be used in multiple places @@ -307,124 +193,69 @@ class OrganizationalEntity: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_organizationalEntity """ - - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - name: Optional[str] = None, - urls: Optional[Iterable[XsUri]] = None, - contacts: Optional[Iterable[OrganizationalContact]] = None, - address: Optional[PostalAddress] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.name = name - self.address = address - self.urls = urls or [] - self.contacts = contacts or [] - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - @serializable.json_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_sequence(10) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - Get the name of the organization. - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(20) - def address(self) -> Optional[PostalAddress]: - """ - The physical address (location) of the organization. - - Returns: - `PostalAddress` or `None` - """ - return self._address - - @address.setter - def address(self, address: Optional[PostalAddress]) -> None: - self._address = address - - @property - @serializable.json_name('url') - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'url') - @serializable.xml_sequence(30) - def urls(self) -> 'SortedSet[XsUri]': - """ - Get a list of URLs of the organization. Multiple URLs are allowed. - - Returns: - Set of `XsUri` - """ - return self._urls - - @urls.setter - def urls(self, urls: Iterable[XsUri]) -> None: - self._urls = SortedSet(urls) - - @property - @serializable.json_name('contact') - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'contact') - @serializable.xml_sequence(40) - def contacts(self) -> 'SortedSet[OrganizationalContact]': - """ - Get a list of contact person at the organization. Multiple contacts are allowed. - - Returns: - Set of `OrganizationalContact` - """ - return self._contacts - - @contacts.setter - def contacts(self, contacts: Iterable[OrganizationalContact]) -> None: - self._contacts = SortedSet(contacts) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, _ComparableTuple(self.urls), _ComparableTuple(self.contacts), - self._bom_ref.value, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, OrganizationalEntity): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_JSON_NAME: 'bom-ref', + } + ) + name: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 10} + ) + address: Optional[PostalAddress] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 20, + } + ) + urls: 'SortedSet[XsUri]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_JSON_NAME: 'url', + METADATA_KEY_XML_SEQUENCE: 30, + } + ) + contacts: 'SortedSet[OrganizationalContact]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_JSON_NAME: 'contact', + METADATA_KEY_XML_SEQUENCE: 40, + } + ) + + @urls.validator + def _validate_urls(self, attribute: attrs.Attribute, value: Any) -> None: + if value is not None and not isinstance(value, SortedSet): + object.__setattr__(self, 'urls', SortedSet(value)) + + @contacts.validator + def _validate_contacts(self, attribute: attrs.Attribute, value: Any) -> None: + if value is not None and not isinstance(value, SortedSet): + object.__setattr__(self, 'contacts', SortedSet(value)) + + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, OrganizationalEntity): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.name), tuple(self.urls), tuple(self.contacts), + self._cmp(self.bom_ref.value)) < ( + self._cmp(other.name), tuple(other.urls), tuple(other.contacts), + self._cmp(other.bom_ref.value)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.name, tuple(self.urls), tuple(self.contacts), self.bom_ref.value)) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/crypto.py b/cyclonedx/model/crypto.py index a3d32d0ea..339fd8daa 100644 --- a/cyclonedx/model/crypto.py +++ b/cyclonedx/model/crypto.py @@ -30,25 +30,29 @@ from enum import Enum from typing import Any, Optional -import py_serializable as serializable +from attrs import Factory, define, field from sortedcontainers import SortedSet from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import InvalidNistQuantumSecurityLevelException, InvalidRelatedCryptoMaterialSizeException -from ..schema.schema import SchemaVersion1Dot6, SchemaVersion1Dot7 +from ..schema import SchemaVersion from .bom_ref import BomRef -@serializable.serializable_enum +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + return SortedSet(value) + + class CryptoAssetType(str, Enum): """ This is our internal representation of the cryptoPropertiesType.assetType ENUM type within the CycloneDX standard. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ ALGORITHM = 'algorithm' @@ -57,17 +61,12 @@ class CryptoAssetType(str, Enum): RELATED_CRYPTO_MATERIAL = 'related-crypto-material' -@serializable.serializable_enum class CryptoPrimitive(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.primitive ENUM type within the - CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.primitive ENUM type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ AE = 'ae' @@ -88,85 +87,69 @@ class CryptoPrimitive(str, Enum): UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoExecutionEnvironment(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.executionEnvironment ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.executionEnvironment ENUM type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - HARDWARE = 'hardware' - SOFTWARE_ENCRYPTED_RAM = 'software-encrypted-ram' SOFTWARE_PLAIN_RAM = 'software-plain-ram' + SOFTWARE_ENCRYPTED_RAM = 'software-encrypted-ram' SOFTWARE_TEE = 'software-tee' + HARDWARE = 'hardware' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoImplementationPlatform(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.implementationPlatform ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.implementationPlatform ENUM. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - ARMV7_A = 'armv7-a' - ARMV7_M = 'armv7-m' - ARMV8_A = 'armv8-a' - ARMV8_M = 'armv8-m' - ARMV9_A = 'armv9-a' - ARMV9_M = 'armv9-m' GENERIC = 'generic' - PPC64 = 'ppc64' - PPC64LE = 'ppc64le' - S390X = 's390x' X86_32 = 'x86_32' X86_64 = 'x86_64' + ARM_V7_A = 'armv7-a' + ARM_V7_M = 'armv7-m' + ARM_V8_A = 'armv8-a' + ARM_V8_M = 'armv8-m' + ARM_V9_A = 'armv9-a' + ARM_V9_M = 'armv9-m' + S390X = 's390x' + PPC64 = 'ppc64' + PPC64LE = 'ppc64le' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoCertificationLevel(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.certificationLevel ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.certificationLevel ENUM. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ NONE = 'none' - - FIPS140_1_L1 = 'fips140-1-l1' - FIPS140_1_L2 = 'fips140-1-l2' - FIPS140_1_L3 = 'fips140-1-l3' - FIPS140_1_L4 = 'fips140-1-l4' - FIPS140_2_L1 = 'fips140-2-l1' - FIPS140_2_L2 = 'fips140-2-l2' - FIPS140_2_L3 = 'fips140-2-l3' - FIPS140_2_L4 = 'fips140-2-l4' - FIPS140_3_L1 = 'fips140-3-l1' - FIPS140_3_L2 = 'fips140-3-l2' - FIPS140_3_L3 = 'fips140-3-l3' - FIPS140_3_L4 = 'fips140-3-l4' + FIPS_140_1_L1 = 'fips140-1-l1' + FIPS_140_1_L2 = 'fips140-1-l2' + FIPS_140_1_L3 = 'fips140-1-l3' + FIPS_140_1_L4 = 'fips140-1-l4' + FIPS_140_2_L1 = 'fips140-2-l1' + FIPS_140_2_L2 = 'fips140-2-l2' + FIPS_140_2_L3 = 'fips140-2-l3' + FIPS_140_2_L4 = 'fips140-2-l4' + FIPS_140_3_L1 = 'fips140-3-l1' + FIPS_140_3_L2 = 'fips140-3-l2' + FIPS_140_3_L3 = 'fips140-3-l3' + FIPS_140_3_L4 = 'fips140-3-l4' CC_EAL1 = 'cc-eal1' CC_EAL1_PLUS = 'cc-eal1+' CC_EAL2 = 'cc-eal2' @@ -186,47 +169,37 @@ class CryptoCertificationLevel(str, Enum): UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoMode(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.mode ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.mode ENUM type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ CBC = 'cbc' - CCM = 'ccm' - CFB = 'cfb' - CTR = 'ctr' ECB = 'ecb' + CCM = 'ccm' GCM = 'gcm' + CFB = 'cfb' OFB = 'ofb' + CTR = 'ctr' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoPadding(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.padding ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.padding ENUM type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ PKCS5 = 'pkcs5' PKCS7 = 'pkcs7' - PKCS1V15 = 'pkcs1v15' + PKCS1_V15 = 'pkcs1v15' OAEP = 'oaep' RAW = 'raw' @@ -234,177 +207,109 @@ class CryptoPadding(str, Enum): UNKNOWN = 'unknown' -@serializable.serializable_enum class CryptoFunction(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties.cryptoFunctions.cryptoFunction - ENUM type within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties.cryptoFunctions ENUM. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - DECAPSULATE = 'decapsulate' + GENERATE = 'generate' + KEYGEN = 'keygen' + ENCRYPT = 'encrypt' DECRYPT = 'decrypt' DIGEST = 'digest' - ENCAPSULATE = 'encapsulate' - ENCRYPT = 'encrypt' - GENERATE = 'generate' + TAG = 'tag' KEYDERIVE = 'keyderive' - KEYGEN = 'keygen' SIGN = 'sign' - TAG = 'tag' VERIFY = 'verify' + ENCAPSULATE = 'encapsulate' + DECAPSULATE = 'decapsulate' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class AlgorithmProperties: """ - This is our internal representation of the cryptoPropertiesType.algorithmProperties ENUM type within the CycloneDX - standard. + This is our internal representation of the cryptoPropertiesType.algorithmProperties complex type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - primitive: Optional[CryptoPrimitive] = None, - parameter_set_identifier: Optional[str] = None, - curve: Optional[str] = None, - execution_environment: Optional[CryptoExecutionEnvironment] = None, - implementation_platform: Optional[CryptoImplementationPlatform] = None, - certification_levels: Optional[Iterable[CryptoCertificationLevel]] = None, - mode: Optional[CryptoMode] = None, - padding: Optional[CryptoPadding] = None, - crypto_functions: Optional[Iterable[CryptoFunction]] = None, - classical_security_level: Optional[int] = None, - nist_quantum_security_level: Optional[int] = None, - ) -> None: - self.primitive = primitive - self.parameter_set_identifier = parameter_set_identifier - self.curve = curve - self.execution_environment = execution_environment - self.implementation_platform = implementation_platform - self.certification_levels = certification_levels or [] - self.mode = mode - self.padding = padding - self.crypto_functions = crypto_functions or [] - self.classical_security_level = classical_security_level - self.nist_quantum_security_level = nist_quantum_security_level - - @property - @serializable.xml_sequence(1) - def primitive(self) -> Optional[CryptoPrimitive]: - """ - Cryptographic building blocks used in higher-level cryptographic systems and protocols. - - Primitives represent different cryptographic routines: deterministic random bit generators (drbg, e.g. CTR_DRBG - from NIST SP800-90A-r1), message authentication codes (mac, e.g. HMAC-SHA-256), blockciphers (e.g. AES), - streamciphers (e.g. Salsa20), signatures (e.g. ECDSA), hash functions (e.g. SHA-256), - public-key encryption schemes (pke, e.g. RSA), extended output functions (xof, e.g. SHAKE256), - key derivation functions (e.g. pbkdf2), key agreement algorithms (e.g. ECDH), - key encapsulation mechanisms (e.g. ML-KEM), authenticated encryption (ae, e.g. AES-GCM) and the combination of - multiple algorithms (combiner, e.g. SP800-56Cr2). - - Returns: - `CryptoPrimitive` or `None` - """ - return self._primitive - - @primitive.setter - def primitive(self, primitive: Optional[CryptoPrimitive]) -> None: - self._primitive = primitive - - @property - @serializable.xml_sequence(2) - def parameter_set_identifier(self) -> Optional[str]: - """ - An identifier for the parameter set of the cryptographic algorithm. Examples: in AES128, '128' identifies the - key length in bits, in SHA256, '256' identifies the digest length, '128' in SHAKE128 identifies its maximum - security level in bits, and 'SHA2-128s' identifies a parameter set used in SLH-DSA (FIPS205). - - Returns: - `str` or `None` - """ - return self._parameter_set_identifier - - @parameter_set_identifier.setter - def parameter_set_identifier(self, parameter_set_identifier: Optional[str]) -> None: - self._parameter_set_identifier = parameter_set_identifier - - @property - @serializable.xml_sequence(3) - def curve(self) -> Optional[str]: - """ - The specific underlying Elliptic Curve (EC) definition employed which is an indicator of the level of security - strength, performance and complexity. Absent an authoritative source of curve names, CycloneDX recommends use - of curve names as defined at https://neuromancer.sk/std/, the source from which can be found at - https://github.com/J08nY/std-curves. - - Returns: - `str` or `None` - """ - return self._curve - - @curve.setter - def curve(self, curve: Optional[str]) -> None: - self._curve = curve - - @property - @serializable.xml_sequence(4) - def execution_environment(self) -> Optional[CryptoExecutionEnvironment]: - """ - The target and execution environment in which the algorithm is implemented in. - - Returns: - `CryptoExecutionEnvironment` or `None` - """ - return self._execution_environment - - @execution_environment.setter - def execution_environment(self, execution_environment: Optional[CryptoExecutionEnvironment]) -> None: - self._execution_environment = execution_environment - - @property - @serializable.xml_sequence(4) - def implementation_platform(self) -> Optional[CryptoImplementationPlatform]: - """ - The target platform for which the algorithm is implemented. The implementation can be 'generic', running on - any platform or for a specific platform. - - Returns: - `CryptoImplementationPlatform` or `None` - """ - return self._implementation_platform - - @implementation_platform.setter - def implementation_platform(self, implementation_platform: Optional[CryptoImplementationPlatform]) -> None: - self._implementation_platform = implementation_platform + primitive: Optional[CryptoPrimitive] = field( + default=None, + metadata={'json_name': 'primitive', 'xml_name': 'primitive', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) + + parameter_set_identifier: Optional[str] = field( + default=None, + metadata={'json_name': 'parameterSetIdentifier', 'xml_name': 'parameterSetIdentifier', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) + + curve: Optional[str] = field( + default=None, + metadata={'json_name': 'curve', 'xml_name': 'curve', 'xml_sequence': 3, + 'min_schema_version': SchemaVersion.V1_6} + ) + + execution_environment: Optional[CryptoExecutionEnvironment] = field( + default=None, + metadata={'json_name': 'executionEnvironment', 'xml_name': 'executionEnvironment', 'xml_sequence': 4, + 'min_schema_version': SchemaVersion.V1_6} + ) + + implementation_platform: Optional[CryptoImplementationPlatform] = field( + default=None, + metadata={'json_name': 'implementationPlatform', 'xml_name': 'implementationPlatform', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _certification_levels: 'SortedSet[CryptoCertificationLevel]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'certificationLevel', 'xml_name': 'certificationLevel', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_6} + ) + + mode: Optional[CryptoMode] = field( + default=None, + metadata={'json_name': 'mode', 'xml_name': 'mode', 'xml_sequence': 7, + 'min_schema_version': SchemaVersion.V1_6} + ) + + padding: Optional[CryptoPadding] = field( + default=None, + metadata={'json_name': 'padding', 'xml_name': 'padding', 'xml_sequence': 8, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _crypto_functions: 'SortedSet[CryptoFunction]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'cryptoFunctions', 'xml_name': 'cryptoFunctions', 'xml_item_name': 'cryptoFunction', + 'xml_sequence': 9, 'min_schema_version': SchemaVersion.V1_6} + ) + + classical_security_level: Optional[int] = field( + default=None, + metadata={'json_name': 'classicalSecurityLevel', 'xml_name': 'classicalSecurityLevel', 'xml_sequence': 10, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _nist_quantum_security_level: Optional[int] = field( + default=None, + metadata={'json_name': 'nistQuantumSecurityLevel', 'xml_name': 'nistQuantumSecurityLevel', 'xml_sequence': 11, + 'min_schema_version': SchemaVersion.V1_6} + ) @property - @serializable.json_name('certificationLevel') - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, child_name='certificationLevel') - @serializable.xml_sequence(5) def certification_levels(self) -> 'SortedSet[CryptoCertificationLevel]': - """ - The certification that the implementation of the cryptographic algorithm has received, if any. Certifications - include revisions and levels of FIPS 140 or Common Criteria of different Extended Assurance Levels (CC-EAL). - - Returns: - `Iterable[CryptoCertificationLevel]` - """ return self._certification_levels @certification_levels.setter @@ -412,45 +317,7 @@ def certification_levels(self, certification_levels: Iterable[CryptoCertificatio self._certification_levels = SortedSet(certification_levels) @property - @serializable.xml_sequence(6) - def mode(self) -> Optional[CryptoMode]: - """ - The mode of operation in which the cryptographic algorithm (block cipher) is used. - - Returns: - `CryptoMode` or `None` - """ - return self._mode - - @mode.setter - def mode(self, mode: Optional[CryptoMode]) -> None: - self._mode = mode - - @property - @serializable.xml_sequence(8) - def padding(self) -> Optional[CryptoPadding]: - """ - The padding scheme that is used for the cryptographic algorithm. - - Returns: - `CryptoPadding` or `None` - """ - return self._padding - - @padding.setter - def padding(self, padding: Optional[CryptoPadding]) -> None: - self._padding = padding - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, child_name='cryptoFunction') - @serializable.xml_sequence(9) def crypto_functions(self) -> 'SortedSet[CryptoFunction]': - """ - The cryptographic functions implemented by the cryptographic algorithm. - - Returns: - `Iterable[CryptoFunction]` - """ return self._crypto_functions @crypto_functions.setter @@ -458,704 +325,345 @@ def crypto_functions(self, crypto_functions: Iterable[CryptoFunction]) -> None: self._crypto_functions = SortedSet(crypto_functions) @property - @serializable.xml_sequence(10) - def classical_security_level(self) -> Optional[int]: - """ - The classical security level that a cryptographic algorithm provides (in bits). - - Returns: - `int` or `None` - """ - return self._classical_security_level - - @classical_security_level.setter - def classical_security_level(self, classical_security_level: Optional[int]) -> None: - self._classical_security_level = classical_security_level - - @property - @serializable.xml_sequence(11) def nist_quantum_security_level(self) -> Optional[int]: - """ - The NIST security strength category as defined in - https://csrc.nist.gov/projects/post-quantum-cryptography/post-quantum-cryptography-standardization/ - evaluation-criteria/security-(evaluation-criteria). A value of 0 indicates that none of the categories are met. - - Returns: - `int` or `None` - """ return self._nist_quantum_security_level @nist_quantum_security_level.setter def nist_quantum_security_level(self, nist_quantum_security_level: Optional[int]) -> None: - if nist_quantum_security_level is not None and ( - nist_quantum_security_level < 0 - or nist_quantum_security_level > 6 - ): + if nist_quantum_security_level is not None and not (0 <= nist_quantum_security_level <= 6): raise InvalidNistQuantumSecurityLevelException( - 'NIST Quantum Security Level must be (0 <= value <= 6)' - ) + f'nist_quantum_security_level must be between 0 and 6. Got: {nist_quantum_security_level}') self._nist_quantum_security_level = nist_quantum_security_level - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.primitive, self._parameter_set_identifier, self.curve, self.execution_environment, - self.implementation_platform, _ComparableTuple(self.certification_levels), self.mode, self.padding, - _ComparableTuple(self.crypto_functions), self.classical_security_level, self.nist_quantum_security_level, - )) + def __hash__(self) -> int: + return hash((self.primitive, self.parameter_set_identifier, self.curve, self.execution_environment, + self.implementation_platform, self.mode, self.padding, self.classical_security_level, + self.nist_quantum_security_level)) - def __eq__(self, other: object) -> bool: - if isinstance(other, AlgorithmProperties): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, AlgorithmProperties): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.primitive), self._cmp(self.parameter_set_identifier), + self._cmp(self.curve)) < ( + self._cmp(other.primitive), self._cmp(other.parameter_set_identifier), + self._cmp(other.curve)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class CertificateProperties: """ - This is our internal representation of the `cryptoPropertiesType.certificateProperties` complex type within - CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.certificateProperties complex type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - subject_name: Optional[str] = None, - issuer_name: Optional[str] = None, - not_valid_before: Optional[datetime] = None, - not_valid_after: Optional[datetime] = None, - signature_algorithm_ref: Optional[BomRef] = None, - subject_public_key_ref: Optional[BomRef] = None, - certificate_format: Optional[str] = None, - certificate_extension: Optional[str] = None, - ) -> None: - self.subject_name = subject_name - self.issuer_name = issuer_name - self.not_valid_before = not_valid_before - self.not_valid_after = not_valid_after - self.signature_algorithm_ref = signature_algorithm_ref - self.subject_public_key_ref = subject_public_key_ref - self.certificate_format = certificate_format - self.certificate_extension = certificate_extension - - @property - @serializable.xml_sequence(10) - def subject_name(self) -> Optional[str]: - """ - The subject name for the certificate. - - Returns: - `str` or `None` - """ - return self._subject_name - - @subject_name.setter - def subject_name(self, subject_name: Optional[str]) -> None: - self._subject_name = subject_name - - @property - @serializable.xml_sequence(20) - def issuer_name(self) -> Optional[str]: - """ - The issuer name for the certificate. - - Returns: - `str` or `None` - """ - return self._issuer_name - - @issuer_name.setter - def issuer_name(self, issuer_name: Optional[str]) -> None: - self._issuer_name = issuer_name - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(30) - def not_valid_before(self) -> Optional[datetime]: - """ - The date and time according to ISO-8601 standard from which the certificate is valid. - - Returns: - `datetime` or `None` - """ - return self._not_valid_before - - @not_valid_before.setter - def not_valid_before(self, not_valid_before: Optional[datetime]) -> None: - self._not_valid_before = not_valid_before - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(40) - def not_valid_after(self) -> Optional[datetime]: - """ - The date and time according to ISO-8601 standard from which the certificate is not valid anymore. - - Returns: - `datetime` or `None` - """ - return self._not_valid_after - - @not_valid_after.setter - def not_valid_after(self, not_valid_after: Optional[datetime]) -> None: - self._not_valid_after = not_valid_after - - @property - @serializable.type_mapping(BomRef) - @serializable.xml_sequence(50) - def signature_algorithm_ref(self) -> Optional[BomRef]: - """ - The bom-ref to signature algorithm used by the certificate. - - Returns: - `BomRef` or `None` - """ - return self._signature_algorithm_ref - - @signature_algorithm_ref.setter - def signature_algorithm_ref(self, signature_algorithm_ref: Optional[BomRef]) -> None: - self._signature_algorithm_ref = signature_algorithm_ref - - @property - @serializable.type_mapping(BomRef) - @serializable.xml_sequence(60) - def subject_public_key_ref(self) -> Optional[BomRef]: - """ - The bom-ref to the public key of the subject. - - Returns: - `BomRef` or `None` - """ - return self._subject_public_key_ref - - @subject_public_key_ref.setter - def subject_public_key_ref(self, subject_public_key_ref: Optional[BomRef]) -> None: - self._subject_public_key_ref = subject_public_key_ref - - @property - @serializable.xml_sequence(70) - def certificate_format(self) -> Optional[str]: - """ - The format of the certificate. Examples include X.509, PEM, DER, and CVC. + subject_name: Optional[str] = field( + default=None, + metadata={'json_name': 'subjectName', 'xml_name': 'subjectName', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) + + issuer_name: Optional[str] = field( + default=None, + metadata={'json_name': 'issuerName', 'xml_name': 'issuerName', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) + + not_valid_before: Optional[datetime] = field( + default=None, + metadata={'json_name': 'notValidBefore', 'xml_name': 'notValidBefore', 'xml_sequence': 3, + 'min_schema_version': SchemaVersion.V1_6} + ) + + not_valid_after: Optional[datetime] = field( + default=None, + metadata={'json_name': 'notValidAfter', 'xml_name': 'notValidAfter', 'xml_sequence': 4, + 'min_schema_version': SchemaVersion.V1_6} + ) + + signature_algorithm_ref: Optional[BomRef] = field( + default=None, + metadata={'json_name': 'signatureAlgorithmRef', 'xml_name': 'signatureAlgorithmRef', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_6} + ) + + subject_public_key_ref: Optional[BomRef] = field( + default=None, + metadata={'json_name': 'subjectPublicKeyRef', 'xml_name': 'subjectPublicKeyRef', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_6} + ) + + certificate_format: Optional[str] = field( + default=None, + metadata={'json_name': 'certificateFormat', 'xml_name': 'certificateFormat', 'xml_sequence': 7, + 'min_schema_version': SchemaVersion.V1_6} + ) + + certificate_extension: Optional[str] = field( + default=None, + metadata={'json_name': 'certificateExtension', 'xml_name': 'certificateExtension', 'xml_sequence': 8, + 'min_schema_version': SchemaVersion.V1_6} + ) - Returns: - `str` or `None` - """ - return self._certificate_format - - @certificate_format.setter - def certificate_format(self, certificate_format: Optional[str]) -> None: - self._certificate_format = certificate_format + def __hash__(self) -> int: + return hash((self.subject_name, self.issuer_name, self.not_valid_before, self.not_valid_after)) - @property - @serializable.xml_sequence(80) - def certificate_extension(self) -> Optional[str]: - """ - The file extension of the certificate. Examples include crt, pem, cer, der, and p12. - - Returns: - `str` or `None` - """ - return self._certificate_extension - - @certificate_extension.setter - def certificate_extension(self, certificate_extension: Optional[str]) -> None: - self._certificate_extension = certificate_extension - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.subject_name, self.issuer_name, self.not_valid_before, self.not_valid_after, - self.certificate_format, self.certificate_extension - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, CertificateProperties): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, CertificateProperties): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.subject_name), self._cmp(self.issuer_name)) < ( + self._cmp(other.subject_name), self._cmp(other.issuer_name)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_enum class RelatedCryptoMaterialType(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties.type ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties.type ENUM. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - ADDITIONAL_DATA = 'additional-data' + PRIVATE_KEY = 'private-key' + PUBLIC_KEY = 'public-key' + SECRET_KEY = 'secret-key' + KEY = 'key' CIPHERTEXT = 'ciphertext' - CREDENTIAL = 'credential' + SIGNATURE = 'signature' DIGEST = 'digest' INITIALIZATION_VECTOR = 'initialization-vector' - KEY = 'key' NONCE = 'nonce' - PASSWORD = 'password' # nosec - PRIVATE_KEY = 'private-key' - PUBLIC_KEY = 'public-key' - SALT = 'salt' - SECRET_KEY = 'secret-key' # nosec SEED = 'seed' - SHARED_SECRET = 'shared-secret' # nosec - SIGNATURE = 'signature' + SALT = 'salt' + SHARED_SECRET = 'shared-secret' TAG = 'tag' - TOKEN = 'token' # nosec - + ADDITIONAL_DATA = 'additional-data' + PASSWORD = 'password' + CREDENTIAL = 'credential' + TOKEN = 'token' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_enum class RelatedCryptoMaterialState(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties.state ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties.state ENUM. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ + PRE_ACTIVATION = 'pre-activation' ACTIVE = 'active' - COMPROMISED = 'compromised' + SUSPENDED = 'suspended' DEACTIVATED = 'deactivated' + COMPROMISED = 'compromised' DESTROYED = 'destroyed' - PRE_ACTIVATION = 'pre-activation' - SUSPENDED = 'suspended' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class RelatedCryptoMaterialSecuredBy: """ - This is our internal representation of the `cryptoPropertiesType.relatedCryptoMaterialProperties.securedBy` complex - type within CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties.securedBy type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - mechanism: Optional[str] = None, - algorithm_ref: Optional[BomRef] = None, - ) -> None: - self.mechanism = mechanism - self.algorithm_ref = algorithm_ref + mechanism: Optional[str] = field( + default=None, + metadata={'json_name': 'mechanism', 'xml_name': 'mechanism', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) - @property - @serializable.xml_sequence(10) - def mechanism(self) -> Optional[str]: - """ - Specifies the mechanism by which the cryptographic asset is secured by. - Examples include HSM, TPM, XGX, Software, and None. - - Returns: - `str` or `None` - """ - return self._mechanism + algorithm_ref: Optional[BomRef] = field( + default=None, + metadata={'json_name': 'algorithmRef', 'xml_name': 'algorithmRef', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) - @mechanism.setter - def mechanism(self, mechanism: Optional[str]) -> None: - self._mechanism = mechanism + def __hash__(self) -> int: + return hash((self.mechanism, self.algorithm_ref)) - @property - @serializable.type_mapping(BomRef) - @serializable.xml_sequence(20) - def algorithm_ref(self) -> Optional[BomRef]: - """ - The bom-ref to the algorithm. - - Returns: - `BomRef` or `None` - """ - return self._algorithm_ref - - @algorithm_ref.setter - def algorithm_ref(self, algorithm_ref: Optional[BomRef]) -> None: - self._algorithm_ref = algorithm_ref - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.mechanism, self.algorithm_ref - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, RelatedCryptoMaterialSecuredBy): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, RelatedCryptoMaterialSecuredBy): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.mechanism), self._cmp(self.algorithm_ref)) < ( + self._cmp(other.mechanism), self._cmp(other.algorithm_ref)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class RelatedCryptoMaterialProperties: """ - This is our internal representation of the `cryptoPropertiesType.relatedCryptoMaterialProperties` complex type - within CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.relatedCryptoMaterialProperties complex type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - type: Optional[RelatedCryptoMaterialType] = None, - id: Optional[str] = None, - state: Optional[RelatedCryptoMaterialState] = None, - algorithm_ref: Optional[BomRef] = None, - creation_date: Optional[datetime] = None, - activation_date: Optional[datetime] = None, - update_date: Optional[datetime] = None, - expiration_date: Optional[datetime] = None, - value: Optional[str] = None, - size: Optional[int] = None, - format: Optional[str] = None, - secured_by: Optional[RelatedCryptoMaterialSecuredBy] = None, - ) -> None: - self.type = type - self.id = id - self.state = state - self.algorithm_ref = algorithm_ref - self.creation_date = creation_date - self.activation_date = activation_date - self.update_date = update_date - self.expiration_date = expiration_date - self.value = value - self.size = size - self.format = format - self.secured_by = secured_by - - @property - @serializable.xml_sequence(10) - def type(self) -> Optional[RelatedCryptoMaterialType]: - """ - The type for the related cryptographic material. - - Returns - """ - return self._type - - @type.setter - def type(self, type: Optional[RelatedCryptoMaterialType]) -> None: - self._type = type - - @property - @serializable.xml_sequence(20) - def id(self) -> Optional[str]: - """ - The optional unique identifier for the related cryptographic material. - - :return: - """ - return self._id - - @id.setter - def id(self, id: Optional[str]) -> None: - self._id = id - - @property - @serializable.xml_sequence(30) - def state(self) -> Optional[RelatedCryptoMaterialState]: - """ - The key state as defined by NIST SP 800-57. - - Returns: - `RelatedCryptoMaterialState` or `None` - """ - return self._state - - @state.setter - def state(self, state: Optional[RelatedCryptoMaterialState]) -> None: - self._state = state - - @property - @serializable.type_mapping(BomRef) - @serializable.xml_sequence(40) - def algorithm_ref(self) -> Optional[BomRef]: - """ - The bom-ref to the algorithm used to generate the related cryptographic material. - - Returns: - `BomRef` or `None` - """ - return self._algorithm_ref - - @algorithm_ref.setter - def algorithm_ref(self, algorithm_ref: Optional[BomRef]) -> None: - self._algorithm_ref = algorithm_ref - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(50) - def creation_date(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the related cryptographic material was created. - - Returns: - `datetime` or `None` - """ - return self._creation_date - - @creation_date.setter - def creation_date(self, creation_date: Optional[datetime]) -> None: - self._creation_date = creation_date - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(60) - def activation_date(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the related cryptographic material was activated. - - Returns: - `datetime` or `None` - """ - return self._activation_date - - @activation_date.setter - def activation_date(self, activation_date: Optional[datetime]) -> None: - self._activation_date = activation_date - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(70) - def update_date(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the related cryptographic material was updated. - - Returns: - `datetime` or `None` - """ - return self._update_date - - @update_date.setter - def update_date(self, update_date: Optional[datetime]) -> None: - self._update_date = update_date + type: Optional[RelatedCryptoMaterialType] = field( + default=None, + metadata={'json_name': 'type', 'xml_name': 'type', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) + + id: Optional[str] = field( + default=None, + metadata={'json_name': 'id', 'xml_name': 'id', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) + + state: Optional[RelatedCryptoMaterialState] = field( + default=None, + metadata={'json_name': 'state', 'xml_name': 'state', 'xml_sequence': 3, + 'min_schema_version': SchemaVersion.V1_6} + ) + + algorithm_ref: Optional[BomRef] = field( + default=None, + metadata={'json_name': 'algorithmRef', 'xml_name': 'algorithmRef', 'xml_sequence': 4, + 'min_schema_version': SchemaVersion.V1_6} + ) + + creation_date: Optional[datetime] = field( + default=None, + metadata={'json_name': 'creationDate', 'xml_name': 'creationDate', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_6} + ) + + activation_date: Optional[datetime] = field( + default=None, + metadata={'json_name': 'activationDate', 'xml_name': 'activationDate', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_6} + ) + + update_date: Optional[datetime] = field( + default=None, + metadata={'json_name': 'updateDate', 'xml_name': 'updateDate', 'xml_sequence': 7, + 'min_schema_version': SchemaVersion.V1_6} + ) + + expiration_date: Optional[datetime] = field( + default=None, + metadata={'json_name': 'expirationDate', 'xml_name': 'expirationDate', 'xml_sequence': 8, + 'min_schema_version': SchemaVersion.V1_6} + ) + + value: Optional[str] = field( + default=None, + metadata={'json_name': 'value', 'xml_name': 'value', 'xml_sequence': 9, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _size: Optional[int] = field( + default=None, + metadata={'json_name': 'size', 'xml_name': 'size', 'xml_sequence': 10, + 'min_schema_version': SchemaVersion.V1_6} + ) + + format: Optional[str] = field( + default=None, + metadata={'json_name': 'format', 'xml_name': 'format', 'xml_sequence': 11, + 'min_schema_version': SchemaVersion.V1_6} + ) + + secured_by: Optional[RelatedCryptoMaterialSecuredBy] = field( + default=None, + metadata={'json_name': 'securedBy', 'xml_name': 'securedBy', 'xml_sequence': 12, + 'min_schema_version': SchemaVersion.V1_6} + ) @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(80) - def expiration_date(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the related cryptographic material expires. - - Returns: - `datetime` or `None` - """ - return self._expiration_date - - @expiration_date.setter - def expiration_date(self, expiration_date: Optional[datetime]) -> None: - self._expiration_date = expiration_date - - @property - @serializable.xml_sequence(90) - def value(self) -> Optional[str]: - """ - The associated value of the cryptographic material. - - Returns: - `str` or `None` - """ - return self._value - - @value.setter - def value(self, value: Optional[str]) -> None: - self._value = value - - @property - @serializable.xml_sequence(100) def size(self) -> Optional[int]: - """ - The size of the cryptographic asset (in bits). - - Returns: - `int` or `None` - """ return self._size @size.setter def size(self, size: Optional[int]) -> None: - if size and size < 0: - raise InvalidRelatedCryptoMaterialSizeException('Size must be greater than zero') + if size is not None and size <= 0: + raise InvalidRelatedCryptoMaterialSizeException( + f'size must be a positive integer. Got: {size}') self._size = size - @property - @serializable.xml_sequence(110) - def format(self) -> Optional[str]: - """ - The format of the related cryptographic material (e.g. P8, PEM, DER). - - Returns: - `str` or `None` - """ - return self._format + def __hash__(self) -> int: + return hash((self.type, self.id, self.state, self.algorithm_ref)) - @format.setter - def format(self, format: Optional[str]) -> None: - self._format = format + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') - @property - @serializable.xml_sequence(120) - def secured_by(self) -> Optional[RelatedCryptoMaterialSecuredBy]: - """ - The mechanism by which the cryptographic asset is secured by. - - Returns: - `RelatedCryptoMaterialSecuredBy` or `None` - """ - return self._secured_by - - @secured_by.setter - def secured_by(self, secured_by: Optional[RelatedCryptoMaterialSecuredBy]) -> None: - self._secured_by = secured_by - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, self.id, self.state, self.algorithm_ref, self.creation_date, self.activation_date, - self.update_date, self.expiration_date, self.value, self.size, self.format, self.secured_by - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, RelatedCryptoMaterialProperties): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, RelatedCryptoMaterialProperties): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.type), self._cmp(self.id), self._cmp(self.state)) < ( + self._cmp(other.type), self._cmp(other.id), self._cmp(other.state)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_enum class ProtocolPropertiesType(str, Enum): """ - This is our internal representation of the cryptoPropertiesType.protocolProperties.type ENUM type - within the CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.protocolProperties.type ENUM type. .. note:: Introduced in CycloneDX v1.6 - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - IKE = 'ike' - IPSEC = 'ipsec' + TLS = 'tls' SSH = 'ssh' + IPSEC = 'ipsec' + IKE = 'ike' SSTP = 'sstp' - TLS = 'tls' WPA = 'wpa' OTHER = 'other' UNKNOWN = 'unknown' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class ProtocolPropertiesCipherSuite: """ - This is our internal representation of the `cryptoPropertiesType.protocolProperties.cipherSuites.cipherSuite` - complex type within CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.protocolProperties.cipherSuites complex type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - name: Optional[str] = None, - algorithms: Optional[Iterable[BomRef]] = None, - identifiers: Optional[Iterable[str]] = None, - ) -> None: - self.name = name - self.algorithms = algorithms or [] - self.identifiers = identifiers or [] - - @property - @serializable.xml_sequence(10) - def name(self) -> Optional[str]: - """ - A common name for the cipher suite. For example: TLS_DHE_RSA_WITH_AES_128_CCM. + name: Optional[str] = field( + default=None, + metadata={'json_name': 'name', 'xml_name': 'name', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) - Returns: - `str` or `None` - """ - return self._name + _algorithms: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'algorithms', 'xml_name': 'algorithms', 'xml_item_name': 'algorithm', + 'xml_sequence': 2, 'min_schema_version': SchemaVersion.V1_6} + ) - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name + _identifiers: 'SortedSet[str]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'identifiers', 'xml_name': 'identifiers', 'xml_item_name': 'identifier', + 'xml_sequence': 3, 'min_schema_version': SchemaVersion.V1_6} + ) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'algorithm') - @serializable.xml_sequence(20) def algorithms(self) -> 'SortedSet[BomRef]': - """ - A list BomRefs to algorithms related to the cipher suite. - - Returns: - `Iterable[BomRef]` or `None` - """ return self._algorithms @algorithms.setter @@ -1163,82 +671,79 @@ def algorithms(self, algorithms: Iterable[BomRef]) -> None: self._algorithms = SortedSet(algorithms) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'identifier') - @serializable.xml_sequence(20) def identifiers(self) -> 'SortedSet[str]': - """ - A list of common identifiers for the cipher suite. Examples include 0xC0 and 0x9E. - - Returns: - `Iterable[str]` or `None` - """ return self._identifiers @identifiers.setter def identifiers(self, identifiers: Iterable[str]) -> None: self._identifiers = SortedSet(identifiers) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, _ComparableTuple(self.algorithms), _ComparableTuple(self.identifiers) - )) + def __hash__(self) -> int: + return hash(self.name) - def __eq__(self, other: object) -> bool: - if isinstance(other, ProtocolPropertiesCipherSuite): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, ProtocolPropertiesCipherSuite): - return self.__comparable_tuple() < other.__comparable_tuple() + return self._cmp(self.name) < self._cmp(other.name) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class Ikev2TransformTypes: """ - This is our internal representation of the `cryptoPropertiesType.protocolProperties.ikev2TransformTypes` - complex type within CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.protocolProperties.ikev2TransformTypes. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - encr: Optional[Iterable[BomRef]] = None, - prf: Optional[Iterable[BomRef]] = None, - integ: Optional[Iterable[BomRef]] = None, - ke: Optional[Iterable[BomRef]] = None, - esn: Optional[bool] = None, - auth: Optional[Iterable[BomRef]] = None, - ) -> None: - self.encr = encr or [] - self.prf = prf or [] - self.integ = integ or [] - self.ke = ke or [] - self.esn = esn - self.auth = auth or [] + _encr: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'encr', 'xml_name': 'encr', 'xml_item_name': 'ref', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _prf: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'prf', 'xml_name': 'prf', 'xml_item_name': 'ref', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _integ: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'integ', 'xml_name': 'integ', 'xml_item_name': 'ref', 'xml_sequence': 3, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _ke: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'ke', 'xml_name': 'ke', 'xml_item_name': 'ref', 'xml_sequence': 4, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _esn: bool = field( + default=False, + metadata={'json_name': 'esn', 'xml_name': 'esn', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_6} + ) + + _auth: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'auth', 'xml_name': 'auth', 'xml_item_name': 'ref', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_6} + ) @property - @serializable.xml_sequence(10) def encr(self) -> 'SortedSet[BomRef]': - """ - Transform Type 1: encryption algorithms. - - Returns: - `Iterable[BomRef]` or `None` - """ return self._encr @encr.setter @@ -1246,14 +751,7 @@ def encr(self, encr: Iterable[BomRef]) -> None: self._encr = SortedSet(encr) @property - @serializable.xml_sequence(20) def prf(self) -> 'SortedSet[BomRef]': - """ - Transform Type 2: pseudorandom functions. - - Returns: - `Iterable[BomRef]` or `None` - """ return self._prf @prf.setter @@ -1261,14 +759,7 @@ def prf(self, prf: Iterable[BomRef]) -> None: self._prf = SortedSet(prf) @property - @serializable.xml_sequence(30) def integ(self) -> 'SortedSet[BomRef]': - """ - Transform Type 3: integrity algorithms. - - Returns: - `Iterable[BomRef]` or `None` - """ return self._integ @integ.setter @@ -1276,14 +767,7 @@ def integ(self, integ: Iterable[BomRef]) -> None: self._integ = SortedSet(integ) @property - @serializable.xml_sequence(40) def ke(self) -> 'SortedSet[BomRef]': - """ - Transform Type 4: Key Exchange Method (KE) per RFC9370, formerly called Diffie-Hellman Group (D-H). - - Returns: - `Iterable[BomRef]` or `None` - """ return self._ke @ke.setter @@ -1291,130 +775,79 @@ def ke(self, ke: Iterable[BomRef]) -> None: self._ke = SortedSet(ke) @property - @serializable.xml_sequence(50) - def esn(self) -> Optional[bool]: - """ - Specifies if an Extended Sequence Number (ESN) is used. - - Returns: - `bool` or `None` - """ + def esn(self) -> bool: return self._esn @esn.setter - def esn(self, esn: Optional[bool]) -> None: + def esn(self, esn: bool) -> None: self._esn = esn @property - @serializable.xml_sequence(60) def auth(self) -> 'SortedSet[BomRef]': - """ - IKEv2 Authentication method. - - Returns: - `Iterable[BomRef]` or `None` - """ return self._auth @auth.setter def auth(self, auth: Iterable[BomRef]) -> None: self._auth = SortedSet(auth) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self.encr), - _ComparableTuple(self.prf), - _ComparableTuple(self.integ), - _ComparableTuple(self.ke), - self.esn, - _ComparableTuple(self.auth) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Ikev2TransformTypes): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((tuple(self.encr), tuple(self.prf), tuple(self.integ), tuple(self.ke), self.esn, tuple(self.auth))) - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, Ikev2TransformTypes): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + tuple(self.encr), tuple(self.prf), tuple(self.integ), + tuple(self.ke), self.esn, tuple(self.auth) + ) < ( + tuple(other.encr), tuple(other.prf), tuple(other.integ), + tuple(other.ke), other.esn, tuple(other.auth) + ) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class ProtocolProperties: """ - This is our internal representation of the `cryptoPropertiesType.protocolProperties` complex type within - CycloneDX standard. + This is our internal representation of the cryptoPropertiesType.protocolProperties complex type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - type: Optional[ProtocolPropertiesType] = None, - version: Optional[str] = None, - cipher_suites: Optional[Iterable[ProtocolPropertiesCipherSuite]] = None, - ikev2_transform_types: Optional[Ikev2TransformTypes] = None, - crypto_refs: Optional[Iterable[BomRef]] = None, - ) -> None: - self.type = type - self.version = version - self.cipher_suites = cipher_suites or [] - self.ikev2_transform_types = ikev2_transform_types - self.crypto_refs = crypto_refs or [] + type: Optional[ProtocolPropertiesType] = field( + default=None, + metadata={'json_name': 'type', 'xml_name': 'type', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) - @property - @serializable.xml_sequence(10) - def type(self) -> Optional[ProtocolPropertiesType]: - """ - The concrete protocol type. + version: Optional[str] = field( + default=None, + metadata={'json_name': 'version', 'xml_name': 'version', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) - Returns: - `ProtocolPropertiesType` or `None` - """ - return self._type + _cipher_suites: 'SortedSet[ProtocolPropertiesCipherSuite]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'cipherSuites', 'xml_name': 'cipherSuites', 'xml_item_name': 'cipherSuite', + 'xml_sequence': 3, 'min_schema_version': SchemaVersion.V1_6} + ) - @type.setter - def type(self, type: Optional[ProtocolPropertiesType]) -> None: - self._type = type + ikev2_transform_types: Optional[Ikev2TransformTypes] = field( + default=None, + metadata={'json_name': 'ikev2TransformTypes', 'xml_name': 'ikev2TransformTypes', 'xml_sequence': 4, + 'min_schema_version': SchemaVersion.V1_6} + ) - @property - @serializable.xml_sequence(20) - def version(self) -> Optional[str]: - """ - The version of the protocol. Examples include 1.0, 1.2, and 1.99. - - Returns: - `str` or `None` - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version + _crypto_refs: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'cryptoRefArray', 'xml_name': 'cryptoRefArray', 'xml_item_name': 'cryptoRef', + 'xml_sequence': 5, 'min_schema_version': SchemaVersion.V1_6} + ) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'cipherSuite') - @serializable.xml_sequence(30) def cipher_suites(self) -> 'SortedSet[ProtocolPropertiesCipherSuite]': - """ - A list of cipher suites related to the protocol. - - Returns: - `Iterable[ProtocolPropertiesCipherSuite]` - """ return self._cipher_suites @cipher_suites.setter @@ -1422,209 +855,72 @@ def cipher_suites(self, cipher_suites: Iterable[ProtocolPropertiesCipherSuite]) self._cipher_suites = SortedSet(cipher_suites) @property - @serializable.xml_sequence(40) - def ikev2_transform_types(self) -> Optional[Ikev2TransformTypes]: - """ - The IKEv2 transform types supported (types 1-4), defined in RFC7296 section 3.3.2, and additional properties. - - Returns: - `Ikev2TransformTypes` or `None` - """ - return self._ikev2_transform_types - - @ikev2_transform_types.setter - def ikev2_transform_types(self, ikev2_transform_types: Optional[Ikev2TransformTypes]) -> None: - self._ikev2_transform_types = ikev2_transform_types - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'cryptoRef') - @serializable.json_name('cryptoRefArray') def crypto_refs(self) -> 'SortedSet[BomRef]': - """ - A list of protocol-related cryptographic assets. - - Returns: - `Iterable[BomRef]` - """ return self._crypto_refs @crypto_refs.setter def crypto_refs(self, crypto_refs: Iterable[BomRef]) -> None: self._crypto_refs = SortedSet(crypto_refs) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, - self.version, - _ComparableTuple(self.cipher_suites), - self.ikev2_transform_types, - _ComparableTuple(self.crypto_refs) - )) + def __hash__(self) -> int: + return hash((self.type, self.version)) - def __eq__(self, other: object) -> bool: - if isinstance(other, ProtocolProperties): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') - def __lt__(self, other: object) -> bool: + def __lt__(self, other: Any) -> bool: if isinstance(other, ProtocolProperties): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.type), self._cmp(self.version)) < ( + self._cmp(other.type), self._cmp(other.version)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class CryptoProperties: """ - This is our internal representation of the `cryptoPropertiesType` complex type within CycloneDX standard. + This is our internal representation of the cryptoPropertiesType complex type. .. note:: Introduced in CycloneDX v1.6 - - - .. note:: - See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_cryptoPropertiesType """ - def __init__( - self, *, - asset_type: Optional[CryptoAssetType] = None, - algorithm_properties: Optional[AlgorithmProperties] = None, - certificate_properties: Optional[CertificateProperties] = None, - related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties] = None, - protocol_properties: Optional[ProtocolProperties] = None, - oid: Optional[str] = None, - ) -> None: - self.asset_type = asset_type - self.algorithm_properties = algorithm_properties - self.certificate_properties = certificate_properties - self.related_crypto_material_properties = related_crypto_material_properties - self.protocol_properties = protocol_properties - self.oid = oid - - @property - @serializable.xml_sequence(10) - def asset_type(self) -> Optional[CryptoAssetType]: - """ - Cryptographic assets occur in several forms. Algorithms and protocols are most commonly implemented in - specialized cryptographic libraries. They may however also be 'hardcoded' in software components. Certificates - and related cryptographic material like keys, tokens, secrets or passwords are other cryptographic assets to be - modelled. - - Returns: - `CryptoAssetType` - """ - return self._asset_type - - @asset_type.setter - def asset_type(self, asset_type: Optional[CryptoAssetType]) -> None: - self._asset_type = asset_type - - @property - @serializable.xml_sequence(20) - def algorithm_properties(self) -> Optional[AlgorithmProperties]: - """ - Additional properties specific to a cryptographic algorithm. - - Returns: - `AlgorithmProperties` or `None` - """ - return self._algorithm_properties - - @algorithm_properties.setter - def algorithm_properties(self, algorithm_properties: Optional[AlgorithmProperties]) -> None: - self._algorithm_properties = algorithm_properties - - @property - @serializable.xml_sequence(30) - def certificate_properties(self) -> Optional[CertificateProperties]: - """ - Properties for cryptographic assets of asset type 'certificate'. - - Returns: - `CertificateProperties` or `None` - """ - return self._certificate_properties - - @certificate_properties.setter - def certificate_properties(self, certificate_properties: Optional[CertificateProperties]) -> None: - self._certificate_properties = certificate_properties - - @property - @serializable.xml_sequence(40) - def related_crypto_material_properties(self) -> Optional[RelatedCryptoMaterialProperties]: - """ - Properties for cryptographic assets of asset type 'relatedCryptoMaterial'. - - Returns: - `RelatedCryptoMaterialProperties` or `None` - """ - return self._related_crypto_material_properties - - @related_crypto_material_properties.setter - def related_crypto_material_properties( - self, - related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties] - ) -> None: - self._related_crypto_material_properties = related_crypto_material_properties - - @property - @serializable.xml_sequence(50) - def protocol_properties(self) -> Optional[ProtocolProperties]: - """ - Properties specific to cryptographic assets of type: 'protocol'. - - Returns: - `ProtocolProperties` or `None` - """ - return self._protocol_properties - - @protocol_properties.setter - def protocol_properties(self, protocol_properties: Optional[ProtocolProperties]) -> None: - self._protocol_properties = protocol_properties - - @property - @serializable.xml_sequence(60) - def oid(self) -> Optional[str]: - """ - The object identifier (OID) of the cryptographic asset. - - Returns: - `str` or `None` - """ - return self._oid - - @oid.setter - def oid(self, oid: Optional[str]) -> None: - self._oid = oid - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.asset_type, - self.algorithm_properties, - self.certificate_properties, - self.related_crypto_material_properties, - self.protocol_properties, - self.oid, - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, CryptoProperties): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __lt__(self, other: Any) -> bool: - if isinstance(other, CryptoProperties): - return self.__comparable_tuple() < other.__comparable_tuple() - return NotImplemented + asset_type: Optional[CryptoAssetType] = field( + default=None, + metadata={'json_name': 'assetType', 'xml_name': 'assetType', 'xml_sequence': 1, + 'min_schema_version': SchemaVersion.V1_6} + ) + + algorithm_properties: Optional[AlgorithmProperties] = field( + default=None, + metadata={'json_name': 'algorithmProperties', 'xml_name': 'algorithmProperties', 'xml_sequence': 2, + 'min_schema_version': SchemaVersion.V1_6} + ) + + certificate_properties: Optional[CertificateProperties] = field( + default=None, + metadata={'json_name': 'certificateProperties', 'xml_name': 'certificateProperties', 'xml_sequence': 3, + 'min_schema_version': SchemaVersion.V1_6} + ) + + related_crypto_material_properties: Optional[RelatedCryptoMaterialProperties] = field( + default=None, + metadata={'json_name': 'relatedCryptoMaterialProperties', 'xml_name': 'relatedCryptoMaterialProperties', + 'xml_sequence': 4, 'min_schema_version': SchemaVersion.V1_6} + ) + + protocol_properties: Optional[ProtocolProperties] = field( + default=None, + metadata={'json_name': 'protocolProperties', 'xml_name': 'protocolProperties', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_6} + ) + + oid: Optional[str] = field( + default=None, + metadata={'json_name': 'oid', 'xml_name': 'oid', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_6} + ) def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' + return hash((self.asset_type, self.oid)) diff --git a/cyclonedx/model/definition.py b/cyclonedx/model/definition.py index 639743e57..21524e51f 100644 --- a/cyclonedx/model/definition.py +++ b/cyclonedx/model/definition.py @@ -19,7 +19,7 @@ from collections.abc import Iterable from typing import TYPE_CHECKING, Any, Optional, Union -import py_serializable as serializable +from attrs import define, field from sortedcontainers import SortedSet from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str @@ -35,12 +35,21 @@ _T_CreId = TypeVar('_T_CreId', bound='CreId') -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class CreId(serializable.helpers.BaseHelper): +def _sortedset_converter(value: Any) -> SortedSet: + """Convert a value to SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) + + +class CreId: """ Helper class that allows us to perform validation on data strings that must conform to Common Requirements Enumeration (CRE) identifier(s). - """ _VALID_CRE_REGEX = re.compile(r'^CRE:[0-9]+-[0-9]+$') @@ -53,8 +62,6 @@ def __init__(self, id: str) -> None: self._id = id @property - @serializable.json_name('.') - @serializable.xml_name('.') def id(self) -> str: return self._id @@ -89,7 +96,7 @@ def __str__(self) -> str: return self._id -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class Requirement: """ A requirement comprising a standard. @@ -99,90 +106,75 @@ class Requirement: https://cyclonedx.org/docs/1.7/json/#definitions_standards_items_requirements """ - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - identifier: Optional[str] = None, - title: Optional[str] = None, - text: Optional[str] = None, - descriptions: Optional[Iterable[str]] = None, - open_cre: Optional[Iterable[CreId]] = None, - parent: Optional[Union[str, BomRef]] = None, - properties: Optional[Iterable[Property]] = None, - external_references: Optional[Iterable[ExternalReference]] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.identifier = identifier - self.title = title - self.text = text - self.descriptions = descriptions or () - self.open_cre = open_cre or () - self.parent = parent - self.properties = properties or () - self.external_references = external_references or () + _bom_ref: BomRef = field( + factory=BomRef, + converter=_bom_ref_from_str, + metadata={'json_name': 'bom-ref', 'xml_name': 'bom-ref', 'xml_attribute': True} + ) + """An optional identifier which can be used to reference the requirement elsewhere in the BOM.""" + + identifier: Optional[str] = field( + default=None, + metadata={'json_name': 'identifier', 'xml_name': 'identifier', 'xml_sequence': 1} + ) + """The identifier of the requirement.""" + + title: Optional[str] = field( + default=None, + metadata={'json_name': 'title', 'xml_name': 'title', 'xml_sequence': 2} + ) + """The title of the requirement.""" + + text: Optional[str] = field( + default=None, + metadata={'json_name': 'text', 'xml_name': 'text', 'xml_sequence': 3} + ) + """The text of the requirement.""" + + _descriptions: 'SortedSet[str]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'descriptions', 'xml_name': 'descriptions', 'xml_item_name': 'description', + 'xml_sequence': 4} + ) + """A SortedSet of descriptions of the requirement.""" + + _open_cre: 'SortedSet[CreId]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'openCre', 'xml_name': 'openCre', 'xml_sequence': 5} + ) + """The Common Requirements Enumeration (CRE) identifier(s).""" + + _parent: Optional[BomRef] = field( + default=None, + metadata={'json_name': 'parent', 'xml_name': 'parent', 'xml_sequence': 6} + ) + """The optional bom-ref to a parent requirement.""" + + _properties: 'SortedSet[Property]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'properties', 'xml_name': 'properties', 'xml_item_name': 'property', 'xml_sequence': 7} + ) + """Properties in a key/value store.""" + + _external_references: 'SortedSet[ExternalReference]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'externalReferences', 'xml_name': 'externalReferences', 'xml_item_name': 'reference', + 'xml_sequence': 8} + ) + """External references related to the component.""" @property - @serializable.type_mapping(BomRef) - @serializable.json_name('bom-ref') - @serializable.xml_name('bom-ref') - @serializable.xml_attribute() def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the requirement elsewhere in the BOM. - Every bom-ref MUST be unique within the BOM. - - Returns: - `BomRef` - """ + """An optional identifier which can be used to reference the requirement elsewhere in the BOM.""" return self._bom_ref @property - @serializable.xml_sequence(1) - def identifier(self) -> Optional[str]: - """ - Returns: - The identifier of the requirement. - """ - return self._identifier - - @identifier.setter - def identifier(self, identifier: Optional[str]) -> None: - self._identifier = identifier - - @property - @serializable.xml_sequence(2) - def title(self) -> Optional[str]: - """ - Returns: - The title of the requirement. - """ - return self._title - - @title.setter - def title(self, title: Optional[str]) -> None: - self._title = title - - @property - @serializable.xml_sequence(3) - def text(self) -> Optional[str]: - """ - Returns: - The text of the requirement. - """ - return self._text - - @text.setter - def text(self, text: Optional[str]) -> None: - self._text = text - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'description') - @serializable.xml_sequence(4) def descriptions(self) -> 'SortedSet[str]': - """ - Returns: - A SortedSet of descriptions of the requirement. - """ + """A SortedSet of descriptions of the requirement.""" return self._descriptions @descriptions.setter @@ -190,19 +182,8 @@ def descriptions(self, descriptions: Iterable[str]) -> None: self._descriptions = SortedSet(descriptions) @property - @serializable.json_name('openCre') - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'openCre') - @serializable.xml_sequence(5) def open_cre(self) -> 'SortedSet[CreId]': - """ - CRE is a structured and standardized framework for uniting security standards and guidelines. CRE links each - section of a resource to a shared topic identifier (a Common Requirement). Through this shared topic link, all - resources map to each other. Use of CRE promotes clear and unambiguous communication among stakeholders. - - Returns: - The Common Requirements Enumeration (CRE) identifier(s). - CREs must match regular expression: ^CRE:[0-9]+-[0-9]+$ - """ + """The Common Requirements Enumeration (CRE) identifier(s).""" return self._open_cre @open_cre.setter @@ -210,14 +191,8 @@ def open_cre(self, open_cre: Iterable[CreId]) -> None: self._open_cre = SortedSet(open_cre) @property - @serializable.type_mapping(BomRef) - @serializable.xml_sequence(6) def parent(self) -> Optional[BomRef]: - """ - Returns: - The optional bom-ref to a parent requirement. This establishes a hierarchy of requirements. Top-level - requirements must not define a parent. Only child requirements should define parents. - """ + """The optional bom-ref to a parent requirement.""" return self._parent @parent.setter @@ -225,16 +200,8 @@ def parent(self, parent: Optional[Union[str, BomRef]]) -> None: self._parent = _bom_ref_from_str(parent, optional=True) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(7) def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Return: - Set of `Property` - """ + """Properties in a key/value store.""" return self._properties @properties.setter @@ -242,51 +209,24 @@ def properties(self, properties: Iterable[Property]) -> None: self._properties = SortedSet(properties) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(8) def external_references(self) -> 'SortedSet[ExternalReference]': - """ - Provides the ability to document external references related to the component or to the project the component - describes. - - Returns: - Set of `ExternalReference` - """ + """External references related to the component.""" return self._external_references @external_references.setter def external_references(self, external_references: Iterable[ExternalReference]) -> None: self._external_references = SortedSet(external_references) - def __comparable_tuple(self) -> _ComparableTuple: - # all properties are optional - so need to compare all, in hope that one is unique - return _ComparableTuple(( - self.identifier, self.bom_ref.value, - self.title, self.text, - _ComparableTuple(self.descriptions), - _ComparableTuple(self.open_cre), self.parent, _ComparableTuple(self.properties), - _ComparableTuple(self.external_references) - )) + def __hash__(self) -> int: + return hash((self.identifier, self.bom_ref.value, self.title, self.text)) def __lt__(self, other: Any) -> bool: if isinstance(other, Requirement): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.identifier or '', self.bom_ref.value or '') < (other.identifier or '', other.bom_ref.value or '') return NotImplemented - def __eq__(self, other: object) -> bool: - if isinstance(other, Requirement): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class Level: """ Level of compliance for a standard. @@ -295,82 +235,47 @@ class Level: See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/json/#definitions_standards_items_levels """ - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - identifier: Optional[str] = None, - title: Optional[str] = None, - description: Optional[str] = None, - requirements: Optional[Iterable[Union[str, BomRef]]] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.identifier = identifier - self.title = title - self.description = description - self.requirements = requirements or () + _bom_ref: BomRef = field( + factory=BomRef, + converter=_bom_ref_from_str, + metadata={'json_name': 'bom-ref', 'xml_name': 'bom-ref', 'xml_attribute': True} + ) + """An optional identifier which can be used to reference the level elsewhere in the BOM.""" + + identifier: Optional[str] = field( + default=None, + metadata={'json_name': 'identifier', 'xml_name': 'identifier', 'xml_sequence': 1} + ) + """The identifier of the level.""" + + title: Optional[str] = field( + default=None, + metadata={'json_name': 'title', 'xml_name': 'title', 'xml_sequence': 2} + ) + """The title of the level.""" + + description: Optional[str] = field( + default=None, + metadata={'json_name': 'description', 'xml_name': 'description', 'xml_sequence': 3} + ) + """The description of the level.""" + + _requirements: 'SortedSet[BomRef]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'requirements', 'xml_name': 'requirements', 'xml_item_name': 'requirement', + 'xml_sequence': 4} + ) + """A SortedSet of requirements associated with the level.""" @property - @serializable.type_mapping(BomRef) - @serializable.json_name('bom-ref') - @serializable.xml_name('bom-ref') - @serializable.xml_attribute() def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the level elsewhere in the BOM. - Every bom-ref MUST be unique within the BOM. - - Returns: - `BomRef` - """ + """An optional identifier which can be used to reference the level elsewhere in the BOM.""" return self._bom_ref @property - @serializable.xml_sequence(1) - def identifier(self) -> Optional[str]: - """ - Returns: - The identifier of the level. - """ - return self._identifier - - @identifier.setter - def identifier(self, identifier: Optional[str]) -> None: - self._identifier = identifier - - @property - @serializable.xml_sequence(2) - def title(self) -> Optional[str]: - """ - Returns: - The title of the level. - """ - return self._title - - @title.setter - def title(self, title: Optional[str]) -> None: - self._title = title - - @property - @serializable.xml_sequence(3) - def description(self) -> Optional[str]: - """ - Returns: - The description of the level. - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.xml_sequence(4) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'requirement') def requirements(self) -> 'SortedSet[BomRef]': - """ - Returns: - A SortedSet of requirements associated with the level. - """ + """A SortedSet of requirements associated with the level.""" return self._requirements @requirements.setter @@ -378,33 +283,16 @@ def requirements(self, requirements: Iterable[Union[str, BomRef]]) -> None: self._requirements = SortedSet(map(_bom_ref_from_str, # type:ignore[arg-type] requirements)) - def __comparable_tuple(self) -> _ComparableTuple: - # all properties are optional - so need to compare all, in hope that one is unique - return _ComparableTuple(( - self.identifier, self.bom_ref.value, - self.title, self.description, - _ComparableTuple(self.requirements) - )) + def __hash__(self) -> int: + return hash((self.identifier, self.bom_ref.value, self.title, self.description)) def __lt__(self, other: Any) -> bool: if isinstance(other, Level): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.identifier or '', self.bom_ref.value or '') < (other.identifier or '', other.bom_ref.value or '') return NotImplemented - def __eq__(self, other: object) -> bool: - if isinstance(other, Level): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class Standard: """ A standard of regulations, industry or organizational-specific standards, maturity models, best practices, @@ -414,103 +302,68 @@ class Standard: See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_standard """ - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - name: Optional[str] = None, - version: Optional[str] = None, - description: Optional[str] = None, - owner: Optional[str] = None, - requirements: Optional[Iterable[Requirement]] = None, - levels: Optional[Iterable[Level]] = None, - external_references: Optional[Iterable['ExternalReference']] = None - # TODO: signature - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.name = name - self.version = version - self.description = description - self.owner = owner - self.requirements = requirements or () - self.levels = levels or () - self.external_references = external_references or () - # TODO: signature + _bom_ref: BomRef = field( + factory=BomRef, + converter=_bom_ref_from_str, + metadata={'json_name': 'bom-ref', 'xml_name': 'bom-ref', 'xml_attribute': True} + ) + """An optional identifier which can be used to reference the standard elsewhere in the BOM.""" + + name: Optional[str] = field( + default=None, + metadata={'json_name': 'name', 'xml_name': 'name', 'xml_sequence': 1} + ) + """The name of the standard.""" + + version: Optional[str] = field( + default=None, + metadata={'json_name': 'version', 'xml_name': 'version', 'xml_sequence': 2} + ) + """The version of the standard.""" + + description: Optional[str] = field( + default=None, + metadata={'json_name': 'description', 'xml_name': 'description', 'xml_sequence': 3} + ) + """The description of the standard.""" + + owner: Optional[str] = field( + default=None, + metadata={'json_name': 'owner', 'xml_name': 'owner', 'xml_sequence': 4} + ) + """The owner of the standard.""" + + _requirements: 'SortedSet[Requirement]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'requirements', 'xml_name': 'requirements', 'xml_item_name': 'requirement', + 'xml_sequence': 5} + ) + """A SortedSet of requirements comprising the standard.""" + + _levels: 'SortedSet[Level]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'levels', 'xml_name': 'levels', 'xml_item_name': 'level', 'xml_sequence': 6} + ) + """A SortedSet of levels associated with the standard.""" + + _external_references: 'SortedSet[ExternalReference]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'externalReferences', 'xml_name': 'externalReferences', 'xml_item_name': 'reference', + 'xml_sequence': 7} + ) + """A SortedSet of external references associated with the standard.""" @property - @serializable.type_mapping(BomRef) - @serializable.json_name('bom-ref') - @serializable.xml_name('bom-ref') - @serializable.xml_attribute() def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the standard elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ + """An optional identifier which can be used to reference the standard elsewhere in the BOM.""" return self._bom_ref @property - @serializable.xml_sequence(1) - def name(self) -> Optional[str]: - """ - Returns: - The name of the standard - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.xml_sequence(2) - def version(self) -> Optional[str]: - """ - Returns: - The version of the standard - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version - - @property - @serializable.xml_sequence(3) - def description(self) -> Optional[str]: - """ - Returns: - The description of the standard - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.xml_sequence(4) - def owner(self) -> Optional[str]: - """ - Returns: - The owner of the standard, often the entity responsible for its release. - """ - return self._owner - - @owner.setter - def owner(self, owner: Optional[str]) -> None: - self._owner = owner - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'requirement') - @serializable.xml_sequence(5) def requirements(self) -> 'SortedSet[Requirement]': - """ - Returns: - A SortedSet of requirements comprising the standard. - """ + """A SortedSet of requirements comprising the standard.""" return self._requirements @requirements.setter @@ -518,13 +371,8 @@ def requirements(self, requirements: Iterable[Requirement]) -> None: self._requirements = SortedSet(requirements) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'level') - @serializable.xml_sequence(6) def levels(self) -> 'SortedSet[Level]': - """ - Returns: - A SortedSet of levels associated with the standard. Some standards have different levels of compliance. - """ + """A SortedSet of levels associated with the standard.""" return self._levels @levels.setter @@ -532,62 +380,24 @@ def levels(self, levels: Iterable[Level]) -> None: self._levels = SortedSet(levels) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(7) def external_references(self) -> 'SortedSet[ExternalReference]': - """ - Returns: - A SortedSet of external references associated with the standard. - """ + """A SortedSet of external references associated with the standard.""" return self._external_references @external_references.setter def external_references(self, external_references: Iterable[ExternalReference]) -> None: self._external_references = SortedSet(external_references) - # @property - # @serializable.xml_sequence(8) - # # MUST NOT RENDER FOR XML -- this is JSON only - # def signature(self) -> ...: - # ... - # - # @signature.setter - # def levels(self, signature: ...) -> None: - # ... - - def __comparable_tuple(self) -> _ComparableTuple: - # all properties are optional - so need to apply all, in hope that one is unique - return _ComparableTuple(( - self.name, self.version, - self.bom_ref.value, - self.description, self.owner, - _ComparableTuple(self.requirements), _ComparableTuple(self.levels), - _ComparableTuple(self.external_references) - )) + def __hash__(self) -> int: + return hash((self.name, self.version, self.bom_ref.value)) def __lt__(self, other: Any) -> bool: if isinstance(other, Standard): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.name or '', self.version or '') < (other.name or '', other.version or '') return NotImplemented - def __eq__(self, other: object) -> bool: - if isinstance(other, Standard): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class( - name='definitions', - ignore_unknown_during_deserialization=True -) +@define class Definitions: """ The repository for definitions @@ -596,20 +406,16 @@ class Definitions: See the CycloneDX Schema for hashType: https://cyclonedx.org/docs/1.7/xml/#type_definitionsType """ - def __init__( - self, *, - standards: Optional[Iterable[Standard]] = None - ) -> None: - self.standards = standards or () + _standards: 'SortedSet[Standard]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'standards', 'xml_name': 'standards', 'xml_item_name': 'standard', 'xml_sequence': 1} + ) + """A SortedSet of Standards.""" @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'standard') - @serializable.xml_sequence(1) def standards(self) -> 'SortedSet[Standard]': - """ - Returns: - A SortedSet of Standards - """ + """A SortedSet of Standards.""" return self._standards @standards.setter @@ -619,22 +425,8 @@ def standards(self, standards: Iterable[Standard]) -> None: def __bool__(self) -> bool: return len(self._standards) > 0 - def __comparable_tuple(self) -> _ComparableTuple: - # all properties are optional - so need to apply all, in hope that one is unique - return _ComparableTuple(self._standards) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Definitions): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __lt__(self, other: Any) -> bool: - if isinstance(other, Definitions): - return self.__comparable_tuple() < other.__comparable_tuple() - return NotImplemented + def __len__(self) -> int: + return len(self._standards) def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' + return hash(tuple(self._standards)) diff --git a/cyclonedx/model/dependency.py b/cyclonedx/model/dependency.py index de3ca3260..9b57c930b 100644 --- a/cyclonedx/model/dependency.py +++ b/cyclonedx/model/dependency.py @@ -20,34 +20,26 @@ from collections.abc import Iterable from typing import Any, Optional -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet -from .._internal.compare import ComparableTuple as _ComparableTuple -from ..exception.serialization import SerializationOfUnexpectedValueException +from ..serialization import METADATA_KEY_JSON_NAME, METADATA_KEY_XML_ATTR from .bom_ref import BomRef -class _DependencyRepositorySerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ +def _sortedset_factory() -> SortedSet: + return SortedSet() - @classmethod - def serialize(cls, o: Any) -> list[str]: - if isinstance(o, (SortedSet, set)): - return [str(i.ref) for i in o] - raise SerializationOfUnexpectedValueException( - f'Attempt to serialize a non-DependencyRepository: {o!r}') - @classmethod - def deserialize(cls, o: Any) -> set['Dependency']: - dependencies = set() - if isinstance(o, list): - for v in o: - dependencies.add(Dependency(ref=BomRef(value=v))) - return dependencies +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + return SortedSet(value) -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class Dependency: """ Models a Dependency within a BOM. @@ -55,52 +47,25 @@ class Dependency: .. note:: See https://cyclonedx.org/docs/1.7/xml/#type_dependencyType """ - - def __init__(self, ref: BomRef, dependencies: Optional[Iterable['Dependency']] = None) -> None: - self.ref = ref - self.dependencies = dependencies or [] - - @property - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - def ref(self) -> BomRef: - return self._ref - - @ref.setter - def ref(self, ref: BomRef) -> None: - self._ref = ref - - @property - @serializable.json_name('dependsOn') - @serializable.type_mapping(_DependencyRepositorySerializationHelper) - @serializable.xml_array(serializable.XmlArraySerializationType.FLAT, 'dependency') - def dependencies(self) -> 'SortedSet[Dependency]': - return self._dependencies - - @dependencies.setter - def dependencies(self, dependencies: Iterable['Dependency']) -> None: - self._dependencies = SortedSet(dependencies) + ref: BomRef = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + dependencies: 'SortedSet[Dependency]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_JSON_NAME: 'dependsOn'} + ) def dependencies_as_bom_refs(self) -> set[BomRef]: return set(map(lambda d: d.ref, self.dependencies)) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.ref, _ComparableTuple(self.dependencies) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Dependency): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - def __lt__(self, other: Any) -> bool: if isinstance(other, Dependency): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.ref, tuple(self.dependencies)) < (other.ref, tuple(other.dependencies)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.ref, tuple(self.dependencies))) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/impact_analysis.py b/cyclonedx/model/impact_analysis.py index 41d35ea33..ffcc7deff 100644 --- a/cyclonedx/model/impact_analysis.py +++ b/cyclonedx/model/impact_analysis.py @@ -28,10 +28,7 @@ from enum import Enum -import py_serializable as serializable - -@serializable.serializable_enum class ImpactAnalysisAffectedStatus(str, Enum): """ Enum object that defines the permissible impact analysis affected states. @@ -53,7 +50,6 @@ class ImpactAnalysisAffectedStatus(str, Enum): UNKNOWN = 'unknown' -@serializable.serializable_enum class ImpactAnalysisJustification(str, Enum): """ Enum object that defines the rationale of why the impact analysis state was asserted. @@ -73,7 +69,6 @@ class ImpactAnalysisJustification(str, Enum): REQUIRES_ENVIRONMENT = 'requires_environment' -@serializable.serializable_enum class ImpactAnalysisResponse(str, Enum): """ Enum object that defines the valid rationales as to why the impact analysis state was asserted. @@ -89,7 +84,6 @@ class ImpactAnalysisResponse(str, Enum): WORKAROUND_AVAILABLE = 'workaround_available' -@serializable.serializable_enum class ImpactAnalysisState(str, Enum): """ Enum object that defines the permissible impact analysis states. diff --git a/cyclonedx/model/issue.py b/cyclonedx/model/issue.py index 1663a7265..afd451b0d 100644 --- a/cyclonedx/model/issue.py +++ b/cyclonedx/model/issue.py @@ -15,18 +15,19 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) OWASP Foundation. All Rights Reserved. +from ..serialization import ALL_VERSIONS +from ..schema import SchemaVersion from collections.abc import Iterable from enum import Enum from typing import Any, Optional -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet -from .._internal.compare import ComparableTuple as _ComparableTuple +from ..serialization import METADATA_KEY_XML_ATTR, METADATA_KEY_XML_SEQUENCE from . import XsUri -@serializable.serializable_enum class IssueClassification(str, Enum): """ This is our internal representation of the enum `issueClassification`. @@ -39,77 +40,57 @@ class IssueClassification(str, Enum): SECURITY = 'security' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +# Issue classification support by schema version +ISSUE_CLASSIFICATION_VERSIONS: dict[IssueClassification, set[SchemaVersion]] = { + IssueClassification.DEFECT: ALL_VERSIONS, + IssueClassification.ENHANCEMENT: ALL_VERSIONS, + IssueClassification.SECURITY: ALL_VERSIONS, +} + + +@attrs.define class IssueTypeSource: """ - This is our internal representation ofa source within the IssueType complex type that can be used in multiple + This is our internal representation of a source within the IssueType complex type that can be used in multiple places within a CycloneDX BOM document. .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_pedigree_patches_items_resolves_items_source """ + name: Optional[str] = attrs.field(default=None) + url: Optional[XsUri] = attrs.field(default=None) - def __init__( - self, *, - name: Optional[str] = None, - url: Optional[XsUri] = None, - ) -> None: - self.name = name - self.url = url - - @property - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - The name of the source. For example "National Vulnerability Database", "NVD", and "Apache". - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - def url(self) -> Optional[XsUri]: - """ - Optional url of the issue documentation as provided by the source. - - Returns: - `XsUri` if set else `None` - """ - return self._url - - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, self.url - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, IssueTypeSource): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, IssueTypeSource): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.name), self._cmp(self.url)) < (self._cmp(other.name), self._cmp(other.url)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.name, self.url)) def __repr__(self) -> str: - return f'' + return f'' + + +def _sortedset_factory() -> SortedSet: + return SortedSet() -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + return SortedSet(value) + + +@attrs.define class IssueType: """ This is our internal representation of an IssueType complex type that can be used in multiple places within @@ -118,135 +99,45 @@ class IssueType: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_issueType """ - - def __init__( - self, *, - type: IssueClassification, - id: Optional[str] = None, - name: Optional[str] = None, - description: Optional[str] = None, - source: Optional[IssueTypeSource] = None, - references: Optional[Iterable[XsUri]] = None, - ) -> None: - self.type = type - self.id = id - self.name = name - self.description = description - self.source = source - self.references = references or [] - - @property - @serializable.xml_attribute() - def type(self) -> IssueClassification: - """ - Specifies the type of issue. - - Returns: - `IssueClassification` - """ - return self._type - - @type.setter - def type(self, type: IssueClassification) -> None: - self._type = type - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def id(self) -> Optional[str]: - """ - The identifier of the issue assigned by the source of the issue. - - Returns: - `str` if set else `None` - """ - return self._id - - @id.setter - def id(self, id: Optional[str]) -> None: - self._id = id - - @property - @serializable.xml_sequence(2) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - The name of the issue. - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.xml_sequence(3) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def description(self) -> Optional[str]: - """ - A description of the issue. - - Returns: - `str` if set else `None` - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.xml_sequence(4) - def source(self) -> Optional[IssueTypeSource]: - """ - The source of this issue. - - Returns: - `IssueTypeSource` if set else `None` - """ - return self._source - - @source.setter - def source(self, source: Optional[IssueTypeSource]) -> None: - self._source = source - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'url') - @serializable.xml_sequence(5) - def references(self) -> 'SortedSet[XsUri]': - """ - Any reference URLs related to this issue. - - Returns: - Set of `XsUri` - """ - return self._references - - @references.setter - def references(self, references: Iterable[XsUri]) -> None: - self._references = SortedSet(references) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, self.id, self.name, self.description, self.source, - _ComparableTuple(self.references) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, IssueType): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + type: IssueClassification = attrs.field( + metadata={METADATA_KEY_XML_ATTR: True} + ) + id: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + name: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + description: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + source: Optional[IssueTypeSource] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + references: 'SortedSet[XsUri]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) + + @staticmethod + def _cmp_issue(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, IssueType): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp_issue + return (self.type, c(self.id), c(self.name), c(self.description), c(self.source), tuple(self.references)) < ( + other.type, c(other.id), c(other.name), c(other.description), c(other.source), tuple(other.references)) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.type, self.id, self.name, self.description, self.source, tuple(self.references))) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/license.py b/cyclonedx/model/license.py index 9d32160e2..3ede1257f 100644 --- a/cyclonedx/model/license.py +++ b/cyclonedx/model/license.py @@ -21,24 +21,27 @@ """ from enum import Enum -from json import loads as json_loads from typing import TYPE_CHECKING, Any, Optional, Union from warnings import warn -from xml.etree.ElementTree import Element # nosec B405 -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str -from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import MutuallyExclusivePropertiesException -from ..exception.serialization import CycloneDxDeserializationException -from ..schema.schema import SchemaVersion1Dot5, SchemaVersion1Dot6, SchemaVersion1Dot7 +from ..serialization import ( + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_5_AND_LATER, + VERSIONS_1_6_AND_LATER, +) from . import AttachedText, XsUri from .bom_ref import BomRef -@serializable.serializable_enum class LicenseAcknowledgement(str, Enum): """ This is our internal representation of the `type_licenseAcknowledgementEnumerationType` ENUM type @@ -66,10 +69,12 @@ class LicenseAcknowledgement(str, Enum): """ -@serializable.serializable_class( - name='license', - ignore_unknown_during_deserialization=True -) +def _bom_ref_converter(value: Optional[Union[str, BomRef]]) -> BomRef: + """Convert string or BomRef to BomRef.""" + return _bom_ref_from_str(value) + + +@attrs.define(slots=False, on_setattr=attrs.setters.NO_OP) class DisjunctiveLicense: """ This is our internal representation of `licenseType` complex type that can be used in multiple places within @@ -78,302 +83,144 @@ class DisjunctiveLicense: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_licenseType """ - - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - id: Optional[str] = None, name: Optional[str] = None, - text: Optional[AttachedText] = None, url: Optional[XsUri] = None, - acknowledgement: Optional[LicenseAcknowledgement] = None, - ) -> None: - if not id and not name: + # Note: Either id or name must be provided, but not both + id: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + name: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_JSON_NAME: 'bom-ref', + } + ) + text: Optional[AttachedText] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + url: Optional[XsUri] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + acknowledgement: Optional[LicenseAcknowledgement] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_ATTR: True, + } + ) + _initialized: bool = attrs.field(default=False, init=False, repr=False, eq=False, hash=False) + + def __attrs_post_init__(self) -> None: + if not self.id and not self.name: raise MutuallyExclusivePropertiesException('Either `id` or `name` MUST be supplied') - if id and name: + if self.id and self.name: warn( 'Both `id` and `name` have been supplied - `name` will be ignored!', - category=RuntimeWarning, stacklevel=1 + category=RuntimeWarning, stacklevel=2 ) - self._bom_ref = _bom_ref_from_str(bom_ref) - self._id = id - self._name = name if not id else None - self._text = text - self._url = url - self._acknowledgement = acknowledgement - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - @serializable.json_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_sequence(1) - def id(self) -> Optional[str]: - """ - A SPDX license ID. - - .. note:: - See the list of expected values: - https://cyclonedx.org/docs/1.7/json/#components_items_licenses_items_license_id - - Returns: - `str` or `None` - """ - return self._id - - @id.setter - def id(self, id: Optional[str]) -> None: - self._id = id - if id is not None: - self._name = None - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - If SPDX does not define the license used, this field may be used to provide the license name. - - Returns: - `str` or `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - if name is not None: - self._id = None - - @property - @serializable.xml_sequence(2) - def text(self) -> Optional[AttachedText]: - """ - Specifies the optional full text of the attachment - - Returns: - `AttachedText` else `None` - """ - return self._text - - @text.setter - def text(self, text: Optional[AttachedText]) -> None: - self._text = text - - @property - @serializable.xml_sequence(3) - def url(self) -> Optional[XsUri]: - """ - The URL to the attachment file. If the attachment is a license or BOM, an externalReference should also be - specified for completeness. - - Returns: - `XsUri` or `None` - """ - return self._url - - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.view(SchemaVersion1Dot6) - # @serializable.xml_sequence(5) - # def licensing(self) -> ...: - # ... # TODO since CDX1.5 - # - # @licensing.setter - # def licensing(self, ...) -> None: - # ... # TODO since CDX1.5 - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.view(SchemaVersion1Dot6) - # @serializable.xml_sequence(6) - # def properties(self) -> ...: - # ... # TODO since CDX1.5 - # - # @licensing.setter - # def properties(self, ...) -> None: - # ... # TODO since CDX1.5 - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_attribute() - def acknowledgement(self) -> Optional[LicenseAcknowledgement]: - """ - Declared licenses and concluded licenses represent two different stages in the licensing process within - software development. - - Declared licenses refer to the initial intention of the software authors regarding the - licensing terms under which their code is released. On the other hand, concluded licenses are the result of a - comprehensive analysis of the project's codebase to identify and confirm the actual licenses of the components - used, which may differ from the initially declared licenses. While declared licenses provide an upfront - indication of the licensing intentions, concluded licenses offer a more thorough understanding of the actual - licensing within a project, facilitating proper compliance and risk management. Observed licenses are defined - in evidence.licenses. Observed licenses form the evidence necessary to substantiate a concluded license. - - Returns: - `LicenseAcknowledgement` or `None` - """ - return self._acknowledgement - - @acknowledgement.setter - def acknowledgement(self, acknowledgement: Optional[LicenseAcknowledgement]) -> None: - self._acknowledgement = acknowledgement - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self._acknowledgement, - self._id, self._name, - self._url, - self._text, - self._bom_ref.value, - )) + object.__setattr__(self, 'name', None) + object.__setattr__(self, '_initialized', True) + + def __setattr__(self, attr_name: str, value: Any) -> None: + # Handle mutual exclusivity between id and name (only after initialization) + if getattr(self, '_initialized', False): + if attr_name == 'id' and value is not None: + object.__setattr__(self, 'name', None) + elif attr_name == 'name' and value is not None: + object.__setattr__(self, 'id', None) + object.__setattr__(self, attr_name, value) def __eq__(self, other: object) -> bool: if isinstance(other, DisjunctiveLicense): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + return (self.acknowledgement, self.id, self.name, self.url, self.text, self.bom_ref.value) == ( + other.acknowledgement, other.id, other.name, other.url, other.text, other.bom_ref.value) + return NotImplemented + + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, DisjunctiveLicense): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return (c(self.acknowledgement), c(self.id), c(self.name), c(self.url), c(self.text), + c(self.bom_ref.value)) < ( + c(other.acknowledgement), c(other.id), c(other.name), c(other.url), c(other.text), + c(other.bom_ref.value)) if isinstance(other, LicenseExpression): return False # self after any LicenseExpression return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.acknowledgement, self.id, self.name, self.url, self.text, self.bom_ref.value)) def __repr__(self) -> str: - return f'' + return f'' -@serializable.serializable_class( - name='expression', - ignore_unknown_during_deserialization=True -) +@attrs.define class LicenseExpression: """ - This is our internal representation of `licenseType`'s expression type that can be used in multiple places within + This is our internal representation of `licenseType`'s expression type that can be used in multiple places within a CycloneDX BOM document. .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#components_items_licenses_items_expression """ - - def __init__( - self, value: str, *, - bom_ref: Optional[Union[str, BomRef]] = None, - acknowledgement: Optional[LicenseAcknowledgement] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self._value = value - self._acknowledgement = acknowledgement - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - @serializable.json_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the component elsewhere in the BOM. Every bom-ref MUST be - unique within the BOM. - - Returns: - `BomRef` - """ - return self._bom_ref - - @property - @serializable.xml_name('.') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - @serializable.json_name('expression') - def value(self) -> str: - """ - Value of this LicenseExpression. - - Returns: - `str` - """ - return self._value - - @value.setter - def value(self, value: str) -> None: - self._value = value - - @property - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_attribute() - def acknowledgement(self) -> Optional[LicenseAcknowledgement]: - """ - Declared licenses and concluded licenses represent two different stages in the licensing process within - software development. - - Declared licenses refer to the initial intention of the software authors regarding the - licensing terms under which their code is released. On the other hand, concluded licenses are the result of a - comprehensive analysis of the project's codebase to identify and confirm the actual licenses of the components - used, which may differ from the initially declared licenses. While declared licenses provide an upfront - indication of the licensing intentions, concluded licenses offer a more thorough understanding of the actual - licensing within a project, facilitating proper compliance and risk management. Observed licenses are defined - in evidence.licenses. Observed licenses form the evidence necessary to substantiate a concluded license. - - Returns: - `LicenseAcknowledgement` or `None` - """ - return self._acknowledgement - - @acknowledgement.setter - def acknowledgement(self, acknowledgement: Optional[LicenseAcknowledgement]) -> None: - self._acknowledgement = acknowledgement - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self._acknowledgement, - self._value, - self._bom_ref.value, - )) + value: str = attrs.field( + metadata={ + METADATA_KEY_XML_NAME: '.', + METADATA_KEY_JSON_NAME: 'expression', + } + ) + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_5_AND_LATER, + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + METADATA_KEY_JSON_NAME: 'bom-ref', + } + ) + acknowledgement: Optional[LicenseAcknowledgement] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_6_AND_LATER, + METADATA_KEY_XML_ATTR: True, + } + ) def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.acknowledgement, self.value, self.bom_ref.value)) def __eq__(self, other: object) -> bool: if isinstance(other, LicenseExpression): - return self.__comparable_tuple() == other.__comparable_tuple() + return (self.acknowledgement, self.value, self.bom_ref.value) == ( + other.acknowledgement, other.value, other.bom_ref.value) return False def __lt__(self, other: Any) -> bool: if isinstance(other, LicenseExpression): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.acknowledgement, self.value, self.bom_ref.value) < ( + other.acknowledgement, other.value, other.bom_ref.value) if isinstance(other, DisjunctiveLicense): return True # self before any DisjunctiveLicense return NotImplemented def __repr__(self) -> str: - return f'' + return f'' License = Union[LicenseExpression, DisjunctiveLicense] @@ -385,7 +232,6 @@ def __repr__(self) -> str: if TYPE_CHECKING: # pragma: no cover # workaround for https://github.com/python/mypy/issues/5264 - # this code path is taken when static code analysis or documentation tools runs through. class LicenseRepository(SortedSet[License]): """Collection of :class:`License`. @@ -414,86 +260,3 @@ class LicenseRepository(SortedSet): Denormalizers/deserializers will be thankful. The normalization/serialization process SHOULD take care of these facts and do what is needed. """ - - -class _LicenseRepositorySerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - @classmethod - def json_normalize(cls, o: LicenseRepository, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> Any: - if len(o) == 0: - return None - expression = next((li for li in o if isinstance(li, LicenseExpression)), None) - if expression: - # mixed license expression and license? this is an invalid constellation according to schema! - # see https://github.com/CycloneDX/specification/pull/205 - # but models need to allow it for backwards compatibility with JSON CDX < 1.5 - return [json_loads(expression.as_json(view_=view))] # type:ignore[attr-defined] - return [ - {'license': json_loads( - li.as_json( # type:ignore[attr-defined] - view_=view) - )} - for li in o - if isinstance(li, DisjunctiveLicense) - ] - - @classmethod - def json_denormalize(cls, o: list[dict[str, Any]], - **__: Any) -> LicenseRepository: - repo = LicenseRepository() - for li in o: - if 'license' in li: - repo.add(DisjunctiveLicense.from_json( # type:ignore[attr-defined] - li['license'])) - elif 'expression' in li: - repo.add(LicenseExpression.from_json( # type:ignore[attr-defined] - li - )) - else: - raise CycloneDxDeserializationException(f'unexpected: {li!r}') - return repo - - @classmethod - def xml_normalize(cls, o: LicenseRepository, *, - element_name: str, - view: Optional[type[serializable.ViewType]], - xmlns: Optional[str], - **__: Any) -> Optional[Element]: - if len(o) == 0: - return None - elem = Element(element_name) - expression = next((li for li in o if isinstance(li, LicenseExpression)), None) - if expression: - # mixed license expression and license? this is an invalid constellation according to schema! - # see https://github.com/CycloneDX/specification/pull/205 - # but models need to allow it for backwards compatibility with JSON CDX < 1.5 - elem.append(expression.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='expression', xmlns=xmlns)) - else: - elem.extend( - li.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='license', xmlns=xmlns) - for li in o - if isinstance(li, DisjunctiveLicense) - ) - return elem - - @classmethod - def xml_denormalize(cls, o: Element, - default_ns: Optional[str], - **__: Any) -> LicenseRepository: - repo = LicenseRepository() - for li in o: - tag = li.tag if default_ns is None else li.tag.replace(f'{{{default_ns}}}', '') - if tag == 'license': - repo.add(DisjunctiveLicense.from_xml( # type:ignore[attr-defined] - li, default_ns)) - elif tag == 'expression': - repo.add(LicenseExpression.from_xml( # type:ignore[attr-defined] - li, default_ns)) - else: - raise CycloneDxDeserializationException(f'unexpected: {li!r}') - return repo diff --git a/cyclonedx/model/lifecycle.py b/cyclonedx/model/lifecycle.py index b7aa062d3..9ea60b2b3 100644 --- a/cyclonedx/model/lifecycle.py +++ b/cyclonedx/model/lifecycle.py @@ -26,22 +26,14 @@ """ from enum import Enum -from json import loads as json_loads from typing import TYPE_CHECKING, Any, Optional, Union -from xml.etree.ElementTree import Element # nosec B405 -import py_serializable as serializable -from py_serializable.helpers import BaseHelper +import attrs from sortedcontainers import SortedSet -from .._internal.compare import ComparableTuple as _ComparableTuple -from ..exception.serialization import CycloneDxDeserializationException - -if TYPE_CHECKING: # pragma: no cover - from py_serializable import ViewType +from ..serialization import METADATA_KEY_XML_SEQUENCE -@serializable.serializable_enum class LifecyclePhase(str, Enum): """ Enum object that defines the permissible 'phase' for a Lifecycle according to the CycloneDX schema. @@ -58,7 +50,7 @@ class LifecyclePhase(str, Enum): DECOMMISSION = 'decommission' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class PredefinedLifecycle: """ Object that defines pre-defined phases in the product lifecycle. @@ -67,38 +59,23 @@ class PredefinedLifecycle: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#tab-pane_metadata_lifecycles_items_oneOf_i0 """ - - def __init__(self, phase: LifecyclePhase) -> None: - self._phase = phase - - @property - def phase(self) -> LifecyclePhase: - return self._phase - - @phase.setter - def phase(self, phase: LifecyclePhase) -> None: - self._phase = phase + phase: LifecyclePhase def __hash__(self) -> int: - return hash(self._phase) - - def __eq__(self, other: object) -> bool: - if isinstance(other, PredefinedLifecycle): - return self._phase == other._phase - return False + return hash(self.phase) def __lt__(self, other: Any) -> bool: if isinstance(other, PredefinedLifecycle): - return self._phase < other._phase + return self.phase.value < other.phase.value if isinstance(other, NamedLifecycle): return True # put PredefinedLifecycle before any NamedLifecycle return NotImplemented def __repr__(self) -> str: - return f'' + return f'' -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@attrs.define class NamedLifecycle: """ Object that defines custom state in the product lifecycle. @@ -107,65 +84,31 @@ class NamedLifecycle: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/json/#tab-pane_metadata_lifecycles_items_oneOf_i1 """ - - def __init__(self, name: str, *, description: Optional[str] = None) -> None: - self._name = name - self._description = description - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> str: - """ - Name of the lifecycle phase. - - Returns: - `str` - """ - return self._name - - @name.setter - def name(self, name: str) -> None: - self._name = name - - @property - @serializable.xml_sequence(2) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def description(self) -> Optional[str]: - """ - Description of the lifecycle phase. - - Returns: - `str` - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self._name, self._description - )) + name: str = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + description: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((self.name, self.description)) - def __eq__(self, other: object) -> bool: - if isinstance(other, NamedLifecycle): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, NamedLifecycle): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.name, self._cmp(self.description)) < (other.name, self._cmp(other.description)) if isinstance(other, PredefinedLifecycle): return False # put NamedLifecycle after any PredefinedLifecycle return NotImplemented def __repr__(self) -> str: - return f'' + return f'' Lifecycle = Union[PredefinedLifecycle, NamedLifecycle] @@ -177,7 +120,6 @@ def __repr__(self) -> str: if TYPE_CHECKING: # pragma: no cover # workaround for https://github.com/python/mypy/issues/5264 - # this code path is taken when static code analysis or documentation tools runs through. class LifecycleRepository(SortedSet[Lifecycle]): """Collection of :class:`Lifecycle`. @@ -189,62 +131,3 @@ class LifecycleRepository(SortedSet): This is a `set`, not a `list`. Order MUST NOT matter here. """ - - -class _LifecycleRepositoryHelper(BaseHelper): - @classmethod - def json_normalize(cls, o: LifecycleRepository, *, - view: Optional[type['ViewType']], - **__: Any) -> Any: - if len(o) == 0: - return None - return [json_loads(li.as_json( # type:ignore[union-attr] - view_=view)) for li in o] - - @classmethod - def json_denormalize(cls, o: list[dict[str, Any]], - **__: Any) -> LifecycleRepository: - repo = LifecycleRepository() - for li in o: - if 'phase' in li: - repo.add(PredefinedLifecycle.from_json( # type:ignore[attr-defined] - li)) - elif 'name' in li: - repo.add(NamedLifecycle.from_json( # type:ignore[attr-defined] - li)) - else: - raise CycloneDxDeserializationException(f'unexpected: {li!r}') - return repo - - @classmethod - def xml_normalize(cls, o: LifecycleRepository, *, - element_name: str, - view: Optional[type['ViewType']], - xmlns: Optional[str], - **__: Any) -> Optional[Element]: - if len(o) == 0: - return None - elem = Element(element_name) - for li in o: - elem.append(li.as_xml( # type:ignore[union-attr] - view_=view, as_string=False, element_name='lifecycle', xmlns=xmlns)) - return elem - - @classmethod - def xml_denormalize(cls, o: Element, - default_ns: Optional[str], - **__: Any) -> LifecycleRepository: - repo = LifecycleRepository() - ns_map = {'bom': default_ns or ''} - # Do not iterate over `o` and do not check for expected `.tag` of items. - # This check could have been done by schema validators before even deserializing. - for li in o.iterfind('bom:lifecycle', ns_map): - if li.find('bom:phase', ns_map) is not None: - repo.add(PredefinedLifecycle.from_xml( # type:ignore[attr-defined] - li, default_ns)) - elif li.find('bom:name', ns_map) is not None: - repo.add(NamedLifecycle.from_xml( # type:ignore[attr-defined] - li, default_ns)) - else: - raise CycloneDxDeserializationException(f'unexpected content: {li!r}') - return repo diff --git a/cyclonedx/model/release_note.py b/cyclonedx/model/release_note.py index 890e1b097..0bf1fed6e 100644 --- a/cyclonedx/model/release_note.py +++ b/cyclonedx/model/release_note.py @@ -17,17 +17,29 @@ from collections.abc import Iterable from datetime import datetime -from typing import Optional +from typing import Any, Optional -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet -from .._internal.compare import ComparableTuple as _ComparableTuple from ..model import Note, Property, XsUri from ..model.issue import IssueType +from ..serialization import METADATA_KEY_XML_SEQUENCE -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _sortedset_factory() -> SortedSet: + return SortedSet() + + +def _sortedset_converter(value: Any) -> SortedSet: + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + return SortedSet(value) + + +@attrs.define class ReleaseNotes: """ This is our internal representation of a `releaseNotesType` for a Component in a BOM. @@ -35,228 +47,74 @@ class ReleaseNotes: .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_releaseNotesType """ - - def __init__( - self, *, - type: str, title: Optional[str] = None, - featured_image: Optional[XsUri] = None, - social_image: Optional[XsUri] = None, - description: Optional[str] = None, - timestamp: Optional[datetime] = None, - aliases: Optional[Iterable[str]] = None, - tags: Optional[Iterable[str]] = None, - resolves: Optional[Iterable[IssueType]] = None, - notes: Optional[Iterable[Note]] = None, - properties: Optional[Iterable[Property]] = None, - ) -> None: - self.type = type - self.title = title - self.featured_image = featured_image - self.social_image = social_image - self.description = description - self.timestamp = timestamp - self.aliases = aliases or [] - self.tags = tags or [] - self.resolves = resolves or [] - self.notes = notes or [] - self.properties = properties or [] - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def type(self) -> str: - """ - The software versioning type. - - It is **RECOMMENDED** that the release type use one of 'major', 'minor', 'patch', 'pre-release', or 'internal'. - - Representing all possible software release types is not practical, so standardizing on the recommended values, - whenever possible, is strongly encouraged. - - * **major** = A major release may contain significant changes or may introduce breaking changes. - * **minor** = A minor release, also known as an update, may contain a smaller number of changes than major - releases. - * **patch** = Patch releases are typically unplanned and may resolve defects or important security issues. - * **pre-release** = A pre-release may include alpha, beta, or release candidates and typically have limited - support. They provide the ability to preview a release prior to its general availability. - * **internal** = Internal releases are not for public consumption and are intended to be used exclusively by the - project or manufacturer that produced it. - """ - return self._type - - @type.setter - def type(self, type: str) -> None: - self._type = type - - @property - @serializable.xml_sequence(2) - def title(self) -> Optional[str]: - """ - The title of the release. - """ - return self._title - - @title.setter - def title(self, title: Optional[str]) -> None: - self._title = title - - @property - @serializable.xml_sequence(3) - def featured_image(self) -> Optional[XsUri]: - """ - The URL to an image that may be prominently displayed with the release note. - """ - return self._featured_image - - @featured_image.setter - def featured_image(self, featured_image: Optional[XsUri]) -> None: - self._featured_image = featured_image - - @property - @serializable.xml_sequence(4) - def social_image(self) -> Optional[XsUri]: - """ - The URL to an image that may be used in messaging on social media platforms. - """ - return self._social_image - - @social_image.setter - def social_image(self, social_image: Optional[XsUri]) -> None: - self._social_image = social_image - - @property - @serializable.xml_sequence(5) - def description(self) -> Optional[str]: - """ - A short description of the release. - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(6) - def timestamp(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the release note was created. - """ - return self._timestamp - - @timestamp.setter - def timestamp(self, timestamp: Optional[datetime]) -> None: - self._timestamp = timestamp - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'alias') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - @serializable.xml_sequence(7) - def aliases(self) -> 'SortedSet[str]': - """ - One or more alternate names the release may be referred to. This may include unofficial terms used by - development and marketing teams (e.g. code names). - - Returns: - Set of `str` - """ - return self._aliases - - @aliases.setter - def aliases(self, aliases: Iterable[str]) -> None: - self._aliases = SortedSet(aliases) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'tag') - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - @serializable.xml_sequence(8) - def tags(self) -> 'SortedSet[str]': - """ - One or more tags that may aid in search or retrieval of the release note. - - Returns: - Set of `str` - """ - return self._tags - - @tags.setter - def tags(self, tags: Iterable[str]) -> None: - self._tags = SortedSet(tags) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'issue') - @serializable.xml_sequence(9) - def resolves(self) -> 'SortedSet[IssueType]': - """ - A collection of issues that have been resolved. - - Returns: - Set of `IssueType` - """ - return self._resolves - - @resolves.setter - def resolves(self, resolves: Iterable[IssueType]) -> None: - self._resolves = SortedSet(resolves) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'note') - @serializable.xml_sequence(10) - def notes(self) -> 'SortedSet[Note]': - """ - Zero or more release notes containing the locale and content. Multiple note elements may be specified to support - release notes in a wide variety of languages. - - Returns: - Set of `Note` - """ - return self._notes - - @notes.setter - def notes(self, notes: Iterable[Note]) -> None: - self._notes = SortedSet(notes) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(11) - def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a name-value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. Unlike - key-value stores, properties support duplicate names, each potentially having different values. - - Returns: - Set of `Property` - """ - return self._properties - - @properties.setter - def properties(self, properties: Iterable[Property]) -> None: - self._properties = SortedSet(properties) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.type, self.title, self.featured_image, self.social_image, self.description, self.timestamp, - _ComparableTuple(self.aliases), - _ComparableTuple(self.tags), - _ComparableTuple(self.resolves), - _ComparableTuple(self.notes), - _ComparableTuple(self.properties) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, ReleaseNotes): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + type: str = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + title: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + featured_image: Optional[XsUri] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + social_image: Optional[XsUri] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + description: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) + timestamp: Optional[datetime] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 6} + ) + aliases: 'SortedSet[str]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 7} + ) + tags: 'SortedSet[str]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 8} + ) + resolves: 'SortedSet[IssueType]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 9} + ) + notes: 'SortedSet[Note]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 10} + ) + properties: 'SortedSet[Property]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 11} + ) def __lt__(self, other: object) -> bool: if isinstance(other, ReleaseNotes): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + self.type, self.title, self.featured_image, self.social_image, + self.description, self.timestamp, tuple(self.aliases), tuple(self.tags), + tuple(self.resolves), tuple(self.notes), tuple(self.properties) + ) < ( + other.type, other.title, other.featured_image, other.social_image, + other.description, other.timestamp, tuple(other.aliases), tuple(other.tags), + tuple(other.resolves), tuple(other.notes), tuple(other.properties) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.type, self.title, self.featured_image, self.social_image, + self.description, self.timestamp, tuple(self.aliases), tuple(self.tags), + tuple(self.resolves), tuple(self.notes), tuple(self.properties) + )) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/service.py b/cyclonedx/model/service.py index 105973703..03737539a 100644 --- a/cyclonedx/model/service.py +++ b/cyclonedx/model/service.py @@ -24,366 +24,204 @@ """ +from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str +from .release_note import ReleaseNotes +from .license import License, LicenseRepository +from .dependency import Dependable +from .contact import OrganizationalEntity +from .bom_ref import BomRef +from . import DataClassification, ExternalReference, Property, XsUri +from ..serialization import ( + METADATA_KEY_JSON_NAME, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_3_AND_LATER, + VERSIONS_1_4_AND_LATER, +) from collections.abc import Iterable from typing import Any, Optional, Union -import py_serializable as serializable +import attrs from sortedcontainers import SortedSet -from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str -from .._internal.compare import ComparableTuple as _ComparableTuple -from ..schema.schema import ( - SchemaVersion1Dot3, - SchemaVersion1Dot4, - SchemaVersion1Dot5, - SchemaVersion1Dot6, - SchemaVersion1Dot7, -) -from . import DataClassification, ExternalReference, Property, XsUri -from .bom_ref import BomRef -from .contact import OrganizationalEntity -from .dependency import Dependable -from .license import License, LicenseRepository, _LicenseRepositorySerializationHelper -from .release_note import ReleaseNotes - - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) -class Service(Dependable): - """ - Class that models the `service` complex type in the CycloneDX schema. - - .. note:: - See the CycloneDX schema: https://cyclonedx.org/docs/1.7/xml/#type_service - """ - - def __init__( - self, *, - name: str, - bom_ref: Optional[Union[str, BomRef]] = None, - provider: Optional[OrganizationalEntity] = None, - group: Optional[str] = None, - version: Optional[str] = None, - description: Optional[str] = None, - endpoints: Optional[Iterable[XsUri]] = None, - authenticated: Optional[bool] = None, - x_trust_boundary: Optional[bool] = None, - data: Optional[Iterable[DataClassification]] = None, - licenses: Optional[Iterable[License]] = None, - external_references: Optional[Iterable[ExternalReference]] = None, - properties: Optional[Iterable[Property]] = None, - services: Optional[Iterable['Service']] = None, - release_notes: Optional[ReleaseNotes] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.provider = provider - self.group = group - self.name = name - self.version = version - self.description = description - self.endpoints = endpoints or [] - self.authenticated = authenticated - self.x_trust_boundary = x_trust_boundary - self.data = data or [] - self.licenses = licenses or [] - self.external_references = external_references or [] - self.services = services or [] - self.release_notes = release_notes - self.properties = properties or [] - - @property - @serializable.json_name('bom-ref') - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') - def bom_ref(self) -> BomRef: - """ - An optional identifier which can be used to reference the service elsewhere in the BOM. Uniqueness is enforced - within all elements and children of the root-level bom element. - - Returns: - `BomRef` unique identifier for this Service - """ - return self._bom_ref - - @property - @serializable.xml_sequence(1) - def provider(self) -> Optional[OrganizationalEntity]: - """ - Get the organization that provides the service. - - Returns: - `OrganizationalEntity` if set else `None` - """ - return self._provider - - @provider.setter - def provider(self, provider: Optional[OrganizationalEntity]) -> None: - self._provider = provider - - @property - @serializable.xml_sequence(2) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def group(self) -> Optional[str]: - """ - The grouping name, namespace, or identifier. This will often be a shortened, single name of the company or - project that produced the service or domain name. Whitespace and special characters should be avoided. - - Returns: - `str` if provided else `None` - """ - return self._group - - @group.setter - def group(self, group: Optional[str]) -> None: - self._group = group - - @property - @serializable.xml_sequence(3) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> str: - """ - The name of the service. This will often be a shortened, single name of the service. - - Returns: - `str` - """ - return self._name - - @name.setter - def name(self, name: str) -> None: - self._name = name - - @property - @serializable.xml_sequence(4) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def version(self) -> Optional[str]: - """ - The service version. - Returns: - `str` if set else `None` - """ - return self._version +def _sortedset_converter(value: Any) -> SortedSet: + """Converter to ensure values are always SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version - @property - @serializable.xml_sequence(5) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def description(self) -> Optional[str]: - """ - Specifies a description for the service. +def _bom_ref_converter(value: Optional[Union[str, BomRef]]) -> BomRef: + """Convert string or BomRef to BomRef.""" + return _bom_ref_from_str(value) - Returns: - `str` if set else `None` - """ - return self._description - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description +def _sortedset_factory() -> SortedSet: + return SortedSet() - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'endpoint') - @serializable.xml_sequence(6) - def endpoints(self) -> 'SortedSet[XsUri]': - """ - A list of endpoints URI's this service provides. - Returns: - Set of `XsUri` - """ - return self._endpoints +def _license_repository_factory() -> LicenseRepository: + return LicenseRepository() - @endpoints.setter - def endpoints(self, endpoints: Iterable[XsUri]) -> None: - self._endpoints = SortedSet(endpoints) - @property - @serializable.xml_sequence(7) - def authenticated(self) -> Optional[bool]: - """ - A boolean value indicating if the service requires authentication. A value of true indicates the service - requires authentication prior to use. +def _license_repository_converter(value: Any) -> LicenseRepository: + """Convert a value to LicenseRepository.""" + if value is None: + return LicenseRepository() + if isinstance(value, LicenseRepository): + return value + # Convert generators, lists, etc. to LicenseRepository + return LicenseRepository(value) - A value of false indicates the service does not require authentication. - Returns: - `bool` if set else `None` - """ - return self._authenticated - - @authenticated.setter - def authenticated(self, authenticated: Optional[bool]) -> None: - self._authenticated = authenticated - - @property - @serializable.json_name('x-trust-boundary') - @serializable.xml_name('x-trust-boundary') - @serializable.xml_sequence(8) - def x_trust_boundary(self) -> Optional[bool]: - """ - A boolean value indicating if use of the service crosses a trust zone or boundary. A value of true indicates - that by using the service, a trust boundary is crossed. - - A value of false indicates that by using the service, a trust boundary is not crossed. - - Returns: - `bool` if set else `None` - """ - return self._x_trust_boundary - - @x_trust_boundary.setter - def x_trust_boundary(self, x_trust_boundary: Optional[bool]) -> None: - self._x_trust_boundary = x_trust_boundary - - # @property - # ... - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(9) - # def trust_zone(self) -> ...: - # ... # since CDX1.5 - # - # @trust_zone.setter - # def trust_zone(self, ...) -> None: - # ... # since CDX1.5 - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'classification') - @serializable.xml_sequence(10) - def data(self) -> 'SortedSet[DataClassification]': - """ - Specifies the data classification. - - Returns: - Set of `DataClassification` - """ - # TODO since CDX1.5 also supports `dataflow`, not only `DataClassification` - return self._data - - @data.setter - def data(self, data: Iterable[DataClassification]) -> None: - self._data = SortedSet(data) - - @property - @serializable.type_mapping(_LicenseRepositorySerializationHelper) - @serializable.xml_sequence(11) - def licenses(self) -> LicenseRepository: - """ - A optional list of statements about how this Service is licensed. - - Returns: - Set of `LicenseChoice` - """ - # TODO since CDX1.5 also supports `dataflow`, not only `DataClassification` - return self._licenses - - @licenses.setter - def licenses(self, licenses: Iterable[License]) -> None: - self._licenses = LicenseRepository(licenses) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(12) - def external_references(self) -> 'SortedSet[ExternalReference]': - """ - Provides the ability to document external references related to the Service. - - Returns: - Set of `ExternalReference` - """ - return self._external_references - - @external_references.setter - def external_references(self, external_references: Iterable[ExternalReference]) -> None: - self._external_references = SortedSet(external_references) - - @property - @serializable.view(SchemaVersion1Dot3) - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(13) - def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Return: - Set of `Property` - """ - return self._properties - - @properties.setter - def properties(self, properties: Iterable[Property]) -> None: - self._properties = SortedSet(properties) - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'service') - @serializable.xml_sequence(14) - def services(self) -> "SortedSet['Service']": - """ - A list of services included or deployed behind the parent service. - - This is not a dependency tree. - - It provides a way to specify a hierarchical representation of service assemblies. - - Returns: - Set of `Service` - """ - return self._services - - @services.setter - def services(self, services: Iterable['Service']) -> None: - self._services = SortedSet(services) - - @property - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(15) - def release_notes(self) -> Optional[ReleaseNotes]: - """ - Specifies optional release notes. - - Returns: - `ReleaseNotes` or `None` - """ - return self._release_notes - - @release_notes.setter - def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None: - self._release_notes = release_notes +@attrs.define +class Service(Dependable): + """ + Class that models the `service` complex type in the CycloneDX schema. - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.group, self.name, self.version, - self.bom_ref.value, - self.provider, self.description, - self.authenticated, _ComparableTuple(self.data), _ComparableTuple(self.endpoints), - _ComparableTuple(self.external_references), _ComparableTuple(self.licenses), - _ComparableTuple(self.properties), self.release_notes, _ComparableTuple(self.services), - self.x_trust_boundary - )) + .. note:: + See the CycloneDX schema: https://cyclonedx.org/docs/1.7/xml/#type_service + """ + name: str = attrs.field( + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + bom_ref: BomRef = attrs.field( + factory=BomRef, + converter=_bom_ref_converter, + metadata={ + METADATA_KEY_JSON_NAME: 'bom-ref', + METADATA_KEY_XML_ATTR: True, + METADATA_KEY_XML_NAME: 'bom-ref', + } + ) + provider: Optional[OrganizationalEntity] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + group: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + version: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + description: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 5} + ) + endpoints: 'SortedSet[XsUri]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 6} + ) + authenticated: Optional[bool] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 7} + ) + x_trust_boundary: Optional[bool] = attrs.field( + default=None, + metadata={ + METADATA_KEY_JSON_NAME: 'x-trust-boundary', + METADATA_KEY_XML_NAME: 'x-trust-boundary', + METADATA_KEY_XML_SEQUENCE: 8, + } + ) + data: 'SortedSet[DataClassification]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 10} + ) + licenses: LicenseRepository = attrs.field( + factory=_license_repository_factory, + converter=_license_repository_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 11} + ) + external_references: 'SortedSet[ExternalReference]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 12} + ) + properties: 'SortedSet[Property]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_3_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 13, + } + ) + services: 'SortedSet[Service]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 14} + ) + release_notes: Optional[ReleaseNotes] = attrs.field( + default=None, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_4_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 15, + } + ) def __eq__(self, other: object) -> bool: if isinstance(other, Service): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + return ( + self.group, self.name, self.version, self.bom_ref.value, + self.provider, self.description, self.authenticated, + tuple(self.data), tuple(self.endpoints), tuple(self.external_references), + tuple(self.licenses), tuple(self.properties), self.release_notes, + tuple(self.services), self.x_trust_boundary + ) == ( + other.group, other.name, other.version, other.bom_ref.value, + other.provider, other.description, other.authenticated, + tuple(other.data), tuple(other.endpoints), tuple(other.external_references), + tuple(other.licenses), tuple(other.properties), other.release_notes, + tuple(other.services), other.x_trust_boundary + ) + return NotImplemented + + @staticmethod + def _none_safe(val: Any) -> tuple: + """Convert value to tuple for safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Service): - return self.__comparable_tuple() < other.__comparable_tuple() + # Use _none_safe to handle None values in comparisons + return ( + self._none_safe(self.group), self.name, self._none_safe(self.version), + self._none_safe(self.bom_ref.value), + self._none_safe(self.provider), self._none_safe(self.description), + self._none_safe(self.authenticated), + tuple(self.data), tuple(self.endpoints), tuple(self.external_references), + tuple(self.licenses), tuple(self.properties), self.release_notes, + tuple(self.services), self._none_safe(self.x_trust_boundary) + ) < ( + self._none_safe(other.group), other.name, self._none_safe(other.version), + self._none_safe(other.bom_ref.value), + self._none_safe(other.provider), self._none_safe(other.description), + self._none_safe(other.authenticated), + tuple(other.data), tuple(other.endpoints), tuple(other.external_references), + tuple(other.licenses), tuple(other.properties), other.release_notes, + tuple(other.services), self._none_safe(other.x_trust_boundary) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.group, self.name, self.version, self.bom_ref.value, + self.provider, self.description, self.authenticated, + tuple(self.data), tuple(self.endpoints), tuple(self.external_references), + tuple(self.licenses), tuple(self.properties), self.release_notes, + tuple(self.services), self.x_trust_boundary + )) def __repr__(self) -> str: return f'' diff --git a/cyclonedx/model/tool.py b/cyclonedx/model/tool.py index 5ef648c71..7e9af561d 100644 --- a/cyclonedx/model/tool.py +++ b/cyclonedx/model/tool.py @@ -18,26 +18,36 @@ from collections.abc import Iterable from itertools import chain -from typing import TYPE_CHECKING, Any, Optional, Union +from typing import TYPE_CHECKING, Any, Optional from warnings import warn -from xml.etree.ElementTree import Element # nosec B405 -import py_serializable as serializable -from py_serializable.helpers import BaseHelper +import attrs from sortedcontainers import SortedSet -from .._internal.compare import ComparableTuple as _ComparableTuple -from ..schema import SchemaVersion -from ..schema.schema import SchemaVersion1Dot4, SchemaVersion1Dot5, SchemaVersion1Dot6, SchemaVersion1Dot7 -from . import ExternalReference, HashType, _HashTypeRepositorySerializationHelper -from .component import Component -from .service import Service +from ..serialization import METADATA_KEY_VERSIONS, METADATA_KEY_XML_SEQUENCE, VERSIONS_1_4_AND_LATER +from . import ExternalReference, HashType if TYPE_CHECKING: # pragma: no cover - from py_serializable import ObjectMetadataLibrary, ViewType + from .component import Component + from .service import Service -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _sortedset_factory() -> SortedSet: + return SortedSet() + + +def _sortedset_converter(value: Any) -> SortedSet: + """Convert a value to SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, (list, tuple, set, frozenset)): + return SortedSet(value) + return SortedSet([value]) + + +@attrs.define class Tool: """ This is our internal representation of the `toolType` complex type within the CycloneDX standard. @@ -50,124 +60,54 @@ class Tool: .. note:: See the CycloneDX Schema for toolType: https://cyclonedx.org/docs/1.7/xml/#type_toolType """ + vendor: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 1} + ) + name: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 2} + ) + version: Optional[str] = attrs.field( + default=None, + metadata={METADATA_KEY_XML_SEQUENCE: 3} + ) + hashes: 'SortedSet[HashType]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={METADATA_KEY_XML_SEQUENCE: 4} + ) + external_references: 'SortedSet[ExternalReference]' = attrs.field( + factory=_sortedset_factory, + converter=_sortedset_converter, + metadata={ + METADATA_KEY_VERSIONS: VERSIONS_1_4_AND_LATER, + METADATA_KEY_XML_SEQUENCE: 5, + } + ) - def __init__( - self, *, - vendor: Optional[str] = None, - name: Optional[str] = None, - version: Optional[str] = None, - hashes: Optional[Iterable[HashType]] = None, - external_references: Optional[Iterable[ExternalReference]] = None, - ) -> None: - self.vendor = vendor - self.name = name - self.version = version - self.hashes = hashes or () - self.external_references = external_references or () - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def vendor(self) -> Optional[str]: - """ - The name of the vendor who created the tool. - - Returns: - `str` if set else `None` - """ - return self._vendor - - @vendor.setter - def vendor(self, vendor: Optional[str]) -> None: - self._vendor = vendor - - @property - @serializable.xml_sequence(2) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - The name of the tool. - - Returns: - `str` if set else `None` - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name - - @property - @serializable.xml_sequence(3) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def version(self) -> Optional[str]: - """ - The version of the tool. - - Returns: - `str` if set else `None` - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version - - @property - @serializable.type_mapping(_HashTypeRepositorySerializationHelper) - @serializable.xml_sequence(4) - def hashes(self) -> 'SortedSet[HashType]': - """ - The hashes of the tool (if applicable). - - Returns: - Set of `HashType` - """ - return self._hashes - - @hashes.setter - def hashes(self, hashes: Iterable[HashType]) -> None: - self._hashes = SortedSet(hashes) - - @property - @serializable.view(SchemaVersion1Dot4) - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(5) - def external_references(self) -> 'SortedSet[ExternalReference]': - """ - External References provides a way to document systems, sites, and information that may be relevant but which - are not included with the BOM. - - Returns: - Set of `ExternalReference` - """ - return self._external_references - - @external_references.setter - def external_references(self, external_references: Iterable[ExternalReference]) -> None: - self._external_references = SortedSet(external_references) - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.vendor, self.name, self.version, - _ComparableTuple(self.hashes), _ComparableTuple(self.external_references) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Tool): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, Tool): - return self.__comparable_tuple() < other.__comparable_tuple() + c = self._cmp + return ( + c(self.vendor), c(self.name), c(self.version), + tuple(self.hashes), tuple(self.external_references) + ) < ( + c(other.vendor), c(other.name), c(other.version), + tuple(other.hashes), tuple(other.external_references) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash(( + self.vendor, self.name, self.version, + tuple(self.hashes), tuple(self.external_references) + )) def __repr__(self) -> str: return f'' @@ -199,15 +139,19 @@ class ToolRepository: def __init__( self, *, - components: Optional[Iterable[Component]] = None, - services: Optional[Iterable[Service]] = None, + components: Optional[Iterable['Component']] = None, + services: Optional[Iterable['Service']] = None, # Deprecated since v1.5 tools: Optional[Iterable[Tool]] = None ) -> None: - self.components = components or () - self.services = services or () - # spec-deprecated properties below - self.tools = tools or () + self._components: SortedSet = SortedSet(components or ()) + self._services: SortedSet = SortedSet(services or ()) + self._tools: SortedSet = SortedSet() + if tools: + warn('`@.tools` is deprecated from CycloneDX v1.5 onwards. ' + 'Please use `@.components` and `@.services` instead.', + DeprecationWarning) + self._tools = SortedSet(tools) @property def components(self) -> 'SortedSet[Component]': @@ -218,7 +162,7 @@ def components(self) -> 'SortedSet[Component]': return self._components @components.setter - def components(self, components: Iterable[Component]) -> None: + def components(self, components: Iterable['Component']) -> None: self._components = SortedSet(components) @property @@ -230,7 +174,7 @@ def services(self) -> 'SortedSet[Service]': return self._services @services.setter - def services(self, services: Iterable[Service]) -> None: + def services(self, services: Iterable['Service']) -> None: self._services = SortedSet(services) @property @@ -246,136 +190,40 @@ def tools(self, tools: Iterable[Tool]) -> None: self._tools = SortedSet(tools) def __len__(self) -> int: - return len(self._tools) \ - + len(self._components) \ - + len(self._services) + return len(self._tools) + len(self._components) + len(self._services) def __bool__(self) -> bool: - return len(self._tools) > 0 \ - or len(self._components) > 0 \ - or len(self._services) > 0 - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self._tools), - _ComparableTuple(self._components), - _ComparableTuple(self._services) - )) + return len(self._tools) > 0 or len(self._components) > 0 or len(self._services) > 0 def __eq__(self, other: object) -> bool: if isinstance(other, ToolRepository): - return self.__comparable_tuple() == other.__comparable_tuple() + return ( + tuple(self._tools), tuple(self._components), tuple(self._services) + ) == ( + tuple(other._tools), tuple(other._components), tuple(other._services) + ) return False def __lt__(self, other: object) -> bool: if isinstance(other, ToolRepository): - return self.__comparable_tuple() < other.__comparable_tuple() + return ( + tuple(self._tools), tuple(self._components), tuple(self._services) + ) < ( + tuple(other._tools), tuple(other._components), tuple(other._services) + ) return NotImplemented def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((tuple(self._tools), tuple(self._components), tuple(self._services))) + def all_as_tools(self) -> 'SortedSet[Tool]': + """Get all tools, components, and services as Tool objects.""" + # Import here to avoid circular imports + from .component import Component + from .service import Service -class _ToolRepositoryHelper(BaseHelper): - - @staticmethod - 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), + self.tools, + map(Tool.from_component, self.components), + map(Tool.from_service, self.services), )) - - @staticmethod - def __supports_components_and_services(view: Any) -> bool: - try: - return view is not None and view().schema_version_enum >= SchemaVersion.V1_5 - except Exception: # pragma: no cover - return False - - @classmethod - 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): - 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) - if o.services: - elem['services'] = tuple(o.services) - return elem or None - - @classmethod - def json_denormalize(cls, o: Union[list[dict[str, Any]], dict[str, Any]], - **__: Any) -> ToolRepository: - tools = None - components = None - services = None - if isinstance(o, dict): - components = map(lambda c: Component.from_json( # type:ignore[attr-defined] - c), o.get('components', ())) - services = map(lambda s: Service.from_json( # type:ignore[attr-defined] - s), o.get('services', ())) - elif isinstance(o, Iterable): - tools = map(lambda t: Tool.from_json( # type:ignore[attr-defined] - t), o) - return ToolRepository(components=components, services=services, tools=tools) - - @classmethod - def xml_normalize(cls, o: ToolRepository, *, - element_name: str, - view: Optional[type['ViewType']], - xmlns: Optional[str], - **__: Any) -> Optional[Element]: - elem = Element(element_name) - if len(o.tools) > 0 or not cls.__supports_components_and_services(view): - elem.extend( - ti.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='tool', xmlns=xmlns) - for ti in cls.__all_as_tools(o) - ) - else: - if o.components: - elem_c = Element(f'{{{xmlns}}}components' if xmlns else 'components') - elem_c.extend( - ci.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='component', xmlns=xmlns) - for ci in o.components) - elem.append(elem_c) - if o.services: - elem_s = Element(f'{{{xmlns}}}services' if xmlns else 'services') - elem_s.extend( - si.as_xml( # type:ignore[attr-defined] - view_=view, as_string=False, element_name='service', xmlns=xmlns) - for si in o.services) - elem.append(elem_s) - return elem \ - if len(elem) > 0 \ - else None - - @classmethod - def xml_denormalize(cls, o: Element, *, - default_ns: Optional[str], - prop_info: 'ObjectMetadataLibrary.SerializableProperty', - ctx: type[Any], - **kwargs: Any) -> ToolRepository: - ns_map = {'bom': default_ns or ''} - # Do not iterate over `o` and do not check for expected `.tag` of items. - # This check could have been done by schema validators before even deserializing. - tools = None - components = None - services = None - ts = o.findall('bom:tool', ns_map) - if len(ts) > 0: - tools = map(lambda t: Tool.from_xml( # type:ignore[attr-defined] - t, default_ns), ts) - else: - components = map(lambda c: Component.from_xml( # type:ignore[attr-defined] - c, default_ns), o.iterfind('./bom:components/bom:component', ns_map)) - services = map(lambda s: Service.from_xml( # type:ignore[attr-defined] - s, default_ns), o.iterfind('./bom:services/bom:service', ns_map)) - return ToolRepository(components=components, services=services, tools=tools) diff --git a/cyclonedx/model/vulnerability.py b/cyclonedx/model/vulnerability.py index 5f3bf0240..3989b2439 100644 --- a/cyclonedx/model/vulnerability.py +++ b/cyclonedx/model/vulnerability.py @@ -28,6 +28,15 @@ See the CycloneDX Schema extension definition https://cyclonedx.org/docs/1.7/xml/#type_vulnerabilitiesType """ +from .contact import OrganizationalContact, OrganizationalEntity +from ..serialization import ALL_VERSIONS, VERSIONS_1_4_AND_LATER, VERSIONS_1_5_AND_LATER +from .tool import Tool, ToolRepository +from .impact_analysis import ( + ImpactAnalysisAffectedStatus, + ImpactAnalysisJustification, + ImpactAnalysisResponse, + ImpactAnalysisState, +) import re import sys from collections.abc import Iterable @@ -41,26 +50,29 @@ else: from typing_extensions import deprecated -import py_serializable as serializable +from attrs import Factory, define, field from sortedcontainers import SortedSet from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import MutuallyExclusivePropertiesException, NoPropertiesProvidedException -from ..schema.schema import SchemaVersion1Dot4, SchemaVersion1Dot5, SchemaVersion1Dot6, SchemaVersion1Dot7 +from ..schema import SchemaVersion from . import Property, XsUri from .bom_ref import BomRef -from .contact import OrganizationalContact, OrganizationalEntity -from .impact_analysis import ( - ImpactAnalysisAffectedStatus, - ImpactAnalysisJustification, - ImpactAnalysisResponse, - ImpactAnalysisState, -) -from .tool import Tool, ToolRepository, _ToolRepositoryHelper -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +def _sortedset_converter(value: Any) -> SortedSet: + """Convert a value to SortedSet.""" + if value is None: + return SortedSet() + if isinstance(value, SortedSet): + return value + if isinstance(value, Iterable) and not isinstance(value, (str, bytes, dict)): + return SortedSet(value) + return SortedSet([value]) + + +@define class BomTargetVersionRange: """ Class that represents either a version or version range and its affected status. @@ -72,162 +84,87 @@ class BomTargetVersionRange: https://cyclonedx.org/docs/1.7/json/#tab-pane_vulnerabilities_items_affects_items_versions_items_oneOf_i0 """ - def __init__( - self, *, - version: Optional[str] = None, - range: Optional[str] = None, - status: Optional[ImpactAnalysisAffectedStatus] = None, - ) -> None: - if not version and not range: + version: Optional[str] = field( + default=None, + metadata={'json_name': 'version', 'xml_name': 'version', 'xml_sequence': 1} + ) + """A single version of a component or service.""" + + range: Optional[str] = field( + default=None, + metadata={'json_name': 'range', 'xml_name': 'range', 'xml_sequence': 2} + ) + """A version range specified in Package URL Version Range syntax (vers).""" + + status: Optional[ImpactAnalysisAffectedStatus] = field( + default=None, + metadata={'json_name': 'status', 'xml_name': 'status', 'xml_sequence': 3} + ) + """The vulnerability status for the version or range of versions.""" + + def __attrs_post_init__(self) -> None: + if not self.version and not self.range: raise NoPropertiesProvidedException( 'One of version or range must be provided for BomTargetVersionRange - neither provided.' ) - if version and range: + if self.version and self.range: raise MutuallyExclusivePropertiesException( 'Either version or range should be provided for BomTargetVersionRange - both provided.' ) - self.version = version - self.range = range - self.status = status - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def version(self) -> Optional[str]: - """ - A single version of a component or service. - """ - return self._version - - @version.setter - def version(self, version: Optional[str]) -> None: - self._version = version - - @property - @serializable.xml_sequence(2) - def range(self) -> Optional[str]: - """ - A version range specified in Package URL Version Range syntax (vers) which is defined at - https://github.com/package-url/purl-spec/VERSION-RANGE-SPEC.rst - - .. note:: - The VERSION-RANGE-SPEC from Package URL is not a formalised standard at the time of writing and this no - validation of conformance with this draft standard is performed. - """ - return self._range - - @range.setter - def range(self, range: Optional[str]) -> None: - self._range = range - - @property - @serializable.xml_sequence(3) - def status(self) -> Optional[ImpactAnalysisAffectedStatus]: - """ - The vulnerability status for the version or range of versions. - """ - return self._status - - @status.setter - def status(self, status: Optional[ImpactAnalysisAffectedStatus]) -> None: - self._status = status - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.version, self.range, self.status - )) + def __hash__(self) -> int: + return hash((self.version, self.range, self.status)) - def __eq__(self, other: object) -> bool: - if isinstance(other, BomTargetVersionRange): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, BomTargetVersionRange): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.version), self._cmp(self.range), self._cmp(self.status)) < ( + self._cmp(other.version), self._cmp(other.range), self._cmp(other.status)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class BomTarget: """ Class that represents referencing a Component or Service in a BOM. - Aims to represent the sub-element `target` of the complex type `vulnerabilityType`. - - You can either create a `cyclonedx.model.bom.Bom` yourself programmatically, or generate a `cyclonedx.model.bom.Bom` - from a `cyclonedx.parser.BaseParser` implementation. - .. note:: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_affects """ - def __init__( - self, *, - ref: str, - versions: Optional[Iterable[BomTargetVersionRange]] = None, - ) -> None: - self.ref = ref - self.versions = versions or [] + ref: str = field(metadata={'json_name': 'ref', 'xml_name': 'ref', 'xml_sequence': 1}) + """Reference to a component or service by the objects `bom-ref`.""" - @property - @serializable.xml_sequence(1) - def ref(self) -> str: - """ - Reference to a component or service by the objects `bom-ref`. - """ - return self._ref - - @ref.setter - def ref(self, ref: str) -> None: - self._ref = ref + _versions: 'SortedSet[BomTargetVersionRange]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'versions', 'xml_name': 'versions', 'xml_item_name': 'version', 'xml_sequence': 2} + ) + """Zero or more individual versions or range of versions.""" @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'version') - @serializable.xml_sequence(2) def versions(self) -> 'SortedSet[BomTargetVersionRange]': - """ - Zero or more individual versions or range of versions. - - Returns: - Set of `BomTargetVersionRange` - """ + """Zero or more individual versions or range of versions.""" return self._versions @versions.setter def versions(self, versions: Iterable[BomTargetVersionRange]) -> None: self._versions = SortedSet(versions) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.ref, - _ComparableTuple(self.versions) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, BomTarget): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((self.ref, tuple(self.versions))) def __lt__(self, other: Any) -> bool: if isinstance(other, BomTarget): - return self.__comparable_tuple() < other.__comparable_tuple() + return self.ref < other.ref return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - def __repr__(self) -> str: - return f'' - - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilityAnalysis: """ Class that models the `analysis` sub-element of the `vulnerabilityType` complex type. @@ -236,140 +173,73 @@ class VulnerabilityAnalysis: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_analysis """ - def __init__( - self, *, - state: Optional[ImpactAnalysisState] = None, - justification: Optional[ImpactAnalysisJustification] = None, - responses: Optional[Iterable[ImpactAnalysisResponse]] = None, - detail: Optional[str] = None, - first_issued: Optional[datetime] = None, - last_updated: Optional[datetime] = None, - ) -> None: - self.state = state - self.justification = justification - self.responses = responses or [] - self.detail = detail - self.first_issued = first_issued - self.last_updated = last_updated - - @property - @serializable.xml_sequence(1) - def state(self) -> Optional[ImpactAnalysisState]: - """ - The declared current state of an occurrence of a vulnerability, after automated or manual analysis. - - Returns: - `ImpactAnalysisState` if set else `None` - """ - return self._state - - @state.setter - def state(self, state: Optional[ImpactAnalysisState]) -> None: - self._state = state - - @property - @serializable.xml_sequence(2) - def justification(self) -> Optional[ImpactAnalysisJustification]: - """ - The rationale of why the impact analysis state was asserted. - - Returns: - `ImpactAnalysisJustification` if set else `None` - """ - return self._justification - - @justification.setter - def justification(self, justification: Optional[ImpactAnalysisJustification]) -> None: - self._justification = justification + state: Optional[ImpactAnalysisState] = field( + default=None, + metadata={'json_name': 'state', 'xml_name': 'state', 'xml_sequence': 1} + ) + """The declared current state of an occurrence of a vulnerability.""" + + justification: Optional[ImpactAnalysisJustification] = field( + default=None, + metadata={'json_name': 'justification', 'xml_name': 'justification', 'xml_sequence': 2} + ) + """The rationale of why the impact analysis state was asserted.""" + + _responses: 'SortedSet[ImpactAnalysisResponse]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'response', 'xml_name': 'responses', 'xml_item_name': 'response', 'xml_sequence': 3} + ) + """A list of responses to the vulnerability.""" + + detail: Optional[str] = field( + default=None, + metadata={'json_name': 'detail', 'xml_name': 'detail', 'xml_sequence': 4} + ) + """A detailed description of the impact.""" + + first_issued: Optional[datetime] = field( + default=None, + metadata={'json_name': 'firstIssued', 'xml_name': 'firstIssued', 'xml_sequence': 5, + 'min_schema_version': SchemaVersion.V1_5} + ) + """The timestamp when the analysis was first issued.""" + + last_updated: Optional[datetime] = field( + default=None, + metadata={'json_name': 'lastUpdated', 'xml_name': 'lastUpdated', 'xml_sequence': 6, + 'min_schema_version': SchemaVersion.V1_5} + ) + """The timestamp when the analysis was last updated.""" @property - @serializable.json_name('response') - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'response') - @serializable.xml_sequence(3) def responses(self) -> 'SortedSet[ImpactAnalysisResponse]': - """ - A list of responses to the vulnerability by the manufacturer, supplier, or project responsible for the - affected component or service. More than one response is allowed. Responses are strongly encouraged for - vulnerabilities where the analysis state is exploitable. - - Returns: - Set of `ImpactAnalysisResponse` - """ + """A list of responses to the vulnerability.""" return self._responses @responses.setter def responses(self, responses: Iterable[ImpactAnalysisResponse]) -> None: self._responses = SortedSet(responses) - @property - @serializable.xml_sequence(4) - def detail(self) -> Optional[str]: - """ - A detailed description of the impact including methods used during assessment. If a vulnerability is not - exploitable, this field should include specific details on why the component or service is not impacted by this - vulnerability. - - Returns: - `str` if set else `None` - """ - return self._detail - - @detail.setter - def detail(self, detail: Optional[str]) -> None: - self._detail = detail - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(5) - def first_issued(self) -> Optional[datetime]: - return self._first_issued - - @first_issued.setter - def first_issued(self, first_issue: Optional[datetime]) -> None: - self._first_issued = first_issue + def __hash__(self) -> int: + return hash((self.state, self.justification, tuple(self.responses), + self.detail, self.first_issued, self.last_updated)) - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(6) - def last_updated(self) -> Optional[datetime]: - return self._last_updated - - @last_updated.setter - def last_updated(self, last_updated: Optional[datetime]) -> None: - self._last_updated = last_updated - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.state, self.justification, - _ComparableTuple(self.responses), - self.detail, - self.first_issued, self.last_updated - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilityAnalysis): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, VulnerabilityAnalysis): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self._cmp(self.state), self._cmp(self.justification), + tuple(self.responses), self._cmp(self.detail)) < ( + self._cmp(other.state), self._cmp(other.justification), + tuple(other.responses), self._cmp(other.detail)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilityAdvisory: """ Class that models the `advisoryType` complex type. @@ -378,247 +248,109 @@ class VulnerabilityAdvisory: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_advisories """ - def __init__( - self, *, - url: XsUri, - title: Optional[str] = None, - ) -> None: - self.title = title - self.url = url - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def title(self) -> Optional[str]: - """ - The title of this advisory. - """ - return self._title - - @title.setter - def title(self, title: Optional[str]) -> None: - self._title = title - - @property - @serializable.xml_sequence(2) - def url(self) -> XsUri: - """ - The url of this advisory. - """ - return self._url - - @url.setter - def url(self, url: XsUri) -> None: - self._url = url + url: XsUri = field(metadata={'json_name': 'url', 'xml_name': 'url', 'xml_sequence': 2}) + """The url of this advisory.""" - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.title, self.url - )) + title: Optional[str] = field( + default=None, + metadata={'json_name': 'title', 'xml_name': 'title', 'xml_sequence': 1} + ) + """The title of this advisory.""" - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilityAdvisory): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((self.title, self.url)) def __lt__(self, other: Any) -> bool: if isinstance(other, VulnerabilityAdvisory): - return self.__comparable_tuple() < other.__comparable_tuple() + # Sort by (title, url), with None values sorted after non-None + self_title = (0, self.title) if self.title is not None else (1, '') + other_title = (0, other.title) if other.title is not None else (1, '') + return (self_title, str(self.url)) < (other_title, str(other.url)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilitySource: """ Class that models the `vulnerabilitySourceType` complex type. - This type is used for multiple purposes in the CycloneDX schema. - .. note:: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_source """ - def __init__( - self, *, - name: Optional[str] = None, - url: Optional[XsUri] = None, - ) -> None: - self.name = name - self.url = url - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def name(self) -> Optional[str]: - """ - Name of this Source. - """ - return self._name - - @name.setter - def name(self, name: Optional[str]) -> None: - self._name = name + name: Optional[str] = field( + default=None, + metadata={'json_name': 'name', 'xml_name': 'name', 'xml_sequence': 1} + ) + """Name of this Source.""" - @property - @serializable.xml_sequence(2) - def url(self) -> Optional[XsUri]: - """ - The url of this Source. - """ - return self._url + url: Optional[XsUri] = field( + default=None, + metadata={'json_name': 'url', 'xml_name': 'url', 'xml_sequence': 2} + ) + """The url of this Source.""" - @url.setter - def url(self, url: Optional[XsUri]) -> None: - self._url = url - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.name, self.url - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilitySource): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((self.name, self.url)) def __lt__(self, other: Any) -> bool: if isinstance(other, VulnerabilitySource): - return self.__comparable_tuple() < other.__comparable_tuple() + # Sort by (name, url), with None values sorted after non-None + self_name = (0, self.name) if self.name is not None else (1, '') + other_name = (0, other.name) if other.name is not None else (1, '') + self_url = (0, str(self.url)) if self.url is not None else (1, '') + other_url = (0, str(other.url)) if other.url is not None else (1, '') + return (self_name, self_url) < (other_name, other_url) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilityReference: """ Class that models the nested `reference` within the `vulnerabilityType` complex type. - Vulnerabilities may benefit from pointers to vulnerabilities that are the equivalent of the vulnerability specified. - Often times, the same vulnerability may exist in multiple sources of vulnerability intelligence, but have different - identifiers. These references provide a way to correlate vulnerabilities across multiple sources of vulnerability - intelligence. - .. note:: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_references - - .. note:: - Properties ``id`` and ``source`` are mandatory. - - History: - * In v1.4 JSON scheme, both properties were mandatory - https://github.com/CycloneDX/specification/blob/d570ffb8956d796585b9574e57598c42ee9de770/schema/bom-1.4.schema.json#L1455-L1474 - * In v1.4 XML schema, both properties were optional - https://github.com/CycloneDX/specification/blob/d570ffb8956d796585b9574e57598c42ee9de770/schema/bom-1.4.xsd#L1788-L1797 - * In v1.5 XML schema, both were mandatory - https://github.com/CycloneDX/specification/blob/d570ffb8956d796585b9574e57598c42ee9de770/schema/bom-1.5.xsd#L3364-L3374 - - Decision: - Since CycloneDXCoreWorkingGroup chose JSON schema as the dominant schema, the one that serves as first spec - implementation, and since XML schema was "fixed" to work same as JSON schema, we'd consider it canon/spec that - both properties were always mandatory. """ - def __init__( - self, *, - id: str, - source: VulnerabilitySource, - ) -> None: - self.id = id - self.source = source - - @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def id(self) -> str: - """ - The identifier that uniquely identifies the vulnerability in the associated Source. For example: CVE-2021-39182. - """ - return self._id - - @id.setter - def id(self, id: str) -> None: - self._id = id + id: str = field(metadata={'json_name': 'id', 'xml_name': 'id', 'xml_sequence': 1}) + """The identifier that uniquely identifies the vulnerability in the associated Source.""" - @property - @serializable.xml_sequence(2) - def source(self) -> VulnerabilitySource: - """ - The source that published the vulnerability. - """ - return self._source + source: VulnerabilitySource = field(metadata={'json_name': 'source', 'xml_name': 'source', 'xml_sequence': 2}) + """The source that published the vulnerability.""" - @source.setter - def source(self, source: VulnerabilitySource) -> None: - self._source = source - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.id, self.source - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilityReference): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((self.id, self.source)) def __lt__(self, other: Any) -> bool: if isinstance(other, VulnerabilityReference): - return self.__comparable_tuple() < other.__comparable_tuple() + # Sort by (id, source) + if self.id != other.id: + return self.id < other.id + return self.source < other.source return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_enum class VulnerabilityScoreSource(str, Enum): """ Enum object that defines the permissible source types for a Vulnerability's score. .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_scoreSourceType - - .. note:: - No explicit carry-over from the former schema extension: - https://github.com/CycloneDX/specification/blob/master/schema/ext/vulnerability-1.0.xsd """ - # see `_VulnerabilityScoreSourceSerializationHelper.__CASES` for view/case map CVSS_V2 = 'CVSSv2' CVSS_V3 = 'CVSSv3' CVSS_V3_1 = 'CVSSv31' CVSS_V4 = 'CVSSv4' # Only supported in >= 1.5 OWASP = 'OWASP' # Name change in 1.4 SSVC = 'SSVC' # Only supported in >= 1.5 - # -- OTHER = 'other' @staticmethod def get_from_vector(vector: str) -> 'VulnerabilityScoreSource': """ Attempt to derive the correct SourceType from an attack vector. - - For example, often attack vector strings are prefixed with the scheme in question - such - that __CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N__ would be the vector - __AV:L/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N__ under the __CVSS 3__ scheme. - - Returns: - Always returns an instance of `VulnerabilityScoreSource`. `VulnerabilityScoreSource.OTHER` is - returned if the scheme is not obvious or known to us. """ if vector.startswith('CVSS:4.'): return VulnerabilityScoreSource.CVSS_V4 @@ -635,12 +367,6 @@ def get_from_vector(vector: str) -> 'VulnerabilityScoreSource': def get_localised_vector(self, vector: str) -> str: """ This method will remove any Source Scheme type from the supplied vector, returning just the vector. - - .. Note:: - Currently supports CVSS 3.x, CVSS 2.x and OWASP schemes. - - Returns: - The vector without any scheme prefix as a `str`. """ if self is VulnerabilityScoreSource.CVSS_V4 and vector.startswith('CVSS:4.'): return re.sub(r'^CVSS:4\.\d/?', '', vector) @@ -656,63 +382,26 @@ def get_localised_vector(self, vector: str) -> str: def get_value_pre_1_4(self) -> str: """ - Some of the enum values changed in 1.4 of the CycloneDX spec. This method allows us to - backport some of the changes for pre-1.4. - - Returns: - `str` + Some of the enum values changed in 1.4 of the CycloneDX spec. """ if self is VulnerabilityScoreSource.OWASP: return 'OWASP Risk' return self.value # type:ignore[no-any-return] -class _VulnerabilityScoreSourceSerializationHelper(serializable.helpers.BaseHelper): - """ THIS CLASS IS NON-PUBLIC API """ - - __CASES: dict[type[serializable.ViewType], frozenset[VulnerabilityScoreSource]] = dict() - __CASES[SchemaVersion1Dot4] = frozenset({ - VulnerabilityScoreSource.CVSS_V2, - VulnerabilityScoreSource.CVSS_V3, - VulnerabilityScoreSource.CVSS_V3_1, - VulnerabilityScoreSource.OWASP, - VulnerabilityScoreSource.OTHER, - }) - __CASES[SchemaVersion1Dot5] = __CASES[SchemaVersion1Dot4] | { - VulnerabilityScoreSource.CVSS_V4, - VulnerabilityScoreSource.SSVC - } - __CASES[SchemaVersion1Dot6] = __CASES[SchemaVersion1Dot5] - __CASES[SchemaVersion1Dot7] = __CASES[SchemaVersion1Dot6] - - @classmethod - def __normalize(cls, vss: VulnerabilityScoreSource, view: type[serializable.ViewType]) -> str: - return ( - vss - if vss in cls.__CASES.get(view, ()) - else VulnerabilityScoreSource.OTHER - ).value - - @classmethod - def json_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> str: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def xml_normalize(cls, o: Any, *, - view: Optional[type[serializable.ViewType]], - **__: Any) -> str: - assert view is not None - return cls.__normalize(o, view) - - @classmethod - def deserialize(cls, o: Any) -> VulnerabilityScoreSource: - return VulnerabilityScoreSource(o) - - -@serializable.serializable_enum +# VulnerabilityScoreSource support by schema version + +VULNERABILITY_SCORE_SOURCE_VERSIONS: dict[VulnerabilityScoreSource, set[SchemaVersion]] = { + VulnerabilityScoreSource.CVSS_V2: ALL_VERSIONS, + VulnerabilityScoreSource.CVSS_V3: ALL_VERSIONS, + VulnerabilityScoreSource.CVSS_V3_1: ALL_VERSIONS, + VulnerabilityScoreSource.OWASP: ALL_VERSIONS, + VulnerabilityScoreSource.OTHER: ALL_VERSIONS, + VulnerabilityScoreSource.CVSS_V4: VERSIONS_1_5_AND_LATER, + VulnerabilityScoreSource.SSVC: VERSIONS_1_5_AND_LATER, +} + + class VulnerabilitySeverity(str, Enum): """ Class that defines the permissible severities for a Vulnerability. @@ -731,186 +420,107 @@ class VulnerabilitySeverity(str, Enum): @staticmethod @deprecated('Deprecated - use cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores instead') def get_from_cvss_scores(scores: Union[tuple[float, ...], float, None]) -> 'VulnerabilitySeverity': - """Deprecated — Alias of :func:`cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores()`. - - Derives the Severity of a Vulnerability from it's declared CVSS scores. - - .. deprecated:: next - Use ``cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores()`` instead. - """ + """Deprecated — Alias of :func:`cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores()`.""" from ..contrib.vulnerability.cvss import vs_from_cvss_scores return vs_from_cvss_scores(scores) -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilityRating: """ Class that models the `ratingType` complex element CycloneDX core schema. - This class previously modelled the `scoreType` complexe type in the schema extension used prior to schema version - 1.4 - see https://github.com/CycloneDX/specification/blob/master/schema/ext/vulnerability-1.0.xsd. - .. note:: See the CycloneDX Schema definition: https://cyclonedx.org/docs/1.7/xml/#type_ratingType - - .. warning:: - As part of implementing support for CycloneDX schema version 1.4, the three score types defined in the schema - extension used prior to 1.4 have been deprecated. The deprecated `score_base` should loosely be equivalent to - the new `score` in 1.4 schema. Both `score_impact` and `score_exploitability` are deprecated and removed as - they are redundant if you have the vector (the vector allows you to calculate the scores). """ - def __init__( - self, *, - source: Optional[VulnerabilitySource] = None, - score: Optional[Decimal] = None, - severity: Optional[VulnerabilitySeverity] = None, - method: Optional[VulnerabilityScoreSource] = None, - vector: Optional[str] = None, - justification: Optional[str] = None, - ) -> None: - self.source = source - self.score = score - self.severity = severity - self.method = method - self.vector = vector - self.justification = justification - - if vector and method: - self.vector = method.get_localised_vector(vector=vector) + source: Optional[VulnerabilitySource] = field( + default=None, + metadata={'json_name': 'source', 'xml_name': 'source', 'xml_sequence': 1} + ) + """The source that published the vulnerability.""" + + score: Optional[Decimal] = field( + default=None, + metadata={'json_name': 'score', 'xml_name': 'score', 'xml_sequence': 2, 'string_format': '.1f'} + ) + """The numerical score of the rating.""" + + severity: Optional[VulnerabilitySeverity] = field( + default=None, + metadata={'json_name': 'severity', 'xml_name': 'severity', 'xml_sequence': 3} + ) + """The textual representation of the severity.""" + + method: Optional[VulnerabilityScoreSource] = field( + default=None, + metadata={'json_name': 'method', 'xml_name': 'method', 'xml_sequence': 4} + ) + """The risk scoring methodology/standard used.""" + + vector: Optional[str] = field( + default=None, + metadata={'json_name': 'vector', 'xml_name': 'vector', 'xml_sequence': 5} + ) + """The textual representation of the metric values used to score the vulnerability.""" + + justification: Optional[str] = field( + default=None, + metadata={'json_name': 'justification', 'xml_name': 'justification', 'xml_sequence': 6} + ) + """An optional reason for rating the vulnerability as it was.""" + + def __attrs_post_init__(self) -> None: + if self.vector and self.method: + self.vector = self.method.get_localised_vector(vector=self.vector) - @property - @serializable.xml_sequence(1) - def source(self) -> Optional[VulnerabilitySource]: - """ - The source that published the vulnerability. - """ - return self._source - - @source.setter - def source(self, source: Optional[VulnerabilitySource]) -> None: - self._source = source - - @property - @serializable.string_format('.1f') - @serializable.xml_sequence(2) - def score(self) -> Optional[Decimal]: - """ - The numerical score of the rating. - """ - return self._score - - @score.setter - def score(self, score: Optional[Decimal]) -> None: - self._score = score - - @property - @serializable.xml_sequence(3) - def severity(self) -> Optional[VulnerabilitySeverity]: - """ - The textual representation of the severity that corresponds to the numerical score of the rating. - """ - return self._severity - - @severity.setter - def severity(self, severity: Optional[VulnerabilitySeverity]) -> None: - self._severity = severity - - @property - @serializable.type_mapping(_VulnerabilityScoreSourceSerializationHelper) - @serializable.xml_sequence(4) - def method(self) -> Optional[VulnerabilityScoreSource]: - """ - The risk scoring methodology/standard used. - """ - return self._method - - @method.setter - def method(self, score_source: Optional[VulnerabilityScoreSource]) -> None: - self._method = score_source - - @property - @serializable.xml_sequence(5) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def vector(self) -> Optional[str]: - """ - The textual representation of the metric values used to score the vulnerability - also known as the vector. - """ - return self._vector - - @vector.setter - def vector(self, vector: Optional[str]) -> None: - self._vector = vector - - @property - @serializable.xml_sequence(6) - def justification(self) -> Optional[str]: - """ - An optional reason for rating the vulnerability as it was. - """ - return self._justification - - @justification.setter - def justification(self, justification: Optional[str]) -> None: - self._justification = justification - - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.severity, self.score or 0, - self.source, self.method, self.vector, - self.justification - )) + def __hash__(self) -> int: + return hash((self.severity, self.score or 0, self.source, self.method, self.vector, self.justification)) - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilityRating): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + @staticmethod + def _cmp(val: Any) -> tuple: + """Wrap value for None-safe comparison (None sorts last).""" + return (0, val) if val is not None else (1, '') def __lt__(self, other: Any) -> bool: if isinstance(other, VulnerabilityRating): - return self.__comparable_tuple() < other.__comparable_tuple() + # Compare by (severity, score, method, source, vector, justification) + return (self._cmp(self.severity), self.score or 0, self._cmp(self.method), + self._cmp(self.source), self._cmp(self.vector), self._cmp(self.justification)) < ( + self._cmp(other.severity), other.score or 0, self._cmp(other.method), + self._cmp(other.source), self._cmp(other.vector), self._cmp(other.justification)) return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class VulnerabilityCredits: """ - Class that models the `credits` of `vulnerabilityType` complex type in the CycloneDX schema (version >= 1.4). - - This class also provides data support for schema versions < 1.4 where Vulnerabilites were possible through a schema - extension (in XML only). + Class that models the `credits` of `vulnerabilityType` complex type in the CycloneDX schema. .. note:: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/json/#vulnerabilities_items_credits """ - def __init__( - self, *, - organizations: Optional[Iterable[OrganizationalEntity]] = None, - individuals: Optional[Iterable[OrganizationalContact]] = None, - ) -> None: - self.organizations = organizations or [] - self.individuals = individuals or [] + _organizations: 'SortedSet[OrganizationalEntity]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'organizations', 'xml_name': 'organizations', 'xml_item_name': 'organization', + 'xml_sequence': 1} + ) + """The organizations credited with vulnerability discovery.""" + + _individuals: 'SortedSet[OrganizationalContact]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'individuals', 'xml_name': 'individuals', 'xml_item_name': 'individual', + 'xml_sequence': 2} + ) + """The individuals credited with vulnerability discovery.""" @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'organization') - @serializable.xml_sequence(1) def organizations(self) -> 'SortedSet[OrganizationalEntity]': - """ - The organizations credited with vulnerability discovery. - - Returns: - Set of `OrganizationalEntity` - """ + """The organizations credited with vulnerability discovery.""" return self._organizations @organizations.setter @@ -918,156 +528,157 @@ def organizations(self, organizations: Iterable[OrganizationalEntity]) -> None: self._organizations = SortedSet(organizations) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'individual') - @serializable.xml_sequence(2) def individuals(self) -> 'SortedSet[OrganizationalContact]': - """ - The individuals, not associated with organizations, that are credited with vulnerability discovery. - - Returns: - Set of `OrganizationalContact` - """ + """The individuals credited with vulnerability discovery.""" return self._individuals @individuals.setter def individuals(self, individuals: Iterable[OrganizationalContact]) -> None: self._individuals = SortedSet(individuals) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - _ComparableTuple(self.organizations), - _ComparableTuple(self.individuals) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, VulnerabilityCredits): - return self.__comparable_tuple() == other.__comparable_tuple() - return False - - def __lt__(self, other: Any) -> bool: - if isinstance(other, VulnerabilityCredits): - return self.__comparable_tuple() < other.__comparable_tuple() - return NotImplemented - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) + return hash((tuple(self.organizations), tuple(self.individuals))) - def __repr__(self) -> str: - return f'' - -@serializable.serializable_class(ignore_unknown_during_deserialization=True) +@define class Vulnerability: """ Class that models the `vulnerabilityType` complex type in the CycloneDX schema (version >= 1.4). - This class also provides data support for schema versions < 1.4 where Vulnerabilites were possible through a schema - extension (in XML only). - .. note:: See the CycloneDX schema: https://cyclonedx.org/docs/1.7/xml/#type_vulnerabilityType """ - def __init__( - self, *, - bom_ref: Optional[Union[str, BomRef]] = None, - id: Optional[str] = None, - source: Optional[VulnerabilitySource] = None, - references: Optional[Iterable[VulnerabilityReference]] = None, - ratings: Optional[Iterable[VulnerabilityRating]] = None, - cwes: Optional[Iterable[int]] = None, - description: Optional[str] = None, - detail: Optional[str] = None, - recommendation: Optional[str] = None, - workaround: Optional[str] = None, - advisories: Optional[Iterable[VulnerabilityAdvisory]] = None, - created: Optional[datetime] = None, - published: Optional[datetime] = None, - updated: Optional[datetime] = None, - credits: Optional[VulnerabilityCredits] = None, - tools: Optional[Union[Iterable[Tool], ToolRepository]] = None, - analysis: Optional[VulnerabilityAnalysis] = None, - affects: Optional[Iterable[BomTarget]] = None, - properties: Optional[Iterable[Property]] = None, - ) -> None: - self._bom_ref = _bom_ref_from_str(bom_ref) - self.id = id - self.source = source - self.references = references or [] - self.ratings = ratings or [] - self.cwes = cwes or [] - self.description = description - self.detail = detail - self.recommendation = recommendation - self.workaround = workaround - self.advisories = advisories or [] - self.created = created - self.published = published - self.updated = updated - self.credits = credits - self.tools = tools or [] - self.analysis = analysis - self.affects = affects or [] - self.properties = properties or [] + _bom_ref: BomRef = field( + factory=BomRef, + converter=_bom_ref_from_str, + metadata={'json_name': 'bom-ref', 'xml_name': 'bom-ref', 'xml_attribute': True} + ) + """Unique reference for this Vulnerability in this BOM.""" + + id: Optional[str] = field( + default=None, + metadata={'json_name': 'id', 'xml_name': 'id', 'xml_sequence': 1} + ) + """The identifier that uniquely identifies the vulnerability.""" + + source: Optional[VulnerabilitySource] = field( + default=None, + metadata={'json_name': 'source', 'xml_name': 'source', 'xml_sequence': 2} + ) + """The source that published the vulnerability.""" + + _references: 'SortedSet[VulnerabilityReference]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'references', 'xml_name': 'references', 'xml_item_name': 'reference', 'xml_sequence': 3} + ) + """References to equivalent vulnerabilities in other sources.""" + + _ratings: 'SortedSet[VulnerabilityRating]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'ratings', 'xml_name': 'ratings', 'xml_item_name': 'rating', 'xml_sequence': 4} + ) + """List of vulnerability ratings.""" + + _cwes: 'SortedSet[int]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'cwes', 'xml_name': 'cwes', 'xml_item_name': 'cwe', 'xml_sequence': 5} + ) + """A list of CWE (Common Weakness Enumeration) identifiers.""" + + description: Optional[str] = field( + default=None, + metadata={'json_name': 'description', 'xml_name': 'description', 'xml_sequence': 6} + ) + """A description of the vulnerability as provided by the source.""" + + detail: Optional[str] = field( + default=None, + metadata={'json_name': 'detail', 'xml_name': 'detail', 'xml_sequence': 7} + ) + """If available, an in-depth description of the vulnerability.""" + + recommendation: Optional[str] = field( + default=None, + metadata={'json_name': 'recommendation', 'xml_name': 'recommendation', 'xml_sequence': 8} + ) + """Recommendations of how the vulnerability can be remediated or mitigated.""" + + workaround: Optional[str] = field( + default=None, + metadata={'json_name': 'workaround', 'xml_name': 'workaround', 'xml_sequence': 9, + 'min_schema_version': SchemaVersion.V1_5} + ) + """A bypass, usually temporary, of the vulnerability.""" + + _advisories: 'SortedSet[VulnerabilityAdvisory]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'advisories', 'xml_name': 'advisories', 'xml_item_name': 'advisory', 'xml_sequence': 11} + ) + """Advisories relating to the Vulnerability.""" + + created: Optional[datetime] = field( + default=None, + metadata={'json_name': 'created', 'xml_name': 'created', 'xml_sequence': 12} + ) + """The date and time when the vulnerability record was created.""" + + published: Optional[datetime] = field( + default=None, + metadata={'json_name': 'published', 'xml_name': 'published', 'xml_sequence': 13} + ) + """The date and time when the vulnerability record was first published.""" + + updated: Optional[datetime] = field( + default=None, + metadata={'json_name': 'updated', 'xml_name': 'updated', 'xml_sequence': 14} + ) + """The date and time when the vulnerability record was last updated.""" + + credits: Optional[VulnerabilityCredits] = field( + default=None, + metadata={'json_name': 'credits', 'xml_name': 'credits', 'xml_sequence': 16} + ) + """Individuals or organizations credited with the discovery of the vulnerability.""" + + _tools: ToolRepository = field( + factory=ToolRepository, + metadata={'json_name': 'tools', 'xml_name': 'tools', 'xml_sequence': 17} + ) + """Tools used to create this BOM.""" + + analysis: Optional[VulnerabilityAnalysis] = field( + default=None, + metadata={'json_name': 'analysis', 'xml_name': 'analysis', 'xml_sequence': 18} + ) + """Analysis of the Vulnerability in your context.""" + + _affects: 'SortedSet[BomTarget]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'affects', 'xml_name': 'affects', 'xml_item_name': 'target', 'xml_sequence': 19} + ) + """The components or services that are affected by the vulnerability.""" + + _properties: 'SortedSet[Property]' = field( + factory=SortedSet, + converter=_sortedset_converter, + metadata={'json_name': 'properties', 'xml_name': 'properties', 'xml_item_name': 'property', 'xml_sequence': 20} + ) + """Properties in a key/value store.""" @property - @serializable.json_name('bom-ref') - @serializable.type_mapping(BomRef) - @serializable.xml_attribute() - @serializable.xml_name('bom-ref') def bom_ref(self) -> BomRef: - """ - Get the unique reference for this Vulnerability in this BOM. - - Returns: - `BomRef` - """ + """Get the unique reference for this Vulnerability in this BOM.""" return self._bom_ref @property - @serializable.xml_sequence(1) - @serializable.xml_string(serializable.XmlStringSerializationType.NORMALIZED_STRING) - def id(self) -> Optional[str]: - """ - The identifier that uniquely identifies the vulnerability. For example: CVE-2021-39182. - - Returns: - `str` if set else `None` - """ - return self._id - - @id.setter - def id(self, id: Optional[str]) -> None: - self._id = id - - @property - @serializable.xml_sequence(2) - def source(self) -> Optional[VulnerabilitySource]: - """ - The source that published the vulnerability. - - Returns: - `VulnerabilitySource` if set else `None` - """ - return self._source - - @source.setter - def source(self, source: Optional[VulnerabilitySource]) -> None: - self._source = source - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference') - @serializable.xml_sequence(3) def references(self) -> 'SortedSet[VulnerabilityReference]': - """ - Zero or more pointers to vulnerabilities that are the equivalent of the vulnerability specified. Often times, - the same vulnerability may exist in multiple sources of vulnerability intelligence, but have different - identifiers. References provides a way to correlate vulnerabilities across multiple sources of vulnerability - intelligence. - - Returns: - Set of `VulnerabilityReference` - """ + """References to equivalent vulnerabilities in other sources.""" return self._references @references.setter @@ -1075,15 +686,8 @@ def references(self, references: Iterable[VulnerabilityReference]) -> None: self._references = SortedSet(references) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'rating') - @serializable.xml_sequence(4) def ratings(self) -> 'SortedSet[VulnerabilityRating]': - """ - List of vulnerability ratings. - - Returns: - Set of `VulnerabilityRating` - """ + """List of vulnerability ratings.""" return self._ratings @ratings.setter @@ -1091,18 +695,8 @@ def ratings(self, ratings: Iterable[VulnerabilityRating]) -> None: self._ratings = SortedSet(ratings) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'cwe') - @serializable.xml_sequence(5) def cwes(self) -> 'SortedSet[int]': - """ - A list of CWE (Common Weakness Enumeration) identifiers. - - .. note:: - See https://cwe.mitre.org/ - - Returns: - Set of `int` - """ + """A list of CWE (Common Weakness Enumeration) identifiers.""" return self._cwes @cwes.setter @@ -1110,90 +704,8 @@ def cwes(self, cwes: Iterable[int]) -> None: self._cwes = SortedSet(cwes) @property - @serializable.xml_sequence(6) - def description(self) -> Optional[str]: - """ - A description of the vulnerability as provided by the source. - - Returns: - `str` if set else `None` - """ - return self._description - - @description.setter - def description(self, description: Optional[str]) -> None: - self._description = description - - @property - @serializable.xml_sequence(7) - def detail(self) -> Optional[str]: - """ - If available, an in-depth description of the vulnerability as provided by the source organization. Details - often include examples, proof-of-concepts, and other information useful in understanding root cause. - - Returns: - `str` if set else `None` - """ - return self._detail - - @detail.setter - def detail(self, detail: Optional[str]) -> None: - self._detail = detail - - @property - @serializable.xml_sequence(8) - def recommendation(self) -> Optional[str]: - """ - Recommendations of how the vulnerability can be remediated or mitigated. - - Returns: - `str` if set else `None` - """ - return self._recommendation - - @recommendation.setter - def recommendation(self, recommendation: Optional[str]) -> None: - self._recommendation = recommendation - - @property - @serializable.view(SchemaVersion1Dot5) - @serializable.view(SchemaVersion1Dot6) - @serializable.view(SchemaVersion1Dot7) - @serializable.xml_sequence(9) - def workaround(self) -> Optional[str]: - """ - A bypass, usually temporary, of the vulnerability that reduces its likelihood and/or impact. - Workarounds often involve changes to configuration or deployments. - - Returns: - `str` if set else `None` - """ - return self._workaround - - @workaround.setter - def workaround(self, workaround: Optional[str]) -> None: - self._workaround = workaround - - # @property - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(10) - # def proof_of_concept(self) -> ...: - # ... # TODO since CDX 1.5 - # - # @proof_of_concept.setter - # def proof_of_concept(self, ...) -> None: - # ... # TODO since CDX 1.5 - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'advisory') - @serializable.xml_sequence(11) def advisories(self) -> 'SortedSet[VulnerabilityAdvisory]': - """ - Advisories relating to the Vulnerability. - - Returns: - Set of `VulnerabilityAdvisory` - """ + """Advisories relating to the Vulnerability.""" return self._advisories @advisories.setter @@ -1201,121 +713,17 @@ def advisories(self, advisories: Iterable[VulnerabilityAdvisory]) -> None: self._advisories = SortedSet(advisories) @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(12) - def created(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the vulnerability record was created in the vulnerability database. - - Returns: - `datetime` if set else `None` - """ - return self._created - - @created.setter - def created(self, created: Optional[datetime]) -> None: - self._created = created - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(13) - def published(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the vulnerability record was first published. - - Returns: - `datetime` if set else `None` - """ - return self._published - - @published.setter - def published(self, published: Optional[datetime]) -> None: - self._published = published - - @property - @serializable.type_mapping(serializable.helpers.XsdDateTime) - @serializable.xml_sequence(14) - def updated(self) -> Optional[datetime]: - """ - The date and time (timestamp) when the vulnerability record was last updated. - - Returns: - `datetime` if set else `None` - """ - return self._updated - - @updated.setter - def updated(self, updated: Optional[datetime]) -> None: - self._updated = updated - - # @property - # @serializable.view(SchemaVersion1Dot5) - # @serializable.xml_sequence(15) - # def rejected(self) -> ...: - # ... # TODO since CDX 1.5 - # - # @rejected.setter - # def rejected(self, ...) -> None: - # ... # TODO since CDX 1.5 - - @property - @serializable.xml_sequence(16) - def credits(self) -> Optional[VulnerabilityCredits]: - """ - Individuals or organizations credited with the discovery of the vulnerability. - - Returns: - `VulnerabilityCredits` if set else `None` - """ - return self._credits - - @credits.setter - def credits(self, credits: Optional[VulnerabilityCredits]) -> None: - self._credits = credits - - @property - @serializable.type_mapping(_ToolRepositoryHelper) - @serializable.xml_sequence(17) def tools(self) -> ToolRepository: - """ - Tools used to create this BOM. - - Returns: - :class:`ToolRepository` object. - """ + """Tools used to create this BOM.""" return self._tools @tools.setter def tools(self, tools: Union[Iterable[Tool], ToolRepository]) -> None: - self._tools = tools \ - if isinstance(tools, ToolRepository) \ - else ToolRepository(tools=tools) + self._tools = tools if isinstance(tools, ToolRepository) else ToolRepository(tools=tools) @property - @serializable.xml_sequence(18) - def analysis(self) -> Optional[VulnerabilityAnalysis]: - """ - Analysis of the Vulnerability in your context. - - Returns: - `VulnerabilityAnalysis` if set else `None` - """ - return self._analysis - - @analysis.setter - def analysis(self, analysis: Optional[VulnerabilityAnalysis]) -> None: - self._analysis = analysis - - @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'target') - @serializable.xml_sequence(19) def affects(self) -> 'SortedSet[BomTarget]': - """ - The components or services that are affected by the vulnerability. - - Returns: - Set of `BomTarget` - """ + """The components or services that are affected by the vulnerability.""" return self._affects @affects.setter @@ -1323,46 +731,18 @@ def affects(self, affects_targets: Iterable[BomTarget]) -> None: self._affects = SortedSet(affects_targets) @property - @serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'property') - @serializable.xml_sequence(20) def properties(self) -> 'SortedSet[Property]': - """ - Provides the ability to document properties in a key/value store. This provides flexibility to include data not - officially supported in the standard without having to use additional namespaces or create extensions. - - Return: - Set of `Property` - """ + """Properties in a key/value store.""" return self._properties @properties.setter def properties(self, properties: Iterable[Property]) -> None: self._properties = SortedSet(properties) - def __comparable_tuple(self) -> _ComparableTuple: - return _ComparableTuple(( - self.id, self.bom_ref.value, - self.source, _ComparableTuple(self.references), - _ComparableTuple(self.ratings), _ComparableTuple(self.cwes), self.description, - self.detail, self.recommendation, self.workaround, _ComparableTuple(self.advisories), - self.created, self.published, self.updated, - self.credits, self.tools, self.analysis, - _ComparableTuple(self.affects), - _ComparableTuple(self.properties) - )) - - def __eq__(self, other: object) -> bool: - if isinstance(other, Vulnerability): - return self.__comparable_tuple() == other.__comparable_tuple() - return False + def __hash__(self) -> int: + return hash((self.id, self.bom_ref.value)) def __lt__(self, other: Any) -> bool: if isinstance(other, Vulnerability): - return self.__comparable_tuple() < other.__comparable_tuple() + return (self.id or '', self.bom_ref.value or '') < (other.id or '', other.bom_ref.value or '') return NotImplemented - - def __hash__(self) -> int: - return hash(self.__comparable_tuple()) - - def __repr__(self) -> str: - return f'' diff --git a/cyclonedx/output/json.py b/cyclonedx/output/json.py index 23d7a6666..d79aba842 100644 --- a/cyclonedx/output/json.py +++ b/cyclonedx/output/json.py @@ -16,13 +16,12 @@ # Copyright (c) OWASP Foundation. All Rights Reserved. from abc import abstractmethod -from json import dumps as json_dumps, loads as json_loads +from json import dumps as json_dumps from typing import TYPE_CHECKING, Any, Literal, Optional, Union from ..exception.output import FormatNotSupportedException from ..schema import OutputFormat, SchemaVersion from ..schema.schema import ( - SCHEMA_VERSIONS, BaseSchemaVersion, SchemaVersion1Dot0, SchemaVersion1Dot1, @@ -33,6 +32,7 @@ SchemaVersion1Dot6, SchemaVersion1Dot7, ) +from ..serialization import make_converter from . import BaseOutput, BomRefDiscriminator if TYPE_CHECKING: # pragma: no cover @@ -53,6 +53,33 @@ def schema_version(self) -> SchemaVersion: def output_format(self) -> Literal[OutputFormat.JSON]: return OutputFormat.JSON + def _validate_component_types(self, bom: 'Bom') -> None: + """Validate that all component types are supported by the schema version.""" + from ..exception.serialization import SerializationOfUnsupportedComponentTypeException + from ..serialization._converters import _get_component_type_versions + + type_versions = _get_component_type_versions() + + def check_component(comp: Any) -> None: + if comp.type: + supported_versions = type_versions.get(comp.type.value, set()) + if self.schema_version_enum not in supported_versions: + raise SerializationOfUnsupportedComponentTypeException( + f"Component type '{comp.type.value}' is not supported in schema version {self.schema_version_enum.value}" + ) + # Check nested components + if comp.components: + for nested in comp.components: + check_component(nested) + + # Check top-level components + for comp in bom.components: + check_component(comp) + + # Check metadata component + if bom.metadata and bom.metadata.component: + check_component(bom.metadata.component) + def generate(self, force_regeneration: bool = False) -> None: if self.generated and not force_regeneration: return @@ -67,17 +94,154 @@ def generate(self, force_regeneration: bool = False) -> None: 'bomFormat': 'CycloneDX', 'specVersion': self.schema_version.to_version() } - _view = SCHEMA_VERSIONS.get(self.schema_version_enum) bom = self.get_bom() bom.validate() + + # Validate component types + self._validate_component_types(bom) + + # Create a converter for this schema version + converter = make_converter(self.schema_version_enum) + with BomRefDiscriminator.from_bom(bom): - bom_json: dict[str, Any] = json_loads( - bom.as_json( # type:ignore[attr-defined] - view_=_view)) + bom_json: dict[str, Any] = converter.unstructure(bom) + + # Post-process to wrap licenses for JSON format + self._wrap_json_licenses(bom_json) + + # Post-process evidence identity for 1.5 (single object, not array) + if self.schema_version_enum == SchemaVersion.V1_5: + self._transform_evidence_identity_for_1_5(bom_json) + + # Filter out enum values not supported in this schema version + self._filter_unsupported_enum_values(bom_json) + bom_json.update(_json_core) self._bom_json = bom_json + + def _wrap_json_licenses(self, data: Any) -> None: + """Recursively wrap licenses in JSON format. + + CycloneDX JSON wraps licenses: {"license": {...}} or {"expression": "..."} + """ + if isinstance(data, dict): + if 'licenses' in data and isinstance(data['licenses'], list): + wrapped = [] + for lic in data['licenses']: + if isinstance(lic, dict): + if 'expression' in lic: + # License expression - already in correct format from unstructure + wrapped.append(lic) + elif 'value' in lic: + # License expression (old format) - wrap it + new_lic = {'expression': lic['value']} + if 'bom-ref' in lic: + new_lic['bom-ref'] = lic['bom-ref'] + if 'acknowledgement' in lic: + new_lic['acknowledgement'] = lic['acknowledgement'] + wrapped.append(new_lic) + elif 'id' in lic or 'name' in lic: + # Disjunctive license - wrap in {"license": {...}} + wrapped.append({'license': lic}) + else: + wrapped.append(lic) + else: + wrapped.append(lic) + data['licenses'] = wrapped + + # Recurse into all values + for value in data.values(): + self._wrap_json_licenses(value) + elif isinstance(data, list): + for item in data: + self._wrap_json_licenses(item) self.generated = True + def _transform_evidence_identity_for_1_5(self, data: Any) -> None: + """Transform evidence.identity from array to single object for schema 1.5. + + In CycloneDX 1.5, evidence.identity is a single object. + In 1.6+, it became an array. + """ + if isinstance(data, dict): + # Check for evidence.identity + if 'evidence' in data and isinstance(data['evidence'], dict): + evidence = data['evidence'] + if 'identity' in evidence and isinstance(evidence['identity'], list): + # Convert array to single object (first element) + identity_list = evidence['identity'] + if identity_list: + evidence['identity'] = identity_list[0] + else: + del evidence['identity'] + + # Recurse into all values + for value in data.values(): + self._transform_evidence_identity_for_1_5(value) + elif isinstance(data, list): + for item in data: + self._transform_evidence_identity_for_1_5(item) + + def _filter_unsupported_enum_values(self, data: Any) -> None: + """Recursively filter out enum values not supported in this schema version.""" + from ..model import EXTREF_TYPE_VERSIONS, HASH_ALG_VERSIONS, ExternalReferenceType, HashAlgorithm + from ..model.component import COMPONENT_SCOPE_VERSIONS, ComponentScope + from ..model.issue import ISSUE_CLASSIFICATION_VERSIONS, IssueClassification + from ..model.vulnerability import VULNERABILITY_SCORE_SOURCE_VERSIONS, VulnerabilityScoreSource + + if isinstance(data, dict): + # Filter hashes + if 'hashes' in data and isinstance(data['hashes'], list): + data['hashes'] = [ + h for h in data['hashes'] + if not isinstance(h, dict) or 'alg' not in h or + self.schema_version_enum in HASH_ALG_VERSIONS.get( + HashAlgorithm(h['alg']), set()) + ] + + # Filter external references by type + if 'externalReferences' in data and isinstance(data['externalReferences'], list): + data['externalReferences'] = [ + er for er in data['externalReferences'] + if not isinstance(er, dict) or 'type' not in er or + self.schema_version_enum in EXTREF_TYPE_VERSIONS.get( + ExternalReferenceType(er['type']), set()) + ] + + # Filter issues by classification + if 'issues' in data and isinstance(data['issues'], list): + data['issues'] = [ + issue for issue in data['issues'] + if not isinstance(issue, dict) or 'classification' not in issue or + self.schema_version_enum in ISSUE_CLASSIFICATION_VERSIONS.get( + IssueClassification(issue['classification']), set()) + ] + + # Filter vulnerability ratings by method + if 'ratings' in data and isinstance(data['ratings'], list): + data['ratings'] = [ + r for r in data['ratings'] + if not isinstance(r, dict) or 'method' not in r or + self.schema_version_enum in VULNERABILITY_SCORE_SOURCE_VERSIONS.get( + VulnerabilityScoreSource(r['method']), set()) + ] + + # Filter out unsupported component scope values + if 'scope' in data and data['scope'] is not None: + try: + scope = ComponentScope(data['scope']) + if self.schema_version_enum not in COMPONENT_SCOPE_VERSIONS.get(scope, set()): + del data['scope'] + except (ValueError, KeyError): + pass + + # Recurse into all values + for value in data.values(): + self._filter_unsupported_enum_values(value) + elif isinstance(data, list): + for item in data: + self._filter_unsupported_enum_values(item) + def output_as_string(self, *, indent: Optional[Union[int, str]] = None, **kwargs: Any) -> str: diff --git a/cyclonedx/output/xml.py b/cyclonedx/output/xml.py index 8c206349f..1c83d5245 100644 --- a/cyclonedx/output/xml.py +++ b/cyclonedx/output/xml.py @@ -22,7 +22,6 @@ from ..schema import OutputFormat, SchemaVersion from ..schema.schema import ( - SCHEMA_VERSIONS, BaseSchemaVersion, SchemaVersion1Dot0, SchemaVersion1Dot1, @@ -33,6 +32,7 @@ SchemaVersion1Dot6, SchemaVersion1Dot7, ) +from ..serialization import make_converter from . import BaseOutput, BomRefDiscriminator if TYPE_CHECKING: # pragma: no cover @@ -52,23 +52,886 @@ def schema_version(self) -> SchemaVersion: def output_format(self) -> Literal[OutputFormat.XML]: return OutputFormat.XML + # Fields that should be serialized as XML attributes (not child elements) + _XML_ATTR_FIELDS = { + 'dependency': {'ref'}, + 'component': {'bom-ref', 'type'}, + 'service': {'bom-ref'}, + 'vulnerability': {'bom-ref'}, + 'license': {'bom-ref'}, + 'hash': {'alg'}, + 'issue': {'type'}, + 'patch': {'type'}, + 'swid': {'tagId', 'name', 'version', 'tagVersion', 'patch'}, + 'identifiableAction': {'timestamp'}, + 'attachment': {'content-type', 'encoding'}, + 'property': {'name'}, + 'reference': {'type'}, # External reference type is an attribute + 'text': {'content-type', 'encoding'}, # AttachedText attributes + 'standard': {'bom-ref'}, + 'requirement': {'bom-ref'}, + 'level': {'bom-ref'}, + } + + # Element ordering for CycloneDX XML schema (field name -> sequence number) + _XML_ELEMENT_ORDER = { + 'component': ['type', 'bom-ref', 'supplier', 'manufacturer', 'authors', 'author', 'publisher', + 'group', 'name', 'version', 'description', 'scope', 'hashes', 'licenses', + 'copyright', 'patentAssertions', 'cpe', 'purl', 'omniborId', 'swhid', 'swid', 'modified', + 'pedigree', 'externalReferences', 'properties', 'components', 'evidence', 'releaseNotes', + 'modelCard', 'data', 'cryptoProperties', 'tags', 'signature'], + 'metadata': ['timestamp', 'lifecycles', 'tools', 'authors', 'component', 'manufacture', + 'manufacturer', 'supplier', 'licenses', 'properties'], + 'service': ['bom-ref', 'provider', 'group', 'name', 'version', 'description', 'endpoints', + 'authenticated', 'x-trust-boundary', 'trustZone', 'data', 'licenses', + 'patentAssertions', 'externalReferences', 'properties', 'services', 'releaseNotes', 'tags'], + 'releaseNotes': ['type', 'title', 'featuredImage', 'socialImage', 'description', 'timestamp', + 'aliases', 'tags', 'resolves', 'notes', 'properties'], + 'note': ['locale', 'text'], + 'issue': ['type', 'id', 'name', 'description', 'source', 'references'], + 'pedigree': ['ancestors', 'descendants', 'variants', 'commits', 'patches', 'notes'], + 'diff': ['text', 'url'], + 'patch': ['type', 'diff', 'resolves'], + 'frame': ['package', 'module', 'function', 'parameters', 'line', 'column', 'fullFilename'], + 'identity': ['field', 'confidence', 'concludedValue', 'methods', 'tools'], + 'method': ['technique', 'confidence', 'value'], + 'occurrence': ['bom-ref', 'location', 'line', 'offset', 'symbol', 'additionalContext'], + 'evidence': ['identity', 'occurrences', 'callstack', 'licenses', 'copyright'], + 'algorithmProperties': ['primitive', 'algorithmFamily', 'parameterSetIdentifier', 'curve', 'ellipticCurve', + 'executionEnvironment', 'implementationPlatform', 'certificationLevel', 'mode', + 'padding', 'cryptoFunctions', 'classicalSecurityLevel', 'nistQuantumSecurityLevel'], + 'cryptoProperties': ['assetType', 'algorithmProperties', 'certificateProperties', 'relatedCryptoMaterialProperties', + 'protocolProperties', 'oid'], + 'protocolProperties': ['type', 'version', 'cipherSuites', 'ikev2TransformTypes', 'cryptoRefArray'], + 'cipherSuite': ['name', 'algorithms', 'identifiers'], + 'vulnerability': ['id', 'source', 'references', 'ratings', 'cwes', 'description', 'detail', + 'recommendation', 'workaround', 'proofOfConcept', 'advisories', 'created', + 'published', 'updated', 'rejected', 'credits', 'tools', 'analysis', + 'affects', 'properties'], + 'rating': ['source', 'score', 'severity', 'method', 'vector', 'justification'], + 'advisory': ['title', 'url'], + 'standard': ['bom-ref', 'name', 'version', 'description', 'owner', 'requirements', 'levels', 'externalReferences'], + 'requirement': ['bom-ref', 'identifier', 'title', 'text', 'descriptions', 'openCre', 'parent', 'properties', 'externalReferences'], + 'level': ['bom-ref', 'identifier', 'title', 'description', 'requirements'], + 'target': ['ref', 'versions'], + 'version': ['version', 'range', 'status'], + 'analysis': ['state', 'justification', 'response', 'detail', 'firstIssued', 'lastUpdated'], + 'organization': ['name', 'address', 'url', 'contact'], + 'individual': ['name', 'email', 'phone'], + 'contact': ['name', 'email', 'phone'], + 'address': ['country', 'region', 'locality', 'postOfficeBoxNumber', 'postalCode', 'streetAddress'], + } + + def _validate_component_types(self, bom: 'Bom') -> None: + """Validate that all component types are supported by the schema version.""" + from ..exception.serialization import SerializationOfUnsupportedComponentTypeException + from ..serialization._converters import _get_component_type_versions + + type_versions = _get_component_type_versions() + + def check_component(comp: Any) -> None: + if comp.type: + supported_versions = type_versions.get(comp.type.value, set()) + if self.schema_version_enum not in supported_versions: + raise SerializationOfUnsupportedComponentTypeException( + f"Component type '{comp.type.value}' is not supported in schema version {self.schema_version_enum.value}" + ) + # Check nested components + if comp.components: + for nested in comp.components: + check_component(nested) + + # Check top-level components + for comp in bom.components: + check_component(comp) + + # Check metadata component + if bom.metadata and bom.metadata.component: + check_component(bom.metadata.component) + + def _ensure_modified_field(self, comp: dict) -> None: + """Recursively ensure 'modified' field is present in component dicts for 1.0/1.1 schemas.""" + if 'modified' not in comp: + comp['modified'] = False + # Handle nested components + if 'components' in comp and comp['components']: + for nested_comp in comp['components']: + self._ensure_modified_field(nested_comp) + + def _filter_unsupported_enum_values(self, data: Any) -> None: + """Recursively filter out enum values not supported in this schema version.""" + from ..model import EXTREF_TYPE_VERSIONS, HASH_ALG_VERSIONS, ExternalReferenceType, HashAlgorithm + from ..model.component import COMPONENT_SCOPE_VERSIONS, ComponentScope + from ..model.issue import ISSUE_CLASSIFICATION_VERSIONS, IssueClassification + from ..model.vulnerability import VULNERABILITY_SCORE_SOURCE_VERSIONS, VulnerabilityScoreSource + + if isinstance(data, dict): + # Filter hashes + if 'hashes' in data and isinstance(data['hashes'], list): + data['hashes'] = [ + h for h in data['hashes'] + if not isinstance(h, dict) or 'alg' not in h or + self.schema_version_enum in HASH_ALG_VERSIONS.get( + HashAlgorithm(h['alg']), set()) + ] + + # Filter external references by type + if 'externalReferences' in data and isinstance(data['externalReferences'], list): + data['externalReferences'] = [ + er for er in data['externalReferences'] + if not isinstance(er, dict) or 'type' not in er or + self.schema_version_enum in EXTREF_TYPE_VERSIONS.get( + ExternalReferenceType(er['type']), set()) + ] + + # Filter issues by classification + if 'issues' in data and isinstance(data['issues'], list): + data['issues'] = [ + issue for issue in data['issues'] + if not isinstance(issue, dict) or 'classification' not in issue or + self.schema_version_enum in ISSUE_CLASSIFICATION_VERSIONS.get( + IssueClassification(issue['classification']), set()) + ] + + # Filter vulnerability ratings by method + if 'ratings' in data and isinstance(data['ratings'], list): + data['ratings'] = [ + r for r in data['ratings'] + if not isinstance(r, dict) or 'method' not in r or + self.schema_version_enum in VULNERABILITY_SCORE_SOURCE_VERSIONS.get( + VulnerabilityScoreSource(r['method']), set()) + ] + + # Filter out unsupported component scope values + if 'scope' in data and data['scope'] is not None: + try: + scope = ComponentScope(data['scope']) + if self.schema_version_enum not in COMPONENT_SCOPE_VERSIONS.get(scope, set()): + del data['scope'] + except (ValueError, KeyError): + pass + + # Recurse into all values + for value in data.values(): + self._filter_unsupported_enum_values(value) + elif isinstance(data, list): + for item in data: + self._filter_unsupported_enum_values(item) + + def _bom_to_xml(self, bom: 'Bom', xmlns: str) -> XmlElement: + """Convert a Bom object to XML Element using the new serialization.""" + from ..serialization._xml import CycloneDxXmlSerializer + + # Validate component types first + self._validate_component_types(bom) + + serializer = CycloneDxXmlSerializer(self.schema_version_enum) + + # Create root bom element with namespace-qualified tag + def ns_tag(name): return f'{{{xmlns}}}{name}' + root = XmlElement(ns_tag('bom'), { + 'version': str(bom.version), + }) + + # serialNumber was introduced in 1.1 + if bom.serial_number and self.schema_version_enum != SchemaVersion.V1_0: + root.set('serialNumber', serializer.serialize_uuid(bom.serial_number)) + + # Convert bom to dict using cattrs, then convert to XML + converter = make_converter(self.schema_version_enum) + bom_dict = converter.unstructure(bom) + + # Filter out enum values not supported in this schema version + self._filter_unsupported_enum_values(bom_dict) + + # Add metadata if present + if 'metadata' in bom_dict and bom_dict['metadata']: + self._dict_to_xml(bom_dict['metadata'], root, 'metadata', xmlns) + + # Add components if present (or empty element for 1.0/1.1 which require it) + has_components = 'components' in bom_dict and bom_dict['components'] + requires_components = self.schema_version_enum in (SchemaVersion.V1_0, SchemaVersion.V1_1) + if has_components or requires_components: + components_elem = XmlElement(ns_tag('components')) + if has_components: + for comp in bom_dict['components']: + # For 1.0/1.1, ensure 'modified' field is present (required in these schemas) + if self.schema_version_enum in (SchemaVersion.V1_0, SchemaVersion.V1_1): + self._ensure_modified_field(comp) + self._dict_to_xml(comp, components_elem, 'component', xmlns) + root.append(components_elem) + + # Add services if present + if 'services' in bom_dict and bom_dict['services']: + services_elem = XmlElement(ns_tag('services')) + for svc in bom_dict['services']: + self._dict_to_xml(svc, services_elem, 'service', xmlns) + root.append(services_elem) + + # Add externalReferences if present + if 'externalReferences' in bom_dict and bom_dict['externalReferences']: + refs_elem = XmlElement(ns_tag('externalReferences')) + for ref in bom_dict['externalReferences']: + self._dict_to_xml(ref, refs_elem, 'reference', xmlns) + root.append(refs_elem) + + # Add dependencies if present + if 'dependencies' in bom_dict and bom_dict['dependencies']: + deps_elem = XmlElement(ns_tag('dependencies')) + for dep in bom_dict['dependencies']: + self._dependency_to_xml(dep, deps_elem, xmlns) + root.append(deps_elem) + + # Add compositions if present + if 'compositions' in bom_dict and bom_dict['compositions']: + comp_elem = XmlElement(ns_tag('compositions')) + for composition in bom_dict['compositions']: + self._dict_to_xml(composition, comp_elem, 'composition', xmlns) + root.append(comp_elem) + + # Add properties if present (comes before vulnerabilities) + if 'properties' in bom_dict and bom_dict['properties']: + props_elem = XmlElement(ns_tag('properties')) + for prop in bom_dict['properties']: + self._property_to_xml(prop, props_elem, xmlns) + root.append(props_elem) + + # Add vulnerabilities if present + if 'vulnerabilities' in bom_dict and bom_dict['vulnerabilities']: + vulns_elem = XmlElement(ns_tag('vulnerabilities')) + for vuln in bom_dict['vulnerabilities']: + self._dict_to_xml(vuln, vulns_elem, 'vulnerability', xmlns) + root.append(vulns_elem) + + # Add annotations if present + if 'annotations' in bom_dict and bom_dict['annotations']: + annot_elem = XmlElement(ns_tag('annotations')) + for annotation in bom_dict['annotations']: + self._dict_to_xml(annotation, annot_elem, 'annotation', xmlns) + root.append(annot_elem) + + # Add formulation if present + if 'formulation' in bom_dict and bom_dict['formulation']: + form_elem = XmlElement(ns_tag('formulation')) + for formula in bom_dict['formulation']: + self._dict_to_xml(formula, form_elem, 'formula', xmlns) + root.append(form_elem) + + # Add definitions if present (introduced in 1.5) + if 'definitions' in bom_dict and bom_dict['definitions']: + defs_elem = XmlElement(ns_tag('definitions')) + definitions = bom_dict['definitions'] + # Handle standards + if 'standards' in definitions and definitions['standards']: + stds_elem = XmlElement(ns_tag('standards')) + for std in definitions['standards']: + self._dict_to_xml(std, stds_elem, 'standard', xmlns) + defs_elem.append(stds_elem) + root.append(defs_elem) + + return root + + def _dependency_to_xml(self, dep: dict, parent: XmlElement, xmlns: str) -> None: + """Convert a dependency dict to XML with ref as attribute.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + elem = XmlElement(ns_tag('dependency')) + + # ref is an attribute + if 'ref' in dep: + elem.set('ref', str(dep['ref'])) + + # dependsOn becomes nested dependency elements + if 'dependsOn' in dep and dep['dependsOn']: + for nested_ref in dep['dependsOn']: + nested = XmlElement(ns_tag('dependency')) + nested.set('ref', str(nested_ref)) + elem.append(nested) + + parent.append(elem) + + def _property_to_xml(self, prop: dict, parent: XmlElement, xmlns: str) -> None: + """Convert a property dict to XML with name as attribute and value as text.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + elem = XmlElement(ns_tag('property')) + + if 'name' in prop: + elem.set('name', str(prop['name'])) + if 'value' in prop: + elem.text = str(prop['value']) + + parent.append(elem) + + def _dict_to_xml(self, data: Any, parent: XmlElement, name: str, xmlns: str) -> None: + """Recursively convert a dict to XML elements.""" + if data is None: + return + + def ns_tag(n): return f'{{{xmlns}}}{n}' + + # Get attribute fields for this element type + attr_fields = self._XML_ATTR_FIELDS.get(name, set()) + # Get element order for this element type + element_order = self._XML_ELEMENT_ORDER.get(name, []) + + if isinstance(data, dict): + elem = XmlElement(ns_tag(name)) + + # First, handle attribute fields + for key in list(data.keys()): + if key in attr_fields and data[key] is not None: + elem.set(key, str(data[key])) + + # Sort remaining keys by element order if specified + remaining_keys = [k for k in data.keys() if k not in attr_fields] + if element_order: + def sort_key(k): + try: + return element_order.index(k) + except ValueError: + return 999 # Unknown keys go at the end + remaining_keys = sorted(remaining_keys, key=sort_key) + + # Then handle child elements + for key in remaining_keys: + value = data[key] + if value is not None: + # Special handling for specific nested structures + if key == 'hashes' and isinstance(value, list): + hashes_elem = XmlElement(ns_tag('hashes')) + for h in value: + self._hash_to_xml(h, hashes_elem, xmlns) + if len(hashes_elem) > 0: + elem.append(hashes_elem) + elif key == 'licenses' and isinstance(value, list): + licenses_elem = XmlElement(ns_tag('licenses')) + for lic in value: + self._license_to_xml(lic, licenses_elem, xmlns) + if len(licenses_elem) > 0: + elem.append(licenses_elem) + elif key == 'externalReferences' and isinstance(value, list): + refs_elem = XmlElement(ns_tag('externalReferences')) + for ref in value: + self._dict_to_xml(ref, refs_elem, 'reference', xmlns) + if len(refs_elem) > 0: + elem.append(refs_elem) + elif key == 'properties' and isinstance(value, list): + props_elem = XmlElement(ns_tag('properties')) + for prop in value: + self._property_to_xml(prop, props_elem, xmlns) + if len(props_elem) > 0: + elem.append(props_elem) + elif key == 'components' and isinstance(value, list): + comps_elem = XmlElement(ns_tag('components')) + for comp in value: + self._dict_to_xml(comp, comps_elem, 'component', xmlns) + if len(comps_elem) > 0: + elem.append(comps_elem) + elif key == 'tools' and isinstance(value, dict): + # Tools can have tools, components, services (newer format) + tools_elem = XmlElement(ns_tag('tools')) + if 'tools' in value and value['tools']: + for t in value['tools']: + self._dict_to_xml(t, tools_elem, 'tool', xmlns) + if 'components' in value and value['components']: + comps = XmlElement(ns_tag('components')) + for c in value['components']: + self._dict_to_xml(c, comps, 'component', xmlns) + tools_elem.append(comps) + if 'services' in value and value['services']: + svcs = XmlElement(ns_tag('services')) + for s in value['services']: + self._dict_to_xml(s, svcs, 'service', xmlns) + tools_elem.append(svcs) + if len(tools_elem) > 0: + elem.append(tools_elem) + elif key == 'tools' and isinstance(value, list) and name == 'metadata': + # Metadata tools as flat list - wrap each in + tools_elem = XmlElement(ns_tag('tools')) + for t in value: + self._dict_to_xml(t, tools_elem, 'tool', xmlns) + if len(tools_elem) > 0: + elem.append(tools_elem) + elif key == 'tools' and isinstance(value, list) and name == 'identity': + # Identity tools - container with children + tools_elem = XmlElement(ns_tag('tools')) + for ref in value: + tool_elem = XmlElement(ns_tag('tool')) + tool_elem.set('ref', str(ref)) + tools_elem.append(tool_elem) + if len(tools_elem) > 0: + elem.append(tools_elem) + elif key == 'tools' and isinstance(value, list) and name == 'vulnerability': + # Vulnerability tools - container with children + tools_elem = XmlElement(ns_tag('tools')) + for t in value: + self._dict_to_xml(t, tools_elem, 'tool', xmlns) + if len(tools_elem) > 0: + elem.append(tools_elem) + elif key == 'tools' and isinstance(value, dict) and name == 'vulnerability': + # Vulnerability tools as single dict + tools_elem = XmlElement(ns_tag('tools')) + self._dict_to_xml(value, tools_elem, 'tool', xmlns) + elem.append(tools_elem) + elif key == 'data' and isinstance(value, list) and name == 'service': + # Service data is a container with classification children + data_elem = XmlElement(ns_tag('data')) + for dc in value: + self._data_classification_to_xml(dc, data_elem, xmlns) + if len(data_elem) > 0: + elem.append(data_elem) + elif key == 'services' and isinstance(value, list) and name == 'service': + # Nested services within a service - container with children + services_elem = XmlElement(ns_tag('services')) + for svc in value: + self._dict_to_xml(svc, services_elem, 'service', xmlns) + if len(services_elem) > 0: + elem.append(services_elem) + elif key == 'endpoints' and isinstance(value, list): + # Endpoints - container with children + endpoints_elem = XmlElement(ns_tag('endpoints')) + for ep in value: + ep_elem = XmlElement(ns_tag('endpoint')) + ep_elem.text = str(ep) + endpoints_elem.append(ep_elem) + if len(endpoints_elem) > 0: + elem.append(endpoints_elem) + elif key == 'authors' and isinstance(value, list): + authors_elem = XmlElement(ns_tag('authors')) + for author in value: + self._dict_to_xml(author, authors_elem, 'author', xmlns) + if len(authors_elem) > 0: + elem.append(authors_elem) + elif key == 'lifecycles' and isinstance(value, list): + lc_elem = XmlElement(ns_tag('lifecycles')) + for lc in value: + self._dict_to_xml(lc, lc_elem, 'lifecycle', xmlns) + if len(lc_elem) > 0: + elem.append(lc_elem) + elif key == 'tags' and isinstance(value, list): + tags_elem = XmlElement(ns_tag('tags')) + for tag in value: + tag_elem = XmlElement(ns_tag('tag')) + tag_elem.text = str(tag) + tags_elem.append(tag_elem) + if len(tags_elem) > 0: + elem.append(tags_elem) + elif key == 'levels' and isinstance(value, list): + # Standard levels - wrap each in + levels_elem = XmlElement(ns_tag('levels')) + for level in value: + self._dict_to_xml(level, levels_elem, 'level', xmlns) + if len(levels_elem) > 0: + elem.append(levels_elem) + elif key == 'requirements' and isinstance(value, list) and name == 'standard': + # Standard requirements - wrap each in + reqs_elem = XmlElement(ns_tag('requirements')) + for req in value: + self._dict_to_xml(req, reqs_elem, 'requirement', xmlns) + if len(reqs_elem) > 0: + elem.append(reqs_elem) + elif key == 'requirements' and isinstance(value, list) and name == 'level': + # Level requirements are BomRefs - text content (refLinkType) + reqs_elem = XmlElement(ns_tag('requirements')) + for ref in value: + req_elem = XmlElement(ns_tag('requirement')) + req_elem.text = str(ref) + reqs_elem.append(req_elem) + if len(reqs_elem) > 0: + elem.append(reqs_elem) + elif key == 'descriptions' and isinstance(value, list): + # Requirement descriptions - container with children + descs_elem = XmlElement(ns_tag('descriptions')) + for desc in value: + desc_elem = XmlElement(ns_tag('description')) + desc_elem.text = str(desc) + descs_elem.append(desc_elem) + if len(descs_elem) > 0: + elem.append(descs_elem) + elif key == 'openCre' and isinstance(value, list): + # openCre - multiple elements directly + for cre in value: + cre_elem = XmlElement(ns_tag('openCre')) + cre_elem.text = str(cre) + elem.append(cre_elem) + elif key in ('ancestors', 'descendants', 'variants') and isinstance(value, list): + # Pedigree component lists - wrap each in + container_elem = XmlElement(ns_tag(key)) + for comp in value: + self._dict_to_xml(comp, container_elem, 'component', xmlns) + if len(container_elem) > 0: + elem.append(container_elem) + elif key == 'patches' and isinstance(value, list): + # Pedigree patches - wrap each in + patches_elem = XmlElement(ns_tag('patches')) + for patch in value: + self._dict_to_xml(patch, patches_elem, 'patch', xmlns) + if len(patches_elem) > 0: + elem.append(patches_elem) + elif key == 'resolves' and isinstance(value, list) and name == 'patch': + # Patch resolves - container with children + resolves_elem = XmlElement(ns_tag('resolves')) + for issue in value: + self._dict_to_xml(issue, resolves_elem, 'issue', xmlns) + if len(resolves_elem) > 0: + elem.append(resolves_elem) + elif key == 'commits' and isinstance(value, list): + # Pedigree commits - wrap each in + commits_elem = XmlElement(ns_tag('commits')) + for commit in value: + self._dict_to_xml(commit, commits_elem, 'commit', xmlns) + if len(commits_elem) > 0: + elem.append(commits_elem) + elif key == 'frames' and isinstance(value, list): + # Callstack frames - wrap each in + frames_elem = XmlElement(ns_tag('frames')) + for frame in value: + self._dict_to_xml(frame, frames_elem, 'frame', xmlns) + if len(frames_elem) > 0: + elem.append(frames_elem) + elif key == 'occurrences' and isinstance(value, list): + # Evidence occurrences - wrap each in + occ_elem = XmlElement(ns_tag('occurrences')) + for occ in value: + self._dict_to_xml(occ, occ_elem, 'occurrence', xmlns) + if len(occ_elem) > 0: + elem.append(occ_elem) + elif key == 'identity' and isinstance(value, list): + # Evidence identity - in 1.5, single object; in 1.6+, array + if self.schema_version_enum == SchemaVersion.V1_5: + # Only output first identity for 1.5 + if value: + self._dict_to_xml(value[0], elem, 'identity', xmlns) + else: + # Output each directly for 1.6+ + for ident in value: + self._dict_to_xml(ident, elem, 'identity', xmlns) + elif key == 'methods' and isinstance(value, list): + # Evidence methods - wrap each in + methods_elem = XmlElement(ns_tag('methods')) + for method in value: + self._dict_to_xml(method, methods_elem, 'method', xmlns) + if len(methods_elem) > 0: + elem.append(methods_elem) + elif key == 'parameters' and isinstance(value, list) and name == 'frame': + # Frame parameters - container with children + params_elem = XmlElement(ns_tag('parameters')) + for param in value: + param_elem = XmlElement(ns_tag('parameter')) + param_elem.text = str(param) + params_elem.append(param_elem) + if len(params_elem) > 0: + elem.append(params_elem) + elif key == 'cryptoFunctions' and isinstance(value, list): + # CryptoFunctions - container with children + funcs_elem = XmlElement(ns_tag('cryptoFunctions')) + for func in value: + func_elem = XmlElement(ns_tag('cryptoFunction')) + func_elem.text = str(func) + funcs_elem.append(func_elem) + if len(funcs_elem) > 0: + elem.append(funcs_elem) + elif key == 'certificationLevel' and isinstance(value, list): + # CertificationLevel is a list of strings + for level in value: + level_elem = XmlElement(ns_tag('certificationLevel')) + level_elem.text = str(level) + elem.append(level_elem) + elif key == 'cipherSuites' and isinstance(value, list): + # CipherSuites - container with children + suites_elem = XmlElement(ns_tag('cipherSuites')) + for suite in value: + self._dict_to_xml(suite, suites_elem, 'cipherSuite', xmlns) + if len(suites_elem) > 0: + elem.append(suites_elem) + elif key == 'algorithms' and isinstance(value, list) and name == 'cipherSuite': + # CipherSuite algorithms - container with ref children + algs_elem = XmlElement(ns_tag('algorithms')) + for alg in value: + alg_elem = XmlElement(ns_tag('algorithm')) + alg_elem.set('ref', str(alg)) + algs_elem.append(alg_elem) + if len(algs_elem) > 0: + elem.append(algs_elem) + elif key == 'ikev2TransformTypes' and isinstance(value, dict): + # ikev2TransformTypes - output as-is + self._dict_to_xml(value, elem, 'ikev2TransformTypes', xmlns) + elif key == 'cryptoRef' and isinstance(value, str): + # cryptoRef is a bom-ref string + ref_elem = XmlElement(ns_tag('cryptoRef')) + ref_elem.text = str(value) + elem.append(ref_elem) + elif key == 'cryptoRefArray' and isinstance(value, list): + # cryptoRefArray should output multiple cryptoRef elements (no container) + for ref in value: + ref_elem = XmlElement(ns_tag('cryptoRef')) + ref_elem.text = str(ref) + elem.append(ref_elem) + elif key == 'identifiers' and isinstance(value, list): + # Identifiers - container with children + ids_elem = XmlElement(ns_tag('identifiers')) + for ident in value: + id_elem = XmlElement(ns_tag('identifier')) + id_elem.text = str(ident) + ids_elem.append(id_elem) + if len(ids_elem) > 0: + elem.append(ids_elem) + elif key == 'ratings' and isinstance(value, list) and name == 'vulnerability': + # Vulnerability ratings - container with children + ratings_elem = XmlElement(ns_tag('ratings')) + for rating in value: + self._dict_to_xml(rating, ratings_elem, 'rating', xmlns) + if len(ratings_elem) > 0: + elem.append(ratings_elem) + elif key == 'cwes' and isinstance(value, list) and name == 'vulnerability': + # Vulnerability cwes - container with children + cwes_elem = XmlElement(ns_tag('cwes')) + for cwe in value: + cwe_elem = XmlElement(ns_tag('cwe')) + cwe_elem.text = str(cwe) + cwes_elem.append(cwe_elem) + if len(cwes_elem) > 0: + elem.append(cwes_elem) + elif key == 'references' and isinstance(value, list) and name == 'vulnerability': + # Vulnerability references - container with children + refs_elem = XmlElement(ns_tag('references')) + for ref in value: + self._dict_to_xml(ref, refs_elem, 'reference', xmlns) + if len(refs_elem) > 0: + elem.append(refs_elem) + elif key == 'affects' and isinstance(value, list): + # Vulnerability affects - container with children + affects_elem = XmlElement(ns_tag('affects')) + for target in value: + self._dict_to_xml(target, affects_elem, 'target', xmlns) + if len(affects_elem) > 0: + elem.append(affects_elem) + elif key == 'advisories' and isinstance(value, list): + # Advisories - container with children + adv_elem = XmlElement(ns_tag('advisories')) + for adv in value: + self._dict_to_xml(adv, adv_elem, 'advisory', xmlns) + if len(adv_elem) > 0: + elem.append(adv_elem) + elif key == 'credits' and isinstance(value, dict): + # Credits container + credits_elem = XmlElement(ns_tag('credits')) + if 'organizations' in value and value['organizations']: + orgs_elem = XmlElement(ns_tag('organizations')) + for org in value['organizations'] if isinstance(value['organizations'], list) else [value['organizations']]: + self._dict_to_xml(org, orgs_elem, 'organization', xmlns) + if len(orgs_elem) > 0: + credits_elem.append(orgs_elem) + if 'individuals' in value and value['individuals']: + indiv_elem = XmlElement(ns_tag('individuals')) + for indiv in value['individuals'] if isinstance(value['individuals'], list) else [value['individuals']]: + self._dict_to_xml(indiv, indiv_elem, 'individual', xmlns) + if len(indiv_elem) > 0: + credits_elem.append(indiv_elem) + if len(credits_elem) > 0: + elem.append(credits_elem) + elif key == 'versions' and isinstance(value, list) and name == 'target': + # Target versions - container with children + versions_elem = XmlElement(ns_tag('versions')) + for ver in value: + self._dict_to_xml(ver, versions_elem, 'version', xmlns) + if len(versions_elem) > 0: + elem.append(versions_elem) + elif key == 'response' and isinstance(value, list) and name == 'analysis': + # Analysis responses - container with children + responses_elem = XmlElement(ns_tag('responses')) + for resp in value: + resp_elem = XmlElement(ns_tag('response')) + resp_elem.text = str(resp) + responses_elem.append(resp_elem) + if len(responses_elem) > 0: + elem.append(responses_elem) + elif key == 'notes' and isinstance(value, list) and name == 'releaseNotes': + # ReleaseNotes notes - wrap each in + notes_elem = XmlElement(ns_tag('notes')) + for note in value: + self._dict_to_xml(note, notes_elem, 'note', xmlns) + if len(notes_elem) > 0: + elem.append(notes_elem) + elif key == 'resolves' and isinstance(value, list) and name == 'releaseNotes': + # ReleaseNotes resolves - wrap each in + resolves_elem = XmlElement(ns_tag('resolves')) + for issue in value: + self._dict_to_xml(issue, resolves_elem, 'issue', xmlns) + if len(resolves_elem) > 0: + elem.append(resolves_elem) + elif key == 'aliases' and isinstance(value, list): + # Aliases container with children + aliases_elem = XmlElement(ns_tag('aliases')) + for alias in value: + alias_elem = XmlElement(ns_tag('alias')) + alias_elem.text = str(alias) + aliases_elem.append(alias_elem) + if len(aliases_elem) > 0: + elem.append(aliases_elem) + elif key == 'references' and isinstance(value, list) and name == 'issue': + # Issue references - container with children + refs_elem = XmlElement(ns_tag('references')) + for ref in value: + url_elem = XmlElement(ns_tag('url')) + url_elem.text = str(ref) + refs_elem.append(url_elem) + if len(refs_elem) > 0: + elem.append(refs_elem) + elif key == 'copyright' and isinstance(value, list) and name == 'evidence': + # Evidence copyright - single element with children + copyright_elem = XmlElement(ns_tag('copyright')) + for cp in value: + if isinstance(cp, dict) and 'text' in cp: + text_elem = XmlElement(ns_tag('text')) + text_elem.text = str(cp['text']) + copyright_elem.append(text_elem) + elif isinstance(cp, str): + text_elem = XmlElement(ns_tag('text')) + text_elem.text = str(cp) + copyright_elem.append(text_elem) + if len(copyright_elem) > 0: + elem.append(copyright_elem) + elif key == 'text' and isinstance(value, dict): + # AttachedText - content as text, contentType and encoding as attributes + self._attached_text_to_xml(value, elem, xmlns) + elif isinstance(value, dict): + self._dict_to_xml(value, elem, key, xmlns) + elif isinstance(value, list): + for item in value: + self._dict_to_xml(item, elem, key, xmlns) + else: + child = XmlElement(ns_tag(key)) + # Handle boolean values (XML Schema expects lowercase true/false) + if isinstance(value, bool): + child.text = 'true' if value else 'false' + else: + child.text = str(value) + elem.append(child) + + if len(elem) > 0 or elem.text or len(elem.attrib) > 0: + parent.append(elem) + elif isinstance(data, list): + for item in data: + self._dict_to_xml(item, parent, name, xmlns) + else: + elem = XmlElement(ns_tag(name)) + # Handle boolean values (XML Schema expects lowercase true/false) + if isinstance(data, bool): + elem.text = 'true' if data else 'false' + else: + elem.text = str(data) + parent.append(elem) + + def _hash_to_xml(self, hash_data: dict, parent: XmlElement, xmlns: str) -> None: + """Convert a hash dict to XML with alg as attribute.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + elem = XmlElement(ns_tag('hash')) + + if 'alg' in hash_data: + elem.set('alg', str(hash_data['alg'])) + if 'content' in hash_data: + elem.text = str(hash_data['content']) + + parent.append(elem) + + def _license_to_xml(self, lic_data: dict, parent: XmlElement, xmlns: str) -> None: + """Convert a license dict to XML.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + + # Check if it's an expression or a license + if 'expression' in lic_data or 'value' in lic_data: + # License expression + elem = XmlElement(ns_tag('expression')) + elem.text = str(lic_data.get('expression') or lic_data.get('value', '')) + # Add acknowledgement attribute if present (1.6+) + if 'acknowledgement' in lic_data and lic_data['acknowledgement']: + elem.set('acknowledgement', str(lic_data['acknowledgement'])) + # Add bom-ref attribute if present + if 'bom-ref' in lic_data and lic_data['bom-ref']: + elem.set('bom-ref', str(lic_data['bom-ref'])) + parent.append(elem) + else: + # Disjunctive license + wrapper = XmlElement(ns_tag('license')) + if 'bom-ref' in lic_data: + wrapper.set('bom-ref', str(lic_data['bom-ref'])) + # Add acknowledgement attribute if present (1.6+) + if 'acknowledgement' in lic_data and lic_data['acknowledgement']: + wrapper.set('acknowledgement', str(lic_data['acknowledgement'])) + + # Add id or name + if 'id' in lic_data and lic_data['id']: + id_elem = XmlElement(ns_tag('id')) + id_elem.text = str(lic_data['id']) + wrapper.append(id_elem) + elif 'name' in lic_data and lic_data['name']: + name_elem = XmlElement(ns_tag('name')) + name_elem.text = str(lic_data['name']) + wrapper.append(name_elem) + + # Add other fields + for key in ['text', 'url']: + if key in lic_data and lic_data[key]: + child = XmlElement(ns_tag(key)) + if isinstance(lic_data[key], dict): + # AttachedText + if 'content' in lic_data[key]: + child.text = str(lic_data[key]['content']) + if 'contentType' in lic_data[key]: + child.set('content-type', str(lic_data[key]['contentType'])) + if 'encoding' in lic_data[key]: + child.set('encoding', str(lic_data[key]['encoding'])) + else: + child.text = str(lic_data[key]) + wrapper.append(child) + + parent.append(wrapper) + + def _data_classification_to_xml(self, dc_data: dict, parent: XmlElement, xmlns: str) -> None: + """Convert a DataClassification dict to XML with flow as attribute.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + elem = XmlElement(ns_tag('classification')) + + if 'flow' in dc_data: + elem.set('flow', str(dc_data['flow'])) + if 'classification' in dc_data: + elem.text = str(dc_data['classification']) + + parent.append(elem) + + def _attached_text_to_xml(self, text_data: dict, parent: XmlElement, xmlns: str) -> None: + """Convert an AttachedText dict to XML with attributes and text content.""" + def ns_tag(n): return f'{{{xmlns}}}{n}' + elem = XmlElement(ns_tag('text')) + + # Set attributes + if 'contentType' in text_data and text_data['contentType']: + elem.set('content-type', str(text_data['contentType'])) + if 'encoding' in text_data and text_data['encoding']: + elem.set('encoding', str(text_data['encoding'])) + + # Set text content + if 'content' in text_data and text_data['content']: + elem.text = str(text_data['content']) + + parent.append(elem) + def generate(self, force_regeneration: bool = False) -> None: if self.generated and not force_regeneration: return - _view = SCHEMA_VERSIONS[self.schema_version_enum] bom = self.get_bom() bom.validate() xmlns = self.get_target_namespace() + with BomRefDiscriminator.from_bom(bom): - self._bom_xml = '\n' + xml_dumps( # type:ignore[call-overload] - bom.as_xml( # type:ignore[attr-defined] - _view, as_string=False, xmlns=xmlns), - method='xml', default_namespace=xmlns, encoding='unicode', - # `xml-declaration` is inconsistent/bugged in py38, - # especially on Windows it will print a non-UTF8 codepage. - # Furthermore, it might add an encoding of "utf-8" which is redundant default value of XML. - # -> so we write the declaration manually, as long as py38 is supported. + xml_elem = self._bom_to_xml(bom, xmlns) + # Register the namespace as empty prefix so it becomes the default + from xml.etree.ElementTree import register_namespace + register_namespace('', xmlns) + self._bom_xml = '\n' + xml_dumps( + xml_elem, + method='xml', encoding='unicode', xml_declaration=False) self.generated = True @@ -85,7 +948,7 @@ def output_as_string(self, *, indent: Optional[Union[int, str]] = None, **kwargs: Any) -> str: self.generate() - return self._bom_xml if indent is None else dom_parseString( # nosecc B318 + return self._bom_xml if indent is None else dom_parseString( # nosec B318 self._bom_xml).toprettyxml( indent=self.__make_indent(indent) # do not set `encoding` - this would convert result to binary, not string diff --git a/cyclonedx/schema/schema.py b/cyclonedx/schema/schema.py index 3be105619..c74302cd8 100644 --- a/cyclonedx/schema/schema.py +++ b/cyclonedx/schema/schema.py @@ -18,12 +18,10 @@ from abc import ABC, abstractmethod from typing import Literal -from py_serializable import ViewType - from . import SchemaVersion -class BaseSchemaVersion(ABC, ViewType): +class BaseSchemaVersion(ABC): @property @abstractmethod diff --git a/cyclonedx/serialization/__init__.py b/cyclonedx/serialization/__init__.py index 1fec0026f..33571e691 100644 --- a/cyclonedx/serialization/__init__.py +++ b/cyclonedx/serialization/__init__.py @@ -17,16 +17,17 @@ """ -Set of helper classes for use with ``serializable`` when conducting (de-)serialization. +Serialization infrastructure for CycloneDX models using attrs and cattrs. + +This module provides converters and utilities for serializing/deserializing +CycloneDX models to/from JSON and XML formats. """ import sys from typing import Any, Optional from uuid import UUID -# See https://github.com/package-url/packageurl-python/issues/65 from packageurl import PackageURL -from py_serializable.helpers import BaseHelper if sys.version_info >= (3, 13): from warnings import deprecated @@ -34,33 +35,36 @@ from typing_extensions import deprecated from ..exception.serialization import CycloneDxDeserializationException, SerializationOfUnexpectedValueException -from ..model.bom_ref import BomRef -from ..model.license import _LicenseRepositorySerializationHelper - - -@deprecated('Use :class:`BomRef` instead.') -class BomRefHelper(BaseHelper): - """**DEPRECATED** in favour of :class:`BomRef`. - - .. deprecated:: 8.6 - Use :class:`BomRef` instead. - """ - - # TODO: remove, no longer needed - - @classmethod - def serialize(cls, o: Any) -> Optional[str]: - return BomRef.serialize(o) +from ._converters import ( + ALL_VERSIONS, + METADATA_KEY_INCLUDE_NONE, + METADATA_KEY_JSON_NAME, + METADATA_KEY_TYPE_MAPPING, + METADATA_KEY_VERSIONS, + METADATA_KEY_XML_ARRAY, + METADATA_KEY_XML_ATTR, + METADATA_KEY_XML_NAME, + METADATA_KEY_XML_SEQUENCE, + VERSIONS_1_0_THROUGH_1_3, + VERSIONS_1_1_AND_LATER, + VERSIONS_1_2_AND_LATER, + VERSIONS_1_3_AND_LATER, + VERSIONS_1_4_AND_LATER, + VERSIONS_1_5_AND_LATER, + VERSIONS_1_6_AND_LATER, + VERSIONS_1_7_AND_LATER, + CycloneDxConverter, + XmlArrayConfig, + make_converter, + versions, +) + + +class PackageUrl: + """Helper for PackageURL serialization.""" @classmethod - def deserialize(cls, o: Any) -> BomRef: - return BomRef.deserialize(o) - - -class PackageUrl(BaseHelper): - - @classmethod - def serialize(cls, o: Any, ) -> str: + def serialize(cls, o: Any) -> str: if isinstance(o, PackageURL): return str(o.to_string()) raise SerializationOfUnexpectedValueException( @@ -76,7 +80,8 @@ def deserialize(cls, o: Any) -> PackageURL: ) from err -class UrnUuidHelper(BaseHelper): +class UrnUuidHelper: + """Helper for UUID serialization as URN.""" @classmethod def serialize(cls, o: Any) -> str: @@ -95,14 +100,33 @@ def deserialize(cls, o: Any) -> UUID: ) from err -@deprecated('No public API planned for replacing this,') -class LicenseRepositoryHelper(_LicenseRepositorySerializationHelper): - """**DEPRECATED** - - .. deprecated:: 8.6 - No public API planned for replacing this, - """ - - # TODO: remove, no longer needed - - pass +# Re-export from _converters for public API +__all__ = [ + # Converter + 'CycloneDxConverter', + 'make_converter', + # Metadata keys + 'METADATA_KEY_VERSIONS', + 'METADATA_KEY_JSON_NAME', + 'METADATA_KEY_XML_NAME', + 'METADATA_KEY_XML_ATTR', + 'METADATA_KEY_XML_SEQUENCE', + 'METADATA_KEY_XML_ARRAY', + 'METADATA_KEY_INCLUDE_NONE', + 'METADATA_KEY_TYPE_MAPPING', + # Version sets + 'ALL_VERSIONS', + 'VERSIONS_1_1_AND_LATER', + 'VERSIONS_1_2_AND_LATER', + 'VERSIONS_1_3_AND_LATER', + 'VERSIONS_1_4_AND_LATER', + 'VERSIONS_1_5_AND_LATER', + 'VERSIONS_1_6_AND_LATER', + 'VERSIONS_1_7_AND_LATER', + 'versions', + # Configs + 'XmlArrayConfig', + # Helpers + 'PackageUrl', + 'UrnUuidHelper', +] diff --git a/pyproject.toml b/pyproject.toml index baef0ca3d..9147d2add 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,8 @@ keywords = [ [tool.poetry.dependencies] python = "^3.9" packageurl-python = ">=0.11, <2" -py-serializable = "^2.1.0" +attrs = ">=23.1.0" +cattrs = ">=23.1.0" sortedcontainers = "^2.4.0" license-expression = "^30" jsonschema = { version = "^4.25", extras=['format-nongpl'], optional=true } diff --git a/tests/__init__.py b/tests/__init__.py index e58c6aa22..1b536711c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -23,6 +23,7 @@ from unittest import TestCase from uuid import UUID +import attrs from sortedcontainers import SortedSet from cyclonedx.output import BomRefDiscriminator as _BomRefDiscriminator @@ -98,7 +99,16 @@ def __deep_dict(self, o: Any) -> Any: return {k: self.__deep_dict(v) for k, v in o.items()} if isinstance(o, (set, SortedSet)): # this method returns dict. `dict` is not hashable, so use `tuple` instead. - return tuple(self.__deep_dict(i) for i in sorted(o, key=hash)) + ('%conv:%set',) + # Use a stable sort key based on string representation of deep_dict output + items = [self.__deep_dict(i) for i in o] + # Sort by string representation for stability across Python sessions + items.sort(key=lambda x: str(x)) + return tuple(items) + ('%conv:%set',) + # Handle attrs classes (which use slots and don't have __dict__) + if attrs.has(type(o)): + d = {a.name: self.__deep_dict(getattr(o, a.name)) for a in attrs.fields(type(o))} + d['%conv'] = str(type(o)) + return d if hasattr(o, '__dict__'): d = {a: self.__deep_dict(v) for a, v in o.__dict__.items() if '__' not in a} d['%conv'] = str(type(o)) diff --git a/tests/_data/models.py b/tests/_data/models.py index 43d62570e..a9b6052d7 100644 --- a/tests/_data/models.py +++ b/tests/_data/models.py @@ -170,8 +170,8 @@ def get_crypto_properties_algorithm() -> CryptoProperties: execution_environment=CryptoExecutionEnvironment.SOFTWARE_PLAIN_RAM, implementation_platform=CryptoImplementationPlatform.GENERIC, certification_levels=[ - CryptoCertificationLevel.FIPS140_1_L1, - CryptoCertificationLevel.FIPS140_2_L3, + CryptoCertificationLevel.FIPS_140_1_L1, + CryptoCertificationLevel.FIPS_140_2_L3, CryptoCertificationLevel.OTHER ], mode=CryptoMode.ECB, diff --git a/tests/_data/snapshots/enum_ComponentScope-1.1.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.1.xml.bin index 810b8976b..a4f9d4839 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.1.xml.bin @@ -1,20 +1,23 @@ - + dummy-EXCLUDED excluded + false dummy-OPTIONAL optional + false dummy-REQUIRED required + false diff --git a/tests/_data/snapshots/enum_ComponentScope-1.2.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.2.json.bin index 08129f201..49f4ed8a2 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.2.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.2.json.bin @@ -1,25 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", "type": "library", - "version": "" + "bom-ref": "scoped-EXCLUDED", + "version": "", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", "type": "library", - "version": "" + "bom-ref": "scoped-OPTIONAL", + "version": "", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", "type": "library", - "version": "" + "bom-ref": "scoped-REQUIRED", + "version": "", + "scope": "required" } ], "dependencies": [ @@ -33,11 +38,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.2.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.2.xml.bin index 2bc682153..8e014eb8d 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentScope-1.3.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.3.json.bin index 9c30c6cb9..1a5f3a106 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.3.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.3.json.bin @@ -1,25 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", "type": "library", - "version": "" + "bom-ref": "scoped-EXCLUDED", + "version": "", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", "type": "library", - "version": "" + "bom-ref": "scoped-OPTIONAL", + "version": "", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", "type": "library", - "version": "" + "bom-ref": "scoped-REQUIRED", + "version": "", + "scope": "required" } ], "dependencies": [ @@ -33,11 +38,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.3.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.3.xml.bin index f10fbd5a6..8a00801f2 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentScope-1.4.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.4.json.bin index a46930fff..7aab75358 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.4.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.4.json.bin @@ -1,22 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", - "type": "library" + "type": "library", + "bom-ref": "scoped-EXCLUDED", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", - "type": "library" + "type": "library", + "bom-ref": "scoped-OPTIONAL", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", - "type": "library" + "type": "library", + "bom-ref": "scoped-REQUIRED", + "scope": "required" } ], "dependencies": [ @@ -30,11 +35,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.4.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.4.xml.bin index 2d6382e77..319e956f7 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentScope-1.5.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.5.json.bin index 08c95fbe1..1c7849e08 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.5.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.5.json.bin @@ -1,22 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", - "type": "library" + "type": "library", + "bom-ref": "scoped-EXCLUDED", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", - "type": "library" + "type": "library", + "bom-ref": "scoped-OPTIONAL", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", - "type": "library" + "type": "library", + "bom-ref": "scoped-REQUIRED", + "scope": "required" } ], "dependencies": [ @@ -30,9 +35,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -43,8 +45,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.5.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.5.xml.bin index 49a4b47a5..4f6cceade 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentScope-1.6.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.6.json.bin index 9c5999f47..0e9723190 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.6.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.6.json.bin @@ -1,22 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", - "type": "library" + "type": "library", + "bom-ref": "scoped-EXCLUDED", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", - "type": "library" + "type": "library", + "bom-ref": "scoped-OPTIONAL", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", - "type": "library" + "type": "library", + "bom-ref": "scoped-REQUIRED", + "scope": "required" } ], "dependencies": [ @@ -30,9 +35,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -43,8 +45,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.6.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.6.xml.bin index 16002be6a..14c189275 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentScope-1.7.json.bin b/tests/_data/snapshots/enum_ComponentScope-1.7.json.bin index 491f8880a..7d1a6d15c 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.7.json.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.7.json.bin @@ -1,22 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "scoped-EXCLUDED", "name": "dummy-EXCLUDED", - "scope": "excluded", - "type": "library" + "type": "library", + "bom-ref": "scoped-EXCLUDED", + "scope": "excluded" }, { - "bom-ref": "scoped-OPTIONAL", "name": "dummy-OPTIONAL", - "scope": "optional", - "type": "library" + "type": "library", + "bom-ref": "scoped-OPTIONAL", + "scope": "optional" }, { - "bom-ref": "scoped-REQUIRED", "name": "dummy-REQUIRED", - "scope": "required", - "type": "library" + "type": "library", + "bom-ref": "scoped-REQUIRED", + "scope": "required" } ], "dependencies": [ @@ -30,9 +35,6 @@ "ref": "scoped-REQUIRED" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -43,8 +45,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_ComponentScope-1.7.xml.bin b/tests/_data/snapshots/enum_ComponentScope-1.7.xml.bin index 9e3dfc35f..907016099 100644 --- a/tests/_data/snapshots/enum_ComponentScope-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ComponentScope-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.1.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.1.xml.bin index 95ad11e54..16649c484 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.1.xml.bin @@ -1,29 +1,35 @@ - + dummy APPLICATION + false dummy DEVICE + false dummy FILE + false dummy FRAMEWORK + false dummy LIBRARY + false dummy OPERATING_SYSTEM + false diff --git a/tests/_data/snapshots/enum_ComponentType-1.2.json.bin b/tests/_data/snapshots/enum_ComponentType-1.2.json.bin index 4af3254a7..785a1560a 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.2.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.2.json.bin @@ -1,51 +1,56 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", "type": "application", + "bom-ref": "typed-APPLICATION", "version": "" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", "type": "container", + "bom-ref": "typed-CONTAINER", "version": "" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", "type": "device", + "bom-ref": "typed-DEVICE", "version": "" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", "type": "file", + "bom-ref": "typed-FILE", "version": "" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", "type": "firmware", + "bom-ref": "typed-FIRMWARE", "version": "" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", "type": "framework", + "bom-ref": "typed-FRAMEWORK", "version": "" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", "type": "library", + "bom-ref": "typed-LIBRARY", "version": "" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM", "version": "" } ], @@ -75,11 +80,6 @@ "ref": "typed-OPERATING_SYSTEM" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentType-1.2.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.2.xml.bin index 231b39694..1b13574bd 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.3.json.bin b/tests/_data/snapshots/enum_ComponentType-1.3.json.bin index aaf85dfb2..d15cd0647 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.3.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.3.json.bin @@ -1,51 +1,56 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", "type": "application", + "bom-ref": "typed-APPLICATION", "version": "" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", "type": "container", + "bom-ref": "typed-CONTAINER", "version": "" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", "type": "device", + "bom-ref": "typed-DEVICE", "version": "" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", "type": "file", + "bom-ref": "typed-FILE", "version": "" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", "type": "firmware", + "bom-ref": "typed-FIRMWARE", "version": "" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", "type": "framework", + "bom-ref": "typed-FRAMEWORK", "version": "" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", "type": "library", + "bom-ref": "typed-LIBRARY", "version": "" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM", "version": "" } ], @@ -75,11 +80,6 @@ "ref": "typed-OPERATING_SYSTEM" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentType-1.3.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.3.xml.bin index 849052aaf..700a6d200 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.4.json.bin b/tests/_data/snapshots/enum_ComponentType-1.4.json.bin index 437468895..2fa3e1e50 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.4.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.4.json.bin @@ -1,44 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", - "type": "application" + "type": "application", + "bom-ref": "typed-APPLICATION" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", - "type": "container" + "type": "container", + "bom-ref": "typed-CONTAINER" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", - "type": "device" + "type": "device", + "bom-ref": "typed-DEVICE" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", - "type": "file" + "type": "file", + "bom-ref": "typed-FILE" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", - "type": "firmware" + "type": "firmware", + "bom-ref": "typed-FIRMWARE" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", - "type": "framework" + "type": "framework", + "bom-ref": "typed-FRAMEWORK" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", - "type": "library" + "type": "library", + "bom-ref": "typed-LIBRARY" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", - "type": "operating-system" + "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM" } ], "dependencies": [ @@ -67,11 +72,6 @@ "ref": "typed-OPERATING_SYSTEM" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ComponentType-1.4.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.4.xml.bin index ecf2566dc..ac65235ba 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.5.json.bin b/tests/_data/snapshots/enum_ComponentType-1.5.json.bin index c9380e542..60c2d6659 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.5.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.5.json.bin @@ -1,64 +1,69 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", - "type": "application" + "type": "application", + "bom-ref": "typed-APPLICATION" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", - "type": "container" + "type": "container", + "bom-ref": "typed-CONTAINER" }, { - "bom-ref": "typed-DATA", "name": "dummy DATA", - "type": "data" + "type": "data", + "bom-ref": "typed-DATA" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", - "type": "device" + "type": "device", + "bom-ref": "typed-DEVICE" }, { - "bom-ref": "typed-DEVICE_DRIVER", "name": "dummy DEVICE_DRIVER", - "type": "device-driver" + "type": "device-driver", + "bom-ref": "typed-DEVICE_DRIVER" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", - "type": "file" + "type": "file", + "bom-ref": "typed-FILE" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", - "type": "firmware" + "type": "firmware", + "bom-ref": "typed-FIRMWARE" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", - "type": "framework" + "type": "framework", + "bom-ref": "typed-FRAMEWORK" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", - "type": "library" + "type": "library", + "bom-ref": "typed-LIBRARY" }, { - "bom-ref": "typed-MACHINE_LEARNING_MODEL", "name": "dummy MACHINE_LEARNING_MODEL", - "type": "machine-learning-model" + "type": "machine-learning-model", + "bom-ref": "typed-MACHINE_LEARNING_MODEL" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", - "type": "operating-system" + "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM" }, { - "bom-ref": "typed-PLATFORM", "name": "dummy PLATFORM", - "type": "platform" + "type": "platform", + "bom-ref": "typed-PLATFORM" } ], "dependencies": [ @@ -99,9 +104,6 @@ "ref": "typed-PLATFORM" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -112,8 +114,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ComponentType-1.5.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.5.xml.bin index 7eece9d39..a1e22e4e7 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.6.json.bin b/tests/_data/snapshots/enum_ComponentType-1.6.json.bin index 14beba083..fde042f0c 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.6.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.6.json.bin @@ -1,69 +1,74 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", - "type": "application" + "type": "application", + "bom-ref": "typed-APPLICATION" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", - "type": "container" + "type": "container", + "bom-ref": "typed-CONTAINER" }, { - "bom-ref": "typed-CRYPTOGRAPHIC_ASSET", "name": "dummy CRYPTOGRAPHIC_ASSET", - "type": "cryptographic-asset" + "type": "cryptographic-asset", + "bom-ref": "typed-CRYPTOGRAPHIC_ASSET" }, { - "bom-ref": "typed-DATA", "name": "dummy DATA", - "type": "data" + "type": "data", + "bom-ref": "typed-DATA" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", - "type": "device" + "type": "device", + "bom-ref": "typed-DEVICE" }, { - "bom-ref": "typed-DEVICE_DRIVER", "name": "dummy DEVICE_DRIVER", - "type": "device-driver" + "type": "device-driver", + "bom-ref": "typed-DEVICE_DRIVER" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", - "type": "file" + "type": "file", + "bom-ref": "typed-FILE" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", - "type": "firmware" + "type": "firmware", + "bom-ref": "typed-FIRMWARE" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", - "type": "framework" + "type": "framework", + "bom-ref": "typed-FRAMEWORK" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", - "type": "library" + "type": "library", + "bom-ref": "typed-LIBRARY" }, { - "bom-ref": "typed-MACHINE_LEARNING_MODEL", "name": "dummy MACHINE_LEARNING_MODEL", - "type": "machine-learning-model" + "type": "machine-learning-model", + "bom-ref": "typed-MACHINE_LEARNING_MODEL" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", - "type": "operating-system" + "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM" }, { - "bom-ref": "typed-PLATFORM", "name": "dummy PLATFORM", - "type": "platform" + "type": "platform", + "bom-ref": "typed-PLATFORM" } ], "dependencies": [ @@ -107,9 +112,6 @@ "ref": "typed-PLATFORM" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -120,8 +122,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ComponentType-1.6.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.6.xml.bin index 84936bca4..279f0d6f4 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ComponentType-1.7.json.bin b/tests/_data/snapshots/enum_ComponentType-1.7.json.bin index 90b109fba..11d5f4bdc 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.7.json.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.7.json.bin @@ -1,69 +1,74 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "typed-APPLICATION", "name": "dummy APPLICATION", - "type": "application" + "type": "application", + "bom-ref": "typed-APPLICATION" }, { - "bom-ref": "typed-CONTAINER", "name": "dummy CONTAINER", - "type": "container" + "type": "container", + "bom-ref": "typed-CONTAINER" }, { - "bom-ref": "typed-CRYPTOGRAPHIC_ASSET", "name": "dummy CRYPTOGRAPHIC_ASSET", - "type": "cryptographic-asset" + "type": "cryptographic-asset", + "bom-ref": "typed-CRYPTOGRAPHIC_ASSET" }, { - "bom-ref": "typed-DATA", "name": "dummy DATA", - "type": "data" + "type": "data", + "bom-ref": "typed-DATA" }, { - "bom-ref": "typed-DEVICE", "name": "dummy DEVICE", - "type": "device" + "type": "device", + "bom-ref": "typed-DEVICE" }, { - "bom-ref": "typed-DEVICE_DRIVER", "name": "dummy DEVICE_DRIVER", - "type": "device-driver" + "type": "device-driver", + "bom-ref": "typed-DEVICE_DRIVER" }, { - "bom-ref": "typed-FILE", "name": "dummy FILE", - "type": "file" + "type": "file", + "bom-ref": "typed-FILE" }, { - "bom-ref": "typed-FIRMWARE", "name": "dummy FIRMWARE", - "type": "firmware" + "type": "firmware", + "bom-ref": "typed-FIRMWARE" }, { - "bom-ref": "typed-FRAMEWORK", "name": "dummy FRAMEWORK", - "type": "framework" + "type": "framework", + "bom-ref": "typed-FRAMEWORK" }, { - "bom-ref": "typed-LIBRARY", "name": "dummy LIBRARY", - "type": "library" + "type": "library", + "bom-ref": "typed-LIBRARY" }, { - "bom-ref": "typed-MACHINE_LEARNING_MODEL", "name": "dummy MACHINE_LEARNING_MODEL", - "type": "machine-learning-model" + "type": "machine-learning-model", + "bom-ref": "typed-MACHINE_LEARNING_MODEL" }, { - "bom-ref": "typed-OPERATING_SYSTEM", "name": "dummy OPERATING_SYSTEM", - "type": "operating-system" + "type": "operating-system", + "bom-ref": "typed-OPERATING_SYSTEM" }, { - "bom-ref": "typed-PLATFORM", "name": "dummy PLATFORM", - "type": "platform" + "type": "platform", + "bom-ref": "typed-PLATFORM" } ], "dependencies": [ @@ -107,9 +112,6 @@ "ref": "typed-PLATFORM" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -120,8 +122,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_ComponentType-1.7.xml.bin b/tests/_data/snapshots/enum_ComponentType-1.7.xml.bin index 9913c12f4..0066e0692 100644 --- a/tests/_data/snapshots/enum_ComponentType-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ComponentType-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.1.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.1.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_DataFlow-1.2.json.bin b/tests/_data/snapshots/enum_DataFlow-1.2.json.bin index cfd8d34e8..5c090a5d0 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.2.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.2.json.bin @@ -1,38 +1,38 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/enum_DataFlow-1.2.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.2.xml.bin index 28afa0858..919764cbf 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.2.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.3.json.bin b/tests/_data/snapshots/enum_DataFlow-1.3.json.bin index ec868cdfb..a5c906ed9 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.3.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.3.json.bin @@ -1,38 +1,38 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/enum_DataFlow-1.3.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.3.xml.bin index 92559dc73..a566c19d7 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.3.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.4.json.bin b/tests/_data/snapshots/enum_DataFlow-1.4.json.bin index e90aec28a..b1c1e4891 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.4.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.4.json.bin @@ -1,38 +1,38 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/enum_DataFlow-1.4.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.4.xml.bin index 07d3b99b6..4f93dd539 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.4.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.5.json.bin b/tests/_data/snapshots/enum_DataFlow-1.5.json.bin index 7ee12db92..97f4eb716 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.5.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.5.json.bin @@ -1,48 +1,48 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/enum_DataFlow-1.5.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.5.xml.bin index d7fb1d167..0f3ff0f1d 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.5.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.6.json.bin b/tests/_data/snapshots/enum_DataFlow-1.6.json.bin index 063107b3e..67f5be029 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.6.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.6.json.bin @@ -1,48 +1,48 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/enum_DataFlow-1.6.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.6.xml.bin index f7fad9535..7dcb33271 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.6.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_DataFlow-1.7.json.bin b/tests/_data/snapshots/enum_DataFlow-1.7.json.bin index fd5eb8667..a6de8940a 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.7.json.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.7.json.bin @@ -1,48 +1,48 @@ { - "dependencies": [ - { - "ref": "dummy" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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", "services": [ { + "name": "dummy", "bom-ref": "dummy", "data": [ { - "classification": "BI_DIRECTIONAL", - "flow": "bi-directional" + "flow": "bi-directional", + "classification": "BI_DIRECTIONAL" }, { - "classification": "INBOUND", - "flow": "inbound" + "flow": "inbound", + "classification": "INBOUND" }, { - "classification": "OUTBOUND", - "flow": "outbound" + "flow": "outbound", + "classification": "OUTBOUND" }, { - "classification": "UNKNOWN", - "flow": "unknown" + "flow": "unknown", + "classification": "UNKNOWN" } - ], - "name": "dummy" + ] + } + ], + "dependencies": [ + { + "ref": "dummy" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_DataFlow-1.7.xml.bin b/tests/_data/snapshots/enum_DataFlow-1.7.xml.bin index 04c4f0136..5df46b2ed 100644 --- a/tests/_data/snapshots/enum_DataFlow-1.7.xml.bin +++ b/tests/_data/snapshots/enum_DataFlow-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.1.xml.bin b/tests/_data/snapshots/enum_Encoding-1.1.xml.bin index 66b78cb97..7485d93d9 100644 --- a/tests/_data/snapshots/enum_Encoding-1.1.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.1.xml.bin @@ -1,5 +1,5 @@ - + dummy @@ -10,6 +10,7 @@ att.encoding: BASE_64 + false diff --git a/tests/_data/snapshots/enum_Encoding-1.2.json.bin b/tests/_data/snapshots/enum_Encoding-1.2.json.bin index 224d106a8..9b3ae1c4b 100644 --- a/tests/_data/snapshots/enum_Encoding-1.2.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.2.json.bin @@ -1,7 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "licenses": [ { "license": { @@ -13,10 +21,7 @@ } } } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -24,11 +29,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_Encoding-1.2.xml.bin b/tests/_data/snapshots/enum_Encoding-1.2.xml.bin index bf3307a6d..d14b88874 100644 --- a/tests/_data/snapshots/enum_Encoding-1.2.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.3.json.bin b/tests/_data/snapshots/enum_Encoding-1.3.json.bin index f5c1794ac..6496007d4 100644 --- a/tests/_data/snapshots/enum_Encoding-1.3.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.3.json.bin @@ -1,7 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "licenses": [ { "license": { @@ -13,10 +21,7 @@ } } } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -24,11 +29,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_Encoding-1.3.xml.bin b/tests/_data/snapshots/enum_Encoding-1.3.xml.bin index 9c0f1a14a..6593f3642 100644 --- a/tests/_data/snapshots/enum_Encoding-1.3.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.4.json.bin b/tests/_data/snapshots/enum_Encoding-1.4.json.bin index 02a99e102..8096ea70f 100644 --- a/tests/_data/snapshots/enum_Encoding-1.4.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.4.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "licenses": [ { @@ -13,9 +20,7 @@ } } } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -23,11 +28,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_Encoding-1.4.xml.bin b/tests/_data/snapshots/enum_Encoding-1.4.xml.bin index d234c5202..2a9ae232a 100644 --- a/tests/_data/snapshots/enum_Encoding-1.4.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.5.json.bin b/tests/_data/snapshots/enum_Encoding-1.5.json.bin index 6ca365eeb..461442e5a 100644 --- a/tests/_data/snapshots/enum_Encoding-1.5.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.5.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "licenses": [ { @@ -13,9 +20,7 @@ } } } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "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" diff --git a/tests/_data/snapshots/enum_Encoding-1.5.xml.bin b/tests/_data/snapshots/enum_Encoding-1.5.xml.bin index 6f25b2f8f..791808e51 100644 --- a/tests/_data/snapshots/enum_Encoding-1.5.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.6.json.bin b/tests/_data/snapshots/enum_Encoding-1.6.json.bin index f3d470e0a..67a82c743 100644 --- a/tests/_data/snapshots/enum_Encoding-1.6.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.6.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "licenses": [ { @@ -13,9 +20,7 @@ } } } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "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" diff --git a/tests/_data/snapshots/enum_Encoding-1.6.xml.bin b/tests/_data/snapshots/enum_Encoding-1.6.xml.bin index c2b00d139..9708d0e3a 100644 --- a/tests/_data/snapshots/enum_Encoding-1.6.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_Encoding-1.7.json.bin b/tests/_data/snapshots/enum_Encoding-1.7.json.bin index 253f842ae..814f9aedc 100644 --- a/tests/_data/snapshots/enum_Encoding-1.7.json.bin +++ b/tests/_data/snapshots/enum_Encoding-1.7.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "licenses": [ { @@ -13,9 +20,7 @@ } } } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_Encoding-1.7.xml.bin b/tests/_data/snapshots/enum_Encoding-1.7.xml.bin index 861dd77fa..9dff57341 100644 --- a/tests/_data/snapshots/enum_Encoding-1.7.xml.bin +++ b/tests/_data/snapshots/enum_Encoding-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.1.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.1.xml.bin index be2cf7e1a..bbe6c9b6a 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.1.xml.bin @@ -1,19 +1,14 @@ - + dummy + false - - tests/ADVERSARY_MODEL - tests/ADVISORIES - - tests/ATTESTATION - tests/BOM @@ -23,126 +18,36 @@ tests/BUILD_SYSTEM - - tests/CERTIFICATION_REPORT - tests/CHAT - - tests/CITATION - - - tests/CODIFIED_INFRASTRUCTURE - - - tests/COMPONENT_ANALYSIS_REPORT - - - tests/CONFIGURATION - - - tests/DIGITAL_SIGNATURE - tests/DISTRIBUTION - - tests/DISTRIBUTION_INTAKE - tests/DOCUMENTATION - - tests/DYNAMIC_ANALYSIS_REPORT - - - tests/ELECTRONIC_SIGNATURE - - - tests/EVIDENCE - - - tests/EXPLOITABILITY_STATEMENT - - - tests/FORMULATION - tests/ISSUE_TRACKER tests/LICENSE - - tests/LOG - tests/MAILING_LIST - - tests/MATURITY_REPORT - - - tests/MODEL_CARD - tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - - - tests/PENTEST_REPORT - - - tests/POAM - - - tests/QUALITY_METRICS - - - tests/RELEASE_NOTES - - - tests/RFC_9166 - - - tests/RISK_ASSESSMENT - - - tests/RUNTIME_ANALYSIS_REPORT - - - tests/SECURITY_CONTACT - tests/SOCIAL - - tests/SOURCE_DISTRIBUTION - - - tests/STATIC_ANALYSIS_REPORT - tests/SUPPORT - - tests/THREAT_MODEL - tests/SCM - - tests/VULNERABILITY_ASSERTION - tests/WEBSITE diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.2.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.2.json.bin index 6d578afd1..4064670e2 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.2.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.2.json.bin @@ -1,20 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "externalReferences": [ - { - "type": "other", - "url": "tests/ADVERSARY_MODEL" - }, { "type": "advisories", "url": "tests/ADVISORIES" }, - { - "type": "other", - "url": "tests/ATTESTATION" - }, { "type": "bom", "url": "tests/BOM" @@ -27,66 +27,18 @@ "type": "build-system", "url": "tests/BUILD_SYSTEM" }, - { - "type": "other", - "url": "tests/CERTIFICATION_REPORT" - }, { "type": "chat", "url": "tests/CHAT" }, - { - "type": "other", - "url": "tests/CITATION" - }, - { - "type": "other", - "url": "tests/CODIFIED_INFRASTRUCTURE" - }, - { - "type": "other", - "url": "tests/COMPONENT_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/CONFIGURATION" - }, - { - "type": "other", - "url": "tests/DIGITAL_SIGNATURE" - }, { "type": "distribution", "url": "tests/DISTRIBUTION" }, - { - "type": "other", - "url": "tests/DISTRIBUTION_INTAKE" - }, { "type": "documentation", "url": "tests/DOCUMENTATION" }, - { - "type": "other", - "url": "tests/DYNAMIC_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/ELECTRONIC_SIGNATURE" - }, - { - "type": "other", - "url": "tests/EVIDENCE" - }, - { - "type": "other", - "url": "tests/EXPLOITABILITY_STATEMENT" - }, - { - "type": "other", - "url": "tests/FORMULATION" - }, { "type": "issue-tracker", "url": "tests/ISSUE_TRACKER" @@ -95,106 +47,31 @@ "type": "license", "url": "tests/LICENSE" }, - { - "type": "other", - "url": "tests/LOG" - }, { "type": "mailing-list", "url": "tests/MAILING_LIST" }, - { - "type": "other", - "url": "tests/MATURITY_REPORT" - }, - { - "type": "other", - "url": "tests/MODEL_CARD" - }, { "type": "other", "url": "tests/OTHER" }, - { - "type": "other", - "url": "tests/PATENT" - }, - { - "type": "other", - "url": "tests/PATENT_ASSERTION" - }, - { - "type": "other", - "url": "tests/PATENT_FAMILY" - }, - { - "type": "other", - "url": "tests/PENTEST_REPORT" - }, - { - "type": "other", - "url": "tests/POAM" - }, - { - "type": "other", - "url": "tests/QUALITY_METRICS" - }, - { - "type": "other", - "url": "tests/RELEASE_NOTES" - }, - { - "type": "other", - "url": "tests/RFC_9166" - }, - { - "type": "other", - "url": "tests/RISK_ASSESSMENT" - }, - { - "type": "other", - "url": "tests/RUNTIME_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/SECURITY_CONTACT" - }, { "type": "social", "url": "tests/SOCIAL" }, - { - "type": "other", - "url": "tests/SOURCE_DISTRIBUTION" - }, - { - "type": "other", - "url": "tests/STATIC_ANALYSIS_REPORT" - }, { "type": "support", "url": "tests/SUPPORT" }, - { - "type": "other", - "url": "tests/THREAT_MODEL" - }, { "type": "vcs", "url": "tests/SCM" }, - { - "type": "other", - "url": "tests/VULNERABILITY_ASSERTION" - }, { "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -202,11 +79,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.2.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.2.xml.bin index 5adf4c1c1..bbfa9d624 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -8,15 +8,9 @@ dummy - - tests/ADVERSARY_MODEL - tests/ADVISORIES - - tests/ATTESTATION - tests/BOM @@ -26,126 +20,36 @@ tests/BUILD_SYSTEM - - tests/CERTIFICATION_REPORT - tests/CHAT - - tests/CITATION - - - tests/CODIFIED_INFRASTRUCTURE - - - tests/COMPONENT_ANALYSIS_REPORT - - - tests/CONFIGURATION - - - tests/DIGITAL_SIGNATURE - tests/DISTRIBUTION - - tests/DISTRIBUTION_INTAKE - tests/DOCUMENTATION - - tests/DYNAMIC_ANALYSIS_REPORT - - - tests/ELECTRONIC_SIGNATURE - - - tests/EVIDENCE - - - tests/EXPLOITABILITY_STATEMENT - - - tests/FORMULATION - tests/ISSUE_TRACKER tests/LICENSE - - tests/LOG - tests/MAILING_LIST - - tests/MATURITY_REPORT - - - tests/MODEL_CARD - tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - - - tests/PENTEST_REPORT - - - tests/POAM - - - tests/QUALITY_METRICS - - - tests/RELEASE_NOTES - - - tests/RFC_9166 - - - tests/RISK_ASSESSMENT - - - tests/RUNTIME_ANALYSIS_REPORT - - - tests/SECURITY_CONTACT - tests/SOCIAL - - tests/SOURCE_DISTRIBUTION - - - tests/STATIC_ANALYSIS_REPORT - tests/SUPPORT - - tests/THREAT_MODEL - tests/SCM - - tests/VULNERABILITY_ASSERTION - tests/WEBSITE diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.3.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.3.json.bin index 3c722e075..072c5deec 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.3.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.3.json.bin @@ -1,20 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "externalReferences": [ - { - "type": "other", - "url": "tests/ADVERSARY_MODEL" - }, { "type": "advisories", "url": "tests/ADVISORIES" }, - { - "type": "other", - "url": "tests/ATTESTATION" - }, { "type": "bom", "url": "tests/BOM" @@ -27,66 +27,18 @@ "type": "build-system", "url": "tests/BUILD_SYSTEM" }, - { - "type": "other", - "url": "tests/CERTIFICATION_REPORT" - }, { "type": "chat", "url": "tests/CHAT" }, - { - "type": "other", - "url": "tests/CITATION" - }, - { - "type": "other", - "url": "tests/CODIFIED_INFRASTRUCTURE" - }, - { - "type": "other", - "url": "tests/COMPONENT_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/CONFIGURATION" - }, - { - "type": "other", - "url": "tests/DIGITAL_SIGNATURE" - }, { "type": "distribution", "url": "tests/DISTRIBUTION" }, - { - "type": "other", - "url": "tests/DISTRIBUTION_INTAKE" - }, { "type": "documentation", "url": "tests/DOCUMENTATION" }, - { - "type": "other", - "url": "tests/DYNAMIC_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/ELECTRONIC_SIGNATURE" - }, - { - "type": "other", - "url": "tests/EVIDENCE" - }, - { - "type": "other", - "url": "tests/EXPLOITABILITY_STATEMENT" - }, - { - "type": "other", - "url": "tests/FORMULATION" - }, { "type": "issue-tracker", "url": "tests/ISSUE_TRACKER" @@ -95,106 +47,31 @@ "type": "license", "url": "tests/LICENSE" }, - { - "type": "other", - "url": "tests/LOG" - }, { "type": "mailing-list", "url": "tests/MAILING_LIST" }, - { - "type": "other", - "url": "tests/MATURITY_REPORT" - }, - { - "type": "other", - "url": "tests/MODEL_CARD" - }, { "type": "other", "url": "tests/OTHER" }, - { - "type": "other", - "url": "tests/PATENT" - }, - { - "type": "other", - "url": "tests/PATENT_ASSERTION" - }, - { - "type": "other", - "url": "tests/PATENT_FAMILY" - }, - { - "type": "other", - "url": "tests/PENTEST_REPORT" - }, - { - "type": "other", - "url": "tests/POAM" - }, - { - "type": "other", - "url": "tests/QUALITY_METRICS" - }, - { - "type": "other", - "url": "tests/RELEASE_NOTES" - }, - { - "type": "other", - "url": "tests/RFC_9166" - }, - { - "type": "other", - "url": "tests/RISK_ASSESSMENT" - }, - { - "type": "other", - "url": "tests/RUNTIME_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/SECURITY_CONTACT" - }, { "type": "social", "url": "tests/SOCIAL" }, - { - "type": "other", - "url": "tests/SOURCE_DISTRIBUTION" - }, - { - "type": "other", - "url": "tests/STATIC_ANALYSIS_REPORT" - }, { "type": "support", "url": "tests/SUPPORT" }, - { - "type": "other", - "url": "tests/THREAT_MODEL" - }, { "type": "vcs", "url": "tests/SCM" }, - { - "type": "other", - "url": "tests/VULNERABILITY_ASSERTION" - }, { "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -202,11 +79,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.3.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.3.xml.bin index 34d645a90..d1efb8e1a 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -8,15 +8,9 @@ dummy - - tests/ADVERSARY_MODEL - tests/ADVISORIES - - tests/ATTESTATION - tests/BOM @@ -26,126 +20,36 @@ tests/BUILD_SYSTEM - - tests/CERTIFICATION_REPORT - tests/CHAT - - tests/CITATION - - - tests/CODIFIED_INFRASTRUCTURE - - - tests/COMPONENT_ANALYSIS_REPORT - - - tests/CONFIGURATION - - - tests/DIGITAL_SIGNATURE - tests/DISTRIBUTION - - tests/DISTRIBUTION_INTAKE - tests/DOCUMENTATION - - tests/DYNAMIC_ANALYSIS_REPORT - - - tests/ELECTRONIC_SIGNATURE - - - tests/EVIDENCE - - - tests/EXPLOITABILITY_STATEMENT - - - tests/FORMULATION - tests/ISSUE_TRACKER tests/LICENSE - - tests/LOG - tests/MAILING_LIST - - tests/MATURITY_REPORT - - - tests/MODEL_CARD - tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - - - tests/PENTEST_REPORT - - - tests/POAM - - - tests/QUALITY_METRICS - - - tests/RELEASE_NOTES - - - tests/RFC_9166 - - - tests/RISK_ASSESSMENT - - - tests/RUNTIME_ANALYSIS_REPORT - - - tests/SECURITY_CONTACT - tests/SOCIAL - - tests/SOURCE_DISTRIBUTION - - - tests/STATIC_ANALYSIS_REPORT - tests/SUPPORT - - tests/THREAT_MODEL - tests/SCM - - tests/VULNERABILITY_ASSERTION - tests/WEBSITE diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.4.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.4.json.bin index bc4bb7857..19f652e1f 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.4.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.4.json.bin @@ -1,20 +1,19 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ - { - "type": "other", - "url": "tests/ADVERSARY_MODEL" - }, { "type": "advisories", "url": "tests/ADVISORIES" }, - { - "type": "other", - "url": "tests/ATTESTATION" - }, { "type": "bom", "url": "tests/BOM" @@ -27,66 +26,18 @@ "type": "build-system", "url": "tests/BUILD_SYSTEM" }, - { - "type": "other", - "url": "tests/CERTIFICATION_REPORT" - }, { "type": "chat", "url": "tests/CHAT" }, - { - "type": "other", - "url": "tests/CITATION" - }, - { - "type": "other", - "url": "tests/CODIFIED_INFRASTRUCTURE" - }, - { - "type": "other", - "url": "tests/COMPONENT_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/CONFIGURATION" - }, - { - "type": "other", - "url": "tests/DIGITAL_SIGNATURE" - }, { "type": "distribution", "url": "tests/DISTRIBUTION" }, - { - "type": "other", - "url": "tests/DISTRIBUTION_INTAKE" - }, { "type": "documentation", "url": "tests/DOCUMENTATION" }, - { - "type": "other", - "url": "tests/DYNAMIC_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/ELECTRONIC_SIGNATURE" - }, - { - "type": "other", - "url": "tests/EVIDENCE" - }, - { - "type": "other", - "url": "tests/EXPLOITABILITY_STATEMENT" - }, - { - "type": "other", - "url": "tests/FORMULATION" - }, { "type": "issue-tracker", "url": "tests/ISSUE_TRACKER" @@ -95,105 +46,35 @@ "type": "license", "url": "tests/LICENSE" }, - { - "type": "other", - "url": "tests/LOG" - }, { "type": "mailing-list", "url": "tests/MAILING_LIST" }, - { - "type": "other", - "url": "tests/MATURITY_REPORT" - }, - { - "type": "other", - "url": "tests/MODEL_CARD" - }, { "type": "other", "url": "tests/OTHER" }, - { - "type": "other", - "url": "tests/PATENT" - }, - { - "type": "other", - "url": "tests/PATENT_ASSERTION" - }, - { - "type": "other", - "url": "tests/PATENT_FAMILY" - }, - { - "type": "other", - "url": "tests/PENTEST_REPORT" - }, - { - "type": "other", - "url": "tests/POAM" - }, - { - "type": "other", - "url": "tests/QUALITY_METRICS" - }, { "type": "release-notes", "url": "tests/RELEASE_NOTES" }, - { - "type": "other", - "url": "tests/RFC_9166" - }, - { - "type": "other", - "url": "tests/RISK_ASSESSMENT" - }, - { - "type": "other", - "url": "tests/RUNTIME_ANALYSIS_REPORT" - }, - { - "type": "other", - "url": "tests/SECURITY_CONTACT" - }, { "type": "social", "url": "tests/SOCIAL" }, - { - "type": "other", - "url": "tests/SOURCE_DISTRIBUTION" - }, - { - "type": "other", - "url": "tests/STATIC_ANALYSIS_REPORT" - }, { "type": "support", "url": "tests/SUPPORT" }, - { - "type": "other", - "url": "tests/THREAT_MODEL" - }, { "type": "vcs", "url": "tests/SCM" }, - { - "type": "other", - "url": "tests/VULNERABILITY_ASSERTION" - }, { "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -201,11 +82,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.4.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.4.xml.bin index 92169a2f6..e0181162f 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -7,15 +7,9 @@ dummy - - tests/ADVERSARY_MODEL - tests/ADVISORIES - - tests/ATTESTATION - tests/BOM @@ -25,126 +19,39 @@ tests/BUILD_SYSTEM - - tests/CERTIFICATION_REPORT - tests/CHAT - - tests/CITATION - - - tests/CODIFIED_INFRASTRUCTURE - - - tests/COMPONENT_ANALYSIS_REPORT - - - tests/CONFIGURATION - - - tests/DIGITAL_SIGNATURE - tests/DISTRIBUTION - - tests/DISTRIBUTION_INTAKE - tests/DOCUMENTATION - - tests/DYNAMIC_ANALYSIS_REPORT - - - tests/ELECTRONIC_SIGNATURE - - - tests/EVIDENCE - - - tests/EXPLOITABILITY_STATEMENT - - - tests/FORMULATION - tests/ISSUE_TRACKER tests/LICENSE - - tests/LOG - tests/MAILING_LIST - - tests/MATURITY_REPORT - - - tests/MODEL_CARD - tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - - - tests/PENTEST_REPORT - - - tests/POAM - - - tests/QUALITY_METRICS - tests/RELEASE_NOTES - - tests/RFC_9166 - - - tests/RISK_ASSESSMENT - - - tests/RUNTIME_ANALYSIS_REPORT - - - tests/SECURITY_CONTACT - tests/SOCIAL - - tests/SOURCE_DISTRIBUTION - - - tests/STATIC_ANALYSIS_REPORT - tests/SUPPORT - - tests/THREAT_MODEL - tests/SCM - - tests/VULNERABILITY_ASSERTION - tests/WEBSITE diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.5.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.5.json.bin index 451384363..d2b88b3f5 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.5.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.5.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { @@ -35,10 +42,6 @@ "type": "chat", "url": "tests/CHAT" }, - { - "type": "other", - "url": "tests/CITATION" - }, { "type": "codified-infrastructure", "url": "tests/CODIFIED_INFRASTRUCTURE" @@ -51,10 +54,6 @@ "type": "configuration", "url": "tests/CONFIGURATION" }, - { - "type": "other", - "url": "tests/DIGITAL_SIGNATURE" - }, { "type": "distribution", "url": "tests/DISTRIBUTION" @@ -71,10 +70,6 @@ "type": "dynamic-analysis-report", "url": "tests/DYNAMIC_ANALYSIS_REPORT" }, - { - "type": "other", - "url": "tests/ELECTRONIC_SIGNATURE" - }, { "type": "evidence", "url": "tests/EVIDENCE" @@ -115,18 +110,6 @@ "type": "other", "url": "tests/OTHER" }, - { - "type": "other", - "url": "tests/PATENT" - }, - { - "type": "other", - "url": "tests/PATENT_ASSERTION" - }, - { - "type": "other", - "url": "tests/PATENT_FAMILY" - }, { "type": "pentest-report", "url": "tests/PENTEST_REPORT" @@ -143,10 +126,6 @@ "type": "release-notes", "url": "tests/RELEASE_NOTES" }, - { - "type": "other", - "url": "tests/RFC_9166" - }, { "type": "risk-assessment", "url": "tests/RISK_ASSESSMENT" @@ -163,10 +142,6 @@ "type": "social", "url": "tests/SOCIAL" }, - { - "type": "other", - "url": "tests/SOURCE_DISTRIBUTION" - }, { "type": "static-analysis-report", "url": "tests/STATIC_ANALYSIS_REPORT" @@ -191,9 +166,7 @@ "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -201,9 +174,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -214,8 +184,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.5.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.5.xml.bin index b7f3bd447..d5ab5f5b4 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -31,9 +31,6 @@ tests/CHAT - - tests/CITATION - tests/CODIFIED_INFRASTRUCTURE @@ -43,9 +40,6 @@ tests/CONFIGURATION - - tests/DIGITAL_SIGNATURE - tests/DISTRIBUTION @@ -58,9 +52,6 @@ tests/DYNAMIC_ANALYSIS_REPORT - - tests/ELECTRONIC_SIGNATURE - tests/EVIDENCE @@ -91,15 +82,6 @@ tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - tests/PENTEST_REPORT @@ -112,9 +94,6 @@ tests/RELEASE_NOTES - - tests/RFC_9166 - tests/RISK_ASSESSMENT @@ -127,9 +106,6 @@ tests/SOCIAL - - tests/SOURCE_DISTRIBUTION - tests/STATIC_ANALYSIS_REPORT diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.6.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.6.json.bin index f927ff82b..3ef6e23b5 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.6.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.6.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { @@ -35,10 +42,6 @@ "type": "chat", "url": "tests/CHAT" }, - { - "type": "other", - "url": "tests/CITATION" - }, { "type": "codified-infrastructure", "url": "tests/CODIFIED_INFRASTRUCTURE" @@ -115,18 +118,6 @@ "type": "other", "url": "tests/OTHER" }, - { - "type": "other", - "url": "tests/PATENT" - }, - { - "type": "other", - "url": "tests/PATENT_ASSERTION" - }, - { - "type": "other", - "url": "tests/PATENT_FAMILY" - }, { "type": "pentest-report", "url": "tests/PENTEST_REPORT" @@ -191,9 +182,7 @@ "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -201,9 +190,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -214,8 +200,6 @@ "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" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.6.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.6.xml.bin index 53080af7e..1d0f4eeac 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -31,9 +31,6 @@ tests/CHAT - - tests/CITATION - tests/CODIFIED_INFRASTRUCTURE @@ -91,15 +88,6 @@ tests/OTHER - - tests/PATENT - - - tests/PATENT_ASSERTION - - - tests/PATENT_FAMILY - tests/PENTEST_REPORT diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.7.json.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.7.json.bin index 9fcd274e9..0918a4526 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.7.json.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.7.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { @@ -191,9 +198,7 @@ "type": "website", "url": "tests/WEBSITE" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -201,9 +206,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -214,8 +216,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_ExternalReferenceType-1.7.xml.bin b/tests/_data/snapshots/enum_ExternalReferenceType-1.7.xml.bin index d053c269f..a75d4502c 100644 --- a/tests/_data/snapshots/enum_ExternalReferenceType-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ExternalReferenceType-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.1.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.1.xml.bin index 333a33805..933abf3e9 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.1.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.1.xml.bin @@ -1,5 +1,5 @@ - + dummy @@ -13,6 +13,7 @@ ae2b1fca515949e5d54fb22b8ed95575 ae2b1fca515949e5d54fb22b8ed95575 + false diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.2.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.2.json.bin index feac89ff1..3682a0a1a 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.2.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.2.json.bin @@ -1,7 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "hashes": [ { "alg": "BLAKE2b-256", @@ -51,10 +59,7 @@ "alg": "SHA3-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -62,11 +67,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.2.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.2.xml.bin index 03ea03021..0c6509a4e 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.2.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.3.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.3.json.bin index b9fea7a86..1741f3665 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.3.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.3.json.bin @@ -1,7 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "hashes": [ { "alg": "BLAKE2b-256", @@ -51,10 +59,7 @@ "alg": "SHA3-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -62,11 +67,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.3.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.3.xml.bin index 420b91c8d..2e2a161fe 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.3.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.4.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.4.json.bin index 46381c547..5235c2f84 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.4.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.4.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "hashes": [ { @@ -51,9 +58,7 @@ "alg": "SHA3-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -61,11 +66,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.4.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.4.xml.bin index 8c8a6e3b0..b35a826a3 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.4.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.5.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.5.json.bin index 979aec046..d97cfe943 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.5.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.5.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "hashes": [ { @@ -51,9 +58,7 @@ "alg": "SHA3-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -61,9 +66,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -74,8 +76,6 @@ "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" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.5.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.5.xml.bin index 3c3cd2658..88d42a3a0 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.5.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.6.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.6.json.bin index fa982e91c..8054eebb0 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.6.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.6.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "hashes": [ { @@ -51,9 +58,7 @@ "alg": "SHA3-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -61,9 +66,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -74,8 +76,6 @@ "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" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.6.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.6.xml.bin index e50c50490..9cadede8a 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.6.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.7.json.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.7.json.bin index 2854cf0ac..7af660fe9 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.7.json.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.7.json.bin @@ -1,6 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "hashes": [ { @@ -59,9 +66,7 @@ "alg": "Streebog-512", "content": "ae2b1fca515949e5d54fb22b8ed95575" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -69,9 +74,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -82,8 +84,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_HashAlgorithm-1.7.xml.bin b/tests/_data/snapshots/enum_HashAlgorithm-1.7.xml.bin index e9e1c49cd..1a690e669 100644 --- a/tests/_data/snapshots/enum_HashAlgorithm-1.7.xml.bin +++ b/tests/_data/snapshots/enum_HashAlgorithm-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.1.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.json.bin index 15ee9ab58..acb53350a 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.json.bin @@ -1,32 +1,32 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "affects": [ { "ref": "urn:cdx:bom23/1#comp42", "versions": [ { - "status": "affected", - "version": "1.33.7+AFFECTED" + "version": "1.33.7+AFFECTED", + "status": "affected" }, { - "status": "unaffected", - "version": "1.33.7+UNAFFECTED" + "version": "1.33.7+UNAFFECTED", + "status": "unaffected" }, { - "status": "unknown", - "version": "1.33.7+UNKNOWN" + "version": "1.33.7+UNKNOWN", + "status": "unknown" } ] } - ], - "bom-ref": "dummy", - "id": "dummy" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.xml.bin index 4468db618..19071db75 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.json.bin index 12f0d76bf..c54f07af1 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,31 +14,29 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "affects": [ { "ref": "urn:cdx:bom23/1#comp42", "versions": [ { - "status": "affected", - "version": "1.33.7+AFFECTED" + "version": "1.33.7+AFFECTED", + "status": "affected" }, { - "status": "unaffected", - "version": "1.33.7+UNAFFECTED" + "version": "1.33.7+UNAFFECTED", + "status": "unaffected" }, { - "status": "unknown", - "version": "1.33.7+UNKNOWN" + "version": "1.33.7+UNKNOWN", + "status": "unknown" } ] } - ], - "bom-ref": "dummy", - "id": "dummy" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.xml.bin index 6a2713477..478e04b81 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.json.bin index 6f041fda1..784714fa0 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,31 +14,29 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "affects": [ { "ref": "urn:cdx:bom23/1#comp42", "versions": [ { - "status": "affected", - "version": "1.33.7+AFFECTED" + "version": "1.33.7+AFFECTED", + "status": "affected" }, { - "status": "unaffected", - "version": "1.33.7+UNAFFECTED" + "version": "1.33.7+UNAFFECTED", + "status": "unaffected" }, { - "status": "unknown", - "version": "1.33.7+UNKNOWN" + "version": "1.33.7+UNKNOWN", + "status": "unknown" } ] } - ], - "bom-ref": "dummy", - "id": "dummy" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.xml.bin index f963edd38..9fcbc8df9 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.json.bin index b3e26d7f0..d4abd446b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,31 +14,29 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "affects": [ { "ref": "urn:cdx:bom23/1#comp42", "versions": [ { - "status": "affected", - "version": "1.33.7+AFFECTED" + "version": "1.33.7+AFFECTED", + "status": "affected" }, { - "status": "unaffected", - "version": "1.33.7+UNAFFECTED" + "version": "1.33.7+UNAFFECTED", + "status": "unaffected" }, { - "status": "unknown", - "version": "1.33.7+UNKNOWN" + "version": "1.33.7+UNKNOWN", + "status": "unknown" } ] } - ], - "bom-ref": "dummy", - "id": "dummy" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.xml.bin index a9cdc5231..1304f8618 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisAffectedStatus-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.1.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.json.bin index 26c7fb756..583f6752f 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.json.bin @@ -1,72 +1,72 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-with-CODE_NOT_PRESENT", + "id": "vuln-with-CODE_NOT_PRESENT", "analysis": { "justification": "code_not_present" - }, - "bom-ref": "vuln-with-CODE_NOT_PRESENT", - "id": "vuln-with-CODE_NOT_PRESENT" + } }, { + "bom-ref": "vuln-with-CODE_NOT_REACHABLE", + "id": "vuln-with-CODE_NOT_REACHABLE", "analysis": { "justification": "code_not_reachable" - }, - "bom-ref": "vuln-with-CODE_NOT_REACHABLE", - "id": "vuln-with-CODE_NOT_REACHABLE" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", + "id": "vuln-with-PROTECTED_AT_PERIMITER", "analysis": { "justification": "protected_at_perimeter" - }, - "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", - "id": "vuln-with-PROTECTED_AT_PERIMITER" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", + "id": "vuln-with-PROTECTED_AT_RUNTIME", "analysis": { "justification": "protected_at_runtime" - }, - "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", - "id": "vuln-with-PROTECTED_AT_RUNTIME" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", + "id": "vuln-with-PROTECTED_BY_COMPILER", "analysis": { "justification": "protected_by_compiler" - }, - "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", - "id": "vuln-with-PROTECTED_BY_COMPILER" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", + "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", "analysis": { "justification": "protected_by_mitigating_control" - }, - "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", - "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL" + } }, { + "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", + "id": "vuln-with-REQUIRES_CONFIGURATION", "analysis": { "justification": "requires_configuration" - }, - "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", - "id": "vuln-with-REQUIRES_CONFIGURATION" + } }, { + "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", + "id": "vuln-with-REQUIRES_DEPENDENCY", "analysis": { "justification": "requires_dependency" - }, - "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", - "id": "vuln-with-REQUIRES_DEPENDENCY" + } }, { + "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", + "id": "vuln-with-REQUIRES_ENVIRONMENT", "analysis": { "justification": "requires_environment" - }, - "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", - "id": "vuln-with-REQUIRES_ENVIRONMENT" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.xml.bin index a761fe009..5a25c3057 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.json.bin index 45504f64c..53fb763a1 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,71 +14,69 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-with-CODE_NOT_PRESENT", + "id": "vuln-with-CODE_NOT_PRESENT", "analysis": { "justification": "code_not_present" - }, - "bom-ref": "vuln-with-CODE_NOT_PRESENT", - "id": "vuln-with-CODE_NOT_PRESENT" + } }, { + "bom-ref": "vuln-with-CODE_NOT_REACHABLE", + "id": "vuln-with-CODE_NOT_REACHABLE", "analysis": { "justification": "code_not_reachable" - }, - "bom-ref": "vuln-with-CODE_NOT_REACHABLE", - "id": "vuln-with-CODE_NOT_REACHABLE" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", + "id": "vuln-with-PROTECTED_AT_PERIMITER", "analysis": { "justification": "protected_at_perimeter" - }, - "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", - "id": "vuln-with-PROTECTED_AT_PERIMITER" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", + "id": "vuln-with-PROTECTED_AT_RUNTIME", "analysis": { "justification": "protected_at_runtime" - }, - "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", - "id": "vuln-with-PROTECTED_AT_RUNTIME" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", + "id": "vuln-with-PROTECTED_BY_COMPILER", "analysis": { "justification": "protected_by_compiler" - }, - "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", - "id": "vuln-with-PROTECTED_BY_COMPILER" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", + "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", "analysis": { "justification": "protected_by_mitigating_control" - }, - "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", - "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL" + } }, { + "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", + "id": "vuln-with-REQUIRES_CONFIGURATION", "analysis": { "justification": "requires_configuration" - }, - "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", - "id": "vuln-with-REQUIRES_CONFIGURATION" + } }, { + "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", + "id": "vuln-with-REQUIRES_DEPENDENCY", "analysis": { "justification": "requires_dependency" - }, - "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", - "id": "vuln-with-REQUIRES_DEPENDENCY" + } }, { + "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", + "id": "vuln-with-REQUIRES_ENVIRONMENT", "analysis": { "justification": "requires_environment" - }, - "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", - "id": "vuln-with-REQUIRES_ENVIRONMENT" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.xml.bin index 562ce1a83..a5b0a96fa 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.json.bin index 8aac74182..6fab07743 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,71 +14,69 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-with-CODE_NOT_PRESENT", + "id": "vuln-with-CODE_NOT_PRESENT", "analysis": { "justification": "code_not_present" - }, - "bom-ref": "vuln-with-CODE_NOT_PRESENT", - "id": "vuln-with-CODE_NOT_PRESENT" + } }, { + "bom-ref": "vuln-with-CODE_NOT_REACHABLE", + "id": "vuln-with-CODE_NOT_REACHABLE", "analysis": { "justification": "code_not_reachable" - }, - "bom-ref": "vuln-with-CODE_NOT_REACHABLE", - "id": "vuln-with-CODE_NOT_REACHABLE" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", + "id": "vuln-with-PROTECTED_AT_PERIMITER", "analysis": { "justification": "protected_at_perimeter" - }, - "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", - "id": "vuln-with-PROTECTED_AT_PERIMITER" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", + "id": "vuln-with-PROTECTED_AT_RUNTIME", "analysis": { "justification": "protected_at_runtime" - }, - "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", - "id": "vuln-with-PROTECTED_AT_RUNTIME" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", + "id": "vuln-with-PROTECTED_BY_COMPILER", "analysis": { "justification": "protected_by_compiler" - }, - "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", - "id": "vuln-with-PROTECTED_BY_COMPILER" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", + "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", "analysis": { "justification": "protected_by_mitigating_control" - }, - "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", - "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL" + } }, { + "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", + "id": "vuln-with-REQUIRES_CONFIGURATION", "analysis": { "justification": "requires_configuration" - }, - "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", - "id": "vuln-with-REQUIRES_CONFIGURATION" + } }, { + "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", + "id": "vuln-with-REQUIRES_DEPENDENCY", "analysis": { "justification": "requires_dependency" - }, - "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", - "id": "vuln-with-REQUIRES_DEPENDENCY" + } }, { + "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", + "id": "vuln-with-REQUIRES_ENVIRONMENT", "analysis": { "justification": "requires_environment" - }, - "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", - "id": "vuln-with-REQUIRES_ENVIRONMENT" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.xml.bin index 2ef1f3b40..3a7cf221b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.json.bin index 982c675e1..19fd4b86b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,71 +14,69 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-with-CODE_NOT_PRESENT", + "id": "vuln-with-CODE_NOT_PRESENT", "analysis": { "justification": "code_not_present" - }, - "bom-ref": "vuln-with-CODE_NOT_PRESENT", - "id": "vuln-with-CODE_NOT_PRESENT" + } }, { + "bom-ref": "vuln-with-CODE_NOT_REACHABLE", + "id": "vuln-with-CODE_NOT_REACHABLE", "analysis": { "justification": "code_not_reachable" - }, - "bom-ref": "vuln-with-CODE_NOT_REACHABLE", - "id": "vuln-with-CODE_NOT_REACHABLE" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", + "id": "vuln-with-PROTECTED_AT_PERIMITER", "analysis": { "justification": "protected_at_perimeter" - }, - "bom-ref": "vuln-with-PROTECTED_AT_PERIMITER", - "id": "vuln-with-PROTECTED_AT_PERIMITER" + } }, { + "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", + "id": "vuln-with-PROTECTED_AT_RUNTIME", "analysis": { "justification": "protected_at_runtime" - }, - "bom-ref": "vuln-with-PROTECTED_AT_RUNTIME", - "id": "vuln-with-PROTECTED_AT_RUNTIME" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", + "id": "vuln-with-PROTECTED_BY_COMPILER", "analysis": { "justification": "protected_by_compiler" - }, - "bom-ref": "vuln-with-PROTECTED_BY_COMPILER", - "id": "vuln-with-PROTECTED_BY_COMPILER" + } }, { + "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", + "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", "analysis": { "justification": "protected_by_mitigating_control" - }, - "bom-ref": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL", - "id": "vuln-with-PROTECTED_BY_MITIGATING_CONTROL" + } }, { + "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", + "id": "vuln-with-REQUIRES_CONFIGURATION", "analysis": { "justification": "requires_configuration" - }, - "bom-ref": "vuln-with-REQUIRES_CONFIGURATION", - "id": "vuln-with-REQUIRES_CONFIGURATION" + } }, { + "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", + "id": "vuln-with-REQUIRES_DEPENDENCY", "analysis": { "justification": "requires_dependency" - }, - "bom-ref": "vuln-with-REQUIRES_DEPENDENCY", - "id": "vuln-with-REQUIRES_DEPENDENCY" + } }, { + "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", + "id": "vuln-with-REQUIRES_ENVIRONMENT", "analysis": { "justification": "requires_environment" - }, - "bom-ref": "vuln-with-REQUIRES_ENVIRONMENT", - "id": "vuln-with-REQUIRES_ENVIRONMENT" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.xml.bin index 4488ae221..bf74bf3ad 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisJustification-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.1.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.json.bin index ebc02088f..4353c50fe 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.json.bin @@ -1,11 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "analysis": { "response": [ "can_not_fix", @@ -14,9 +16,7 @@ "will_not_fix", "workaround_available" ] - }, - "bom-ref": "dummy", - "id": "dummy" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.xml.bin index fecbfd539..2808491e3 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.json.bin index d931b3bee..c6c7723ca 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,10 +14,10 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "analysis": { "response": [ "can_not_fix", @@ -24,9 +26,7 @@ "will_not_fix", "workaround_available" ] - }, - "bom-ref": "dummy", - "id": "dummy" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.xml.bin index b1e639faa..804e610b0 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.json.bin index 0ebcf7bcc..8462c5f46 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,10 +14,10 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "analysis": { "response": [ "can_not_fix", @@ -24,9 +26,7 @@ "will_not_fix", "workaround_available" ] - }, - "bom-ref": "dummy", - "id": "dummy" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.xml.bin index 194e1fa2b..724973c25 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.json.bin index c17b463f8..4910c3fd0 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,10 +14,10 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "dummy", + "id": "dummy", "analysis": { "response": [ "can_not_fix", @@ -24,9 +26,7 @@ "will_not_fix", "workaround_available" ] - }, - "bom-ref": "dummy", - "id": "dummy" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.xml.bin index 03c49530c..6ab46d95f 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisResponse-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.1.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.1.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.json.bin index 56acc0b39..00e81608a 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.json.bin @@ -1,51 +1,51 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-wit-state-EXPLOITABLE", + "id": "vuln-wit-state-EXPLOITABLE", "analysis": { "state": "exploitable" - }, - "bom-ref": "vuln-wit-state-EXPLOITABLE", - "id": "vuln-wit-state-EXPLOITABLE" + } }, { + "bom-ref": "vuln-wit-state-FALSE_POSITIVE", + "id": "vuln-wit-state-FALSE_POSITIVE", "analysis": { "state": "false_positive" - }, - "bom-ref": "vuln-wit-state-FALSE_POSITIVE", - "id": "vuln-wit-state-FALSE_POSITIVE" + } }, { + "bom-ref": "vuln-wit-state-IN_TRIAGE", + "id": "vuln-wit-state-IN_TRIAGE", "analysis": { "state": "in_triage" - }, - "bom-ref": "vuln-wit-state-IN_TRIAGE", - "id": "vuln-wit-state-IN_TRIAGE" + } }, { + "bom-ref": "vuln-wit-state-NOT_AFFECTED", + "id": "vuln-wit-state-NOT_AFFECTED", "analysis": { "state": "not_affected" - }, - "bom-ref": "vuln-wit-state-NOT_AFFECTED", - "id": "vuln-wit-state-NOT_AFFECTED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED", + "id": "vuln-wit-state-RESOLVED", "analysis": { "state": "resolved" - }, - "bom-ref": "vuln-wit-state-RESOLVED", - "id": "vuln-wit-state-RESOLVED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", + "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", "analysis": { "state": "resolved_with_pedigree" - }, - "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", - "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.xml.bin index 9342e9743..f4db3bc90 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.json.bin index 33171e55e..17421ec9c 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,50 +14,48 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-wit-state-EXPLOITABLE", + "id": "vuln-wit-state-EXPLOITABLE", "analysis": { "state": "exploitable" - }, - "bom-ref": "vuln-wit-state-EXPLOITABLE", - "id": "vuln-wit-state-EXPLOITABLE" + } }, { + "bom-ref": "vuln-wit-state-FALSE_POSITIVE", + "id": "vuln-wit-state-FALSE_POSITIVE", "analysis": { "state": "false_positive" - }, - "bom-ref": "vuln-wit-state-FALSE_POSITIVE", - "id": "vuln-wit-state-FALSE_POSITIVE" + } }, { + "bom-ref": "vuln-wit-state-IN_TRIAGE", + "id": "vuln-wit-state-IN_TRIAGE", "analysis": { "state": "in_triage" - }, - "bom-ref": "vuln-wit-state-IN_TRIAGE", - "id": "vuln-wit-state-IN_TRIAGE" + } }, { + "bom-ref": "vuln-wit-state-NOT_AFFECTED", + "id": "vuln-wit-state-NOT_AFFECTED", "analysis": { "state": "not_affected" - }, - "bom-ref": "vuln-wit-state-NOT_AFFECTED", - "id": "vuln-wit-state-NOT_AFFECTED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED", + "id": "vuln-wit-state-RESOLVED", "analysis": { "state": "resolved" - }, - "bom-ref": "vuln-wit-state-RESOLVED", - "id": "vuln-wit-state-RESOLVED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", + "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", "analysis": { "state": "resolved_with_pedigree" - }, - "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", - "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.xml.bin index 8577d31fc..c98777b90 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.json.bin index b1ee30d71..cbec64865 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,50 +14,48 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-wit-state-EXPLOITABLE", + "id": "vuln-wit-state-EXPLOITABLE", "analysis": { "state": "exploitable" - }, - "bom-ref": "vuln-wit-state-EXPLOITABLE", - "id": "vuln-wit-state-EXPLOITABLE" + } }, { + "bom-ref": "vuln-wit-state-FALSE_POSITIVE", + "id": "vuln-wit-state-FALSE_POSITIVE", "analysis": { "state": "false_positive" - }, - "bom-ref": "vuln-wit-state-FALSE_POSITIVE", - "id": "vuln-wit-state-FALSE_POSITIVE" + } }, { + "bom-ref": "vuln-wit-state-IN_TRIAGE", + "id": "vuln-wit-state-IN_TRIAGE", "analysis": { "state": "in_triage" - }, - "bom-ref": "vuln-wit-state-IN_TRIAGE", - "id": "vuln-wit-state-IN_TRIAGE" + } }, { + "bom-ref": "vuln-wit-state-NOT_AFFECTED", + "id": "vuln-wit-state-NOT_AFFECTED", "analysis": { "state": "not_affected" - }, - "bom-ref": "vuln-wit-state-NOT_AFFECTED", - "id": "vuln-wit-state-NOT_AFFECTED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED", + "id": "vuln-wit-state-RESOLVED", "analysis": { "state": "resolved" - }, - "bom-ref": "vuln-wit-state-RESOLVED", - "id": "vuln-wit-state-RESOLVED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", + "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", "analysis": { "state": "resolved_with_pedigree" - }, - "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", - "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.xml.bin index 1800c469d..649c07439 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.json.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.json.bin index d7589c2ec..d1a63a336 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.json.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,50 +14,48 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { + "bom-ref": "vuln-wit-state-EXPLOITABLE", + "id": "vuln-wit-state-EXPLOITABLE", "analysis": { "state": "exploitable" - }, - "bom-ref": "vuln-wit-state-EXPLOITABLE", - "id": "vuln-wit-state-EXPLOITABLE" + } }, { + "bom-ref": "vuln-wit-state-FALSE_POSITIVE", + "id": "vuln-wit-state-FALSE_POSITIVE", "analysis": { "state": "false_positive" - }, - "bom-ref": "vuln-wit-state-FALSE_POSITIVE", - "id": "vuln-wit-state-FALSE_POSITIVE" + } }, { + "bom-ref": "vuln-wit-state-IN_TRIAGE", + "id": "vuln-wit-state-IN_TRIAGE", "analysis": { "state": "in_triage" - }, - "bom-ref": "vuln-wit-state-IN_TRIAGE", - "id": "vuln-wit-state-IN_TRIAGE" + } }, { + "bom-ref": "vuln-wit-state-NOT_AFFECTED", + "id": "vuln-wit-state-NOT_AFFECTED", "analysis": { "state": "not_affected" - }, - "bom-ref": "vuln-wit-state-NOT_AFFECTED", - "id": "vuln-wit-state-NOT_AFFECTED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED", + "id": "vuln-wit-state-RESOLVED", "analysis": { "state": "resolved" - }, - "bom-ref": "vuln-wit-state-RESOLVED", - "id": "vuln-wit-state-RESOLVED" + } }, { + "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", + "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", "analysis": { "state": "resolved_with_pedigree" - }, - "bom-ref": "vuln-wit-state-RESOLVED_WITH_PEDIGREE", - "id": "vuln-wit-state-RESOLVED_WITH_PEDIGREE" + } } ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", diff --git a/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.xml.bin b/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.xml.bin index aa6c24d31..d791c3bb4 100644 --- a/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.xml.bin +++ b/tests/_data/snapshots/enum_ImpactAnalysisState-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.1.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.1.xml.bin index 4eeb006ce..d4f193608 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.1.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.1.xml.bin @@ -1,10 +1,10 @@ - + dummy - + false diff --git a/tests/_data/snapshots/enum_IssueClassification-1.2.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.2.json.bin index 255c5dc10..458243804 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.2.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.2.json.bin @@ -1,31 +1,36 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", + "version": "", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library", - "version": "" + } } ], "dependencies": [ @@ -33,11 +38,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.2.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.2.xml.bin index 1ec44335a..b1d4b0b2e 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.2.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.3.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.3.json.bin index 3c869f0cf..ddaafe9c1 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.3.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.3.json.bin @@ -1,31 +1,36 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", + "version": "", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library", - "version": "" + } } ], "dependencies": [ @@ -33,11 +38,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.3.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.3.xml.bin index c232cf9a4..80f0ba7ac 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.3.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.4.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.4.json.bin index ee938e8f4..f894b6a43 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.4.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.4.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -32,11 +37,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.4.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.4.xml.bin index 1092bb0fc..3587888fa 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.4.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.5.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.5.json.bin index 72d132b02..b83447601 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.5.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.5.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -32,9 +37,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "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" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.5.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.5.xml.bin index 973446b4c..d688f366c 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.5.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.6.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.6.json.bin index 5065703c7..89201a436 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.6.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.6.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -32,9 +37,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "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" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.6.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.6.xml.bin index e32cecf57..49ce0c6eb 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.6.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_IssueClassification-1.7.json.bin b/tests/_data/snapshots/enum_IssueClassification-1.7.json.bin index 0259c6ba9..1b2605528 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.7.json.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.7.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { + "type": "backport", "resolves": [ { - "id": "issue-DEFECT", - "type": "defect" + "type": "defect", + "id": "issue-DEFECT" }, { - "id": "issue-ENHANCEMENT", - "type": "enhancement" + "type": "enhancement", + "id": "issue-ENHANCEMENT" }, { - "id": "issue-SECURITY", - "type": "security" + "type": "security", + "id": "issue-SECURITY" } - ], - "type": "backport" + ] } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -32,9 +37,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_IssueClassification-1.7.xml.bin b/tests/_data/snapshots/enum_IssueClassification-1.7.xml.bin index d7b8b274f..71552e7b5 100644 --- a/tests/_data/snapshots/enum_IssueClassification-1.7.xml.bin +++ b/tests/_data/snapshots/enum_IssueClassification-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.1.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.1.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.2.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.2.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.2.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.2.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.3.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.3.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.3.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.3.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.4.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.4.json.bin index 48f1745d1..39ff065e8 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.4.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.4.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.4.xml.bin index d0a7d4c90..013ff9521 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.4.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.5.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.5.json.bin index 438211b78..b86e9bf59 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.5.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.5.json.bin @@ -1,5 +1,8 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -22,8 +25,7 @@ { "phase": "pre-build" } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, "properties": [ { @@ -35,8 +37,6 @@ "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" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.5.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.5.xml.bin index a7b6f45c7..3e96fafef 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.5.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.6.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.6.json.bin index 4daf2f8f3..0aa3de5f7 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.6.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.6.json.bin @@ -1,5 +1,8 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -22,8 +25,7 @@ { "phase": "pre-build" } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, "properties": [ { @@ -35,8 +37,6 @@ "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" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.6.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.6.xml.bin index 514837b92..77d1f49e5 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.6.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.7.json.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.7.json.bin index 1307728e9..790463d48 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.7.json.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.7.json.bin @@ -1,5 +1,8 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -22,8 +25,7 @@ { "phase": "pre-build" } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, "properties": [ { @@ -35,8 +37,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_LifecyclePhase-1.7.xml.bin b/tests/_data/snapshots/enum_LifecyclePhase-1.7.xml.bin index e8bb572e3..26677c808 100644 --- a/tests/_data/snapshots/enum_LifecyclePhase-1.7.xml.bin +++ b/tests/_data/snapshots/enum_LifecyclePhase-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.1.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.1.xml.bin index 4eeb006ce..d4f193608 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.1.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.1.xml.bin @@ -1,10 +1,10 @@ - + dummy - + false diff --git a/tests/_data/snapshots/enum_PatchClassification-1.2.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.2.json.bin index 8df13dfc8..d98461776 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.2.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.2.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", + "version": "", "pedigree": { "patches": [ { @@ -18,9 +25,7 @@ "type": "unofficial" } ] - }, - "type": "library", - "version": "" + } } ], "dependencies": [ @@ -28,11 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.2.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.2.xml.bin index 7fb48ba97..c2da19aac 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.2.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.3.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.3.json.bin index bfc7ef492..16296fa94 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.3.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.3.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", + "version": "", "pedigree": { "patches": [ { @@ -18,9 +25,7 @@ "type": "unofficial" } ] - }, - "type": "library", - "version": "" + } } ], "dependencies": [ @@ -28,11 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.3.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.3.xml.bin index 4b3f595a0..e169601bf 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.3.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.4.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.4.json.bin index f451305b6..3fd9f6c3d 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.4.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.4.json.bin @@ -1,8 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { @@ -18,8 +24,7 @@ "type": "unofficial" } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -27,11 +32,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.4.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.4.xml.bin index 7777bf43e..40091e0a0 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.4.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.5.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.5.json.bin index 575e38a5f..70b92369c 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.5.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.5.json.bin @@ -1,8 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { @@ -18,8 +24,7 @@ "type": "unofficial" } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -27,9 +32,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -40,8 +42,6 @@ "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" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.5.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.5.xml.bin index 24d98f096..cf6556183 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.5.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.6.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.6.json.bin index 9db7f4cb4..171c2b1c7 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.6.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.6.json.bin @@ -1,8 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { @@ -18,8 +24,7 @@ "type": "unofficial" } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -27,9 +32,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -40,8 +42,6 @@ "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" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.6.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.6.xml.bin index dcd75a03b..f058de455 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.6.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_PatchClassification-1.7.json.bin b/tests/_data/snapshots/enum_PatchClassification-1.7.json.bin index 2db037a7d..f6eb74c2c 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.7.json.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.7.json.bin @@ -1,8 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy", "name": "dummy", + "type": "library", + "bom-ref": "dummy", "pedigree": { "patches": [ { @@ -18,8 +24,7 @@ "type": "unofficial" } ] - }, - "type": "library" + } } ], "dependencies": [ @@ -27,9 +32,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -40,8 +42,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_PatchClassification-1.7.xml.bin b/tests/_data/snapshots/enum_PatchClassification-1.7.xml.bin index 322f7fefa..3295b053e 100644 --- a/tests/_data/snapshots/enum_PatchClassification-1.7.xml.bin +++ b/tests/_data/snapshots/enum_PatchClassification-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.1.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.1.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_TlpClassification-1.2.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.2.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.2.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.2.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.3.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.3.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.3.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.3.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.4.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.4.json.bin index 48f1745d1..39ff065e8 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.4.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.4.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.4.xml.bin index d0a7d4c90..013ff9521 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.4.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.5.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.5.json.bin index 57b5e590e..7ee9568a7 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.5.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "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" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.5.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.5.xml.bin index f952637cf..9789b0d42 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.5.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.6.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.6.json.bin index b93790d4b..65c2c733c 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.6.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "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" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.6.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.6.xml.bin index 6faca474a..4fc136f23 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.6.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_TlpClassification-1.7.json.bin b/tests/_data/snapshots/enum_TlpClassification-1.7.json.bin index e5f7f9c2a..b5136ce74 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.7.json.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.7.json.bin @@ -1,9 +1,11 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "distributionConstraints": { "tlp": "CLEAR" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, "properties": [ { @@ -15,8 +17,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/enum_TlpClassification-1.7.xml.bin b/tests/_data/snapshots/enum_TlpClassification-1.7.xml.bin index 5f78c14aa..cbe384d61 100644 --- a/tests/_data/snapshots/enum_TlpClassification-1.7.xml.bin +++ b/tests/_data/snapshots/enum_TlpClassification-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.1.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.1.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.json.bin index caf42668c..9efc4da59 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", @@ -18,15 +18,9 @@ { "method": "CVSSv31" }, - { - "method": "other" - }, { "method": "OWASP" }, - { - "method": "other" - }, { "method": "other" } diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.xml.bin index 81c65a561..9f8023524 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 @@ -16,18 +16,12 @@ CVSSv31 - - other - OWASP other - - other - diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.json.bin index 2cebe4e2b..708fcabea 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.xml.bin index e8200fddf..11b389e46 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.json.bin index 8156593a6..92e194ec7 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.xml.bin index 568057a83..62b7cbcfc 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.json.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.json.bin index 19c5d3b6b..cf86507ba 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.xml.bin b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.xml.bin index 665c49ee1..7b30025fb 100644 --- a/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilityScoreSource-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.1.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.1.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.json.bin index bbf74ceb6..1b466820f 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.xml.bin index df515f777..3f54cf117 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.json.bin index d71a4f544..c43e92c6e 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.xml.bin index 674a90e88..03a7a7cd8 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.json.bin index 90731def2..9c1b6994b 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.xml.bin index 07848760f..4cef102ad 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.json.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.json.bin index a30277ee6..de030f508 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.json.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { "bom-ref": "dummy", diff --git a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.xml.bin b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.xml.bin index 5d34b880e..306e0c915 100644 --- a/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.xml.bin +++ b/tests/_data/snapshots/enum_VulnerabilitySeverity-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin index 6d4d9bdb1..b5e2e8a7b 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.1.xml.bin @@ -1,17 +1,20 @@ - + some-component + false some-library + false some-library + false diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin index fd8f32b50..c101bce09 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.json.bin @@ -1,37 +1,48 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp", + "version": "" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", "type": "library", + "bom-ref": "some-component", "version": "" }, { - "bom-ref": "some-library1", "name": "some-library", "type": "library", + "bom-ref": "some-library1", "version": "" }, { - "bom-ref": "some-library2", "name": "some-library", "type": "library", + "bom-ref": "some-library2", "version": "" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -40,17 +51,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin index 625bc1dc2..cde4d056c 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin index 601c5974f..f998fa503 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.json.bin @@ -1,37 +1,48 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp", + "version": "" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", "type": "library", + "bom-ref": "some-component", "version": "" }, { - "bom-ref": "some-library1", "name": "some-library", "type": "library", + "bom-ref": "some-library1", "version": "" }, { - "bom-ref": "some-library2", "name": "some-library", "type": "library", + "bom-ref": "some-library2", "version": "" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -40,17 +51,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin index 9ca84692e..d1d6921c6 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin index 1da355382..b4fe8c270 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.json.bin @@ -1,34 +1,44 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", - "type": "library" + "type": "library", + "bom-ref": "some-component" }, { - "bom-ref": "some-library1", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library1" }, { - "bom-ref": "some-library2", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library2" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -37,16 +47,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin index 22db0779f..c1e6e3512 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin index 64c0371b5..87cb5ed68 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.json.bin @@ -1,34 +1,44 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", - "type": "library" + "type": "library", + "bom-ref": "some-component" }, { - "bom-ref": "some-library1", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library1" }, { - "bom-ref": "some-library2", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library2" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -37,14 +47,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -55,8 +57,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin index 9146c15a4..8e853e7c3 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin index 0ce6b2c90..efeef9d98 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.json.bin @@ -1,34 +1,44 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", - "type": "library" + "type": "library", + "bom-ref": "some-component" }, { - "bom-ref": "some-library1", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library1" }, { - "bom-ref": "some-library2", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library2" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -37,14 +47,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -55,8 +57,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin index c64cf5366..cfd80d432 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.json.bin index 53966ad8d..47c3a8875 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.json.bin @@ -1,34 +1,44 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "myApp", + "type": "application", + "bom-ref": "myApp" + } + }, "components": [ { - "bom-ref": "some-component", "name": "some-component", - "type": "library" + "type": "library", + "bom-ref": "some-component" }, { - "bom-ref": "some-library1", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library1" }, { - "bom-ref": "some-library2", "name": "some-library", - "type": "library" + "type": "library", + "bom-ref": "some-library2" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "some-component" - ], - "ref": "myApp" + ] }, { + "ref": "some-component", "dependsOn": [ "some-library1", "some-library2" - ], - "ref": "some-component" + ] }, { "ref": "some-library1" @@ -37,14 +47,6 @@ "ref": "some-library2" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "name": "myApp", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -55,8 +57,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.xml.bin index ba05022e5..1b3dec441 100644 --- a/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue540_duplicate_components-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.1.xml.bin index 85289a746..9973d2f9f 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.1.xml.bin @@ -1,17 +1,20 @@ - + comp_a 1.0.0 + false comp_b 1.0.0 + false comp_c 1.0.0 + false diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.json.bin index ae67e6188..ed9bac38f 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.json.bin @@ -1,58 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.xml.bin index af1fa1389..50b3f14a2 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.json.bin index d37153a68..8eba19fc5 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.json.bin @@ -1,58 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.xml.bin index 14a099332..44641f599 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.json.bin index db8ec07e0..81e193cdf 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.json.bin @@ -1,58 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.xml.bin index f93fb0917..381376824 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.json.bin index b65167aa7..d9b4368f3 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.json.bin @@ -1,56 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -61,8 +63,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.xml.bin index c94ee6b52..8ff51458f 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.json.bin index 8c1632de4..867315ffb 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.json.bin @@ -1,56 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -61,8 +63,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.xml.bin index a24873904..6f8e6a5dd 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.json.bin index 3c5da6dea..9565144a9 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.json.bin @@ -1,56 +1,58 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "library", + "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", + "version": "1.0.0" + } + }, "components": [ { - "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "name": "comp_a", "type": "library", + "bom-ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda", "version": "1.0.0" }, { + "name": "comp_b", + "type": "library", "bom-ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", + "version": "1.0.0", "components": [ { - "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "name": "comp_c", "type": "library", + "bom-ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789", "version": "1.0.0" } - ], - "name": "comp_b", - "type": "library", - "version": "1.0.0" + ] } ], "dependencies": [ { + "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857", "dependsOn": [ "cd3e9c95-9d41-49e7-9924-8cf0465ae789" - ], - "ref": "0b049d09-64c0-4490-a0f5-c84d9aacf857" + ] }, { "ref": "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" }, { + "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", "dependsOn": [ "0b049d09-64c0-4490-a0f5-c84d9aacf857", "17e3b199-dc0b-42ef-bfdd-1fa81a1e3eda" - ], - "ref": "be2c6502-7e9a-47db-9a66-e34f729810a3" + ] }, { "ref": "cd3e9c95-9d41-49e7-9924-8cf0465ae789" } ], - "metadata": { - "component": { - "bom-ref": "be2c6502-7e9a-47db-9a66-e34f729810a3", - "name": "app", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -61,8 +63,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.xml.bin index 6b1078990..5277b148a 100644 --- a/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_275_components-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.1.xml.bin index 210e36e9f..8ea695ddd 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.1.xml.bin @@ -1,17 +1,20 @@ - + A 0.1 + false B 1.0 + false C 1.0 + false diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.json.bin index b44dc6878..3ef71434a 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.json.bin @@ -1,62 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.xml.bin index dcc24077b..04dafc300 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.json.bin index 16985452e..9df322b51 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.json.bin @@ -1,62 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.xml.bin index c6e67375c..609a5d567 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.json.bin index 7aa0517fa..ad2ee27cf 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.json.bin @@ -1,62 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.xml.bin index f54eea8ab..d37be61f7 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.json.bin index f0b8e5a78..414a537ea 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.json.bin @@ -1,60 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -65,8 +67,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.xml.bin index 4d741a7d0..82d8c8769 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.json.bin index 4e9a3b248..3b5a6be59 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.json.bin @@ -1,60 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -65,8 +67,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.xml.bin index 07f8c3abe..b049f68b6 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.json.bin index 134f26f7f..8a767fa66 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.json.bin @@ -1,60 +1,62 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "my-project", + "type": "application", + "bom-ref": "my-project", + "version": "1" + } + }, "components": [ { + "name": "A", + "type": "library", "bom-ref": "component-A", + "version": "0.1", "components": [ { + "name": "B", + "type": "library", "bom-ref": "component-B", + "version": "1.0", "components": [ { - "bom-ref": "component-C", "name": "C", "type": "library", + "bom-ref": "component-C", "version": "1.0" } - ], - "name": "B", - "type": "library", - "version": "1.0" + ] } - ], - "name": "A", - "type": "library", - "version": "0.1" + ] } ], "dependencies": [ { + "ref": "component-A", "dependsOn": [ "component-B" - ], - "ref": "component-A" + ] }, { + "ref": "component-B", "dependsOn": [ "component-C" - ], - "ref": "component-B" + ] }, { "ref": "component-C" }, { + "ref": "my-project", "dependsOn": [ "component-A" - ], - "ref": "my-project" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-project", - "name": "my-project", - "type": "application", - "version": "1" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -65,8 +67,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.xml.bin index b5b2b60ae..631e99100 100644 --- a/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_328_components-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.1.xml.bin index 6506e2bf1..d992b03f2 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.1.xml.bin @@ -1,9 +1,10 @@ - + dummy + false https://acme.org diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.json.bin index af420942b..dd59ea87e 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.json.bin @@ -1,27 +1,32 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -29,11 +34,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.xml.bin index 659778ba2..5ab0d7ac9 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.json.bin index 1eba574fc..0580e5496 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.json.bin @@ -1,27 +1,32 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", + "version": "", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library", - "version": "" + ] } ], "dependencies": [ @@ -29,11 +34,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.xml.bin index eb950283c..d409785ae 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.json.bin index f715c57ae..83ecd9377 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.json.bin @@ -1,26 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -28,11 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.xml.bin index 0364698a3..68ae719ec 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.json.bin index 60a822f1d..1204d4e39 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.json.bin @@ -1,26 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -28,9 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -41,8 +43,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.xml.bin index f947d6cec..24a06010c 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.json.bin index 4336a31cb..6e08dc5cc 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.json.bin @@ -1,26 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -28,9 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -41,8 +43,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.xml.bin index c7fee449b..9bce9719a 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.json.bin index dce009b61..7f0057836 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.json.bin @@ -1,26 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "dummy", + "type": "library", "bom-ref": "dummy", "externalReferences": [ { - "comment": "nothing special", "type": "other", - "url": "https://acme.org" + "url": "https://acme.org", + "comment": "nothing special" }, { - "comment": "pre-encoded", "type": "other", - "url": "https://acme.org/?bar%5b23%5D=42" + "url": "https://acme.org/?bar%5b23%5D=42", + "comment": "pre-encoded" }, { - "comment": "control characters", "type": "other", - "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27" + "url": "https://acme.org/?foo=sp%20ace&bar%5B23%5D=42<=1%3C2>=3%3E2&cb=%7Blol%7D"e=%22test%22is%27test%27", + "comment": "control characters" } - ], - "name": "dummy", - "type": "library" + ] } ], "dependencies": [ @@ -28,9 +33,6 @@ "ref": "dummy" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -41,8 +43,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.xml.bin index 63c3332f5..3ec3aefd5 100644 --- a/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_497_urls-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin index 7e9f29bb1..ad73d6217 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.1.xml.bin @@ -1,15 +1,17 @@ - + dummy 2.3.5 pkg:pypi/pathlib2@2.3.5 + false dummy 2.3.5 pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6 + false diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin index cba8ccc0c..992a52f1f 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,11 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin index 8e52087ff..e472e5946 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin index 4f4e55285..5078c36c9 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,11 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin index 56808073b..174e2d587 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin index 5745f1cf5..64f5c35f9 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,11 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin index 81a3cb223..c5bc086c7 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin index a88cf7ae5..f3d38862b 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin index 36630746e..dff4b9208 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin index 1251020bb..6a1885fab 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin index 183903671..de43f3952 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.json.bin index bb0266dca..61f539980 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.json.bin @@ -1,18 +1,23 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "dummy-a", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-a", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5" }, { - "bom-ref": "dummy-b", "name": "dummy", - "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6", "type": "library", - "version": "2.3.5" + "bom-ref": "dummy-b", + "version": "2.3.5", + "purl": "pkg:pypi/pathlib2@2.3.5?vcs_url=git%2Bhttps://github.com/jazzband/pathlib2.git%405a6a88db3cc1d08dbc86fbe15edfb69fb5f5a3d6" } ], "dependencies": [ @@ -23,9 +28,6 @@ "ref": "dummy-b" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -36,8 +38,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.xml.bin index 8a17c960d..678f5c708 100644 --- a/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_598_multiple_components_with_purl_qualifiers-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.1.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.1.xml.bin index ed55f2e1d..484e7c361 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.1.xml.bin @@ -1,9 +1,10 @@ - + example 15.8.0 + false diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.json.bin index 23e771fbb..aec516393 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.json.bin @@ -1,9 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", "type": "library", + "bom-ref": "example@15.8.0", "version": "15.8.0" } ], @@ -12,11 +17,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.xml.bin index 52a808fd5..424ed5de3 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.json.bin index 7aad7daca..fd0966719 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.json.bin @@ -1,15 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", + "type": "library", + "bom-ref": "example@15.8.0", + "version": "15.8.0", "properties": [ { - "name": "cdx:npm:package:path" + "name": "cdx:npm:package:path", + "value": "" } - ], - "type": "library", - "version": "15.8.0" + ] } ], "dependencies": [ @@ -17,11 +23,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.xml.bin index c840840b3..3356947ca 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.json.bin index d60f3f65d..e5aaa14a6 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.json.bin @@ -1,15 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", + "type": "library", + "bom-ref": "example@15.8.0", + "version": "15.8.0", "properties": [ { - "name": "cdx:npm:package:path" + "name": "cdx:npm:package:path", + "value": "" } - ], - "type": "library", - "version": "15.8.0" + ] } ], "dependencies": [ @@ -17,11 +23,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.xml.bin index 94b4e6945..fac8f2b87 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.json.bin index f538e2afe..459293ef0 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.json.bin @@ -1,15 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", + "type": "library", + "bom-ref": "example@15.8.0", + "version": "15.8.0", "properties": [ { - "name": "cdx:npm:package:path" + "name": "cdx:npm:package:path", + "value": "" } - ], - "type": "library", - "version": "15.8.0" + ] } ], "dependencies": [ @@ -17,9 +23,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -30,8 +33,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.xml.bin index 54be5404c..672b16a8c 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.json.bin index 46cca52fd..7dcc8e749 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.json.bin @@ -1,15 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", + "type": "library", + "bom-ref": "example@15.8.0", + "version": "15.8.0", "properties": [ { - "name": "cdx:npm:package:path" + "name": "cdx:npm:package:path", + "value": "" } - ], - "type": "library", - "version": "15.8.0" + ] } ], "dependencies": [ @@ -17,9 +23,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -30,8 +33,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.xml.bin index 345708a3e..bdf019ceb 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.json.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.json.bin index 0bdc84311..d09ac7dc2 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.json.bin @@ -1,15 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "bom-ref": "example@15.8.0", "name": "example", + "type": "library", + "bom-ref": "example@15.8.0", + "version": "15.8.0", "properties": [ { - "name": "cdx:npm:package:path" + "name": "cdx:npm:package:path", + "value": "" } - ], - "type": "library", - "version": "15.8.0" + ] } ], "dependencies": [ @@ -17,9 +23,6 @@ "ref": "example@15.8.0" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -30,8 +33,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.xml.bin b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.xml.bin index e6dc26f8d..4174c0ffe 100644 --- a/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_for_issue_630_empty_property-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.1.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.json.bin index a2b15378c..47a08bab0 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.json.bin @@ -1,71 +1,46 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "externalReferences": [ - { - "comment": "No comment", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", "description": "This component is awesome", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "scope": "required", "licenses": [ { "license": { @@ -73,12 +48,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -86,14 +76,14 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -101,22 +91,16 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -124,50 +108,36 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -175,102 +145,132 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } - ] - }, - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "scope": "required", - "supplier": { - "contact": [ + ], + "commits": [ { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } } ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] + "notes": "Some notes here please" }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ], + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] + } + ] }, "manufacture": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, "supplier": { + "name": "Cyclone DX", + "url": [ + "https://cyclonedx.org/" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" ] - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.xml.bin index 494079589..25db82678 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.json.bin index 82f119774..6ac164114 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.json.bin @@ -1,93 +1,46 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -95,12 +48,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -108,14 +76,14 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -123,22 +91,16 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -146,56 +108,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -203,39 +151,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -246,39 +224,90 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "scope": "required", - "supplier": { - "contact": [ + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "text": "Commercial" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "text": "Commercial 2" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" + } + }, + "manufacture": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "supplier": { + "name": "Cyclone DX", + "url": [ + "https://cyclonedx.org/" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } + ] }, "licenses": [ { @@ -293,24 +322,6 @@ } } ], - "manufacture": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "properties": [ { "name": "key1", @@ -320,24 +331,13 @@ "name": "key2", "value": "val2" } - ], - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" - ] - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.xml.bin index 4b23f5a95..3083f3f36 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.json.bin index adc2bc76e..c26e61080 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.json.bin @@ -1,93 +1,46 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -95,12 +48,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -108,14 +76,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -123,21 +90,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -145,55 +106,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -201,39 +149,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -244,30 +222,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -279,63 +332,39 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" + } + }, + "manufacture": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "supplier": { + "name": "Cyclone DX", + "url": [ + "https://cyclonedx.org/" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } + ] }, "licenses": [ { @@ -350,24 +379,6 @@ } } ], - "manufacture": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "properties": [ { "name": "key1", @@ -377,24 +388,13 @@ "name": "key2", "value": "val2" } - ], - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" - ] - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.xml.bin index e9cef55b1..d28262fe4 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.json.bin index c3e653c75..e2d4fb928 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.json.bin @@ -1,93 +1,51 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "lifecycles": [ + { + "phase": "build" + } + ], "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -95,12 +53,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -108,14 +81,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -123,21 +95,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -145,55 +111,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -201,39 +154,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -244,30 +227,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -279,63 +337,39 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" + } + }, + "manufacture": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "supplier": { + "name": "Cyclone DX", + "url": [ + "https://cyclonedx.org/" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } + ] }, "licenses": [ { @@ -350,29 +384,6 @@ } } ], - "lifecycles": [ - { - "phase": "build" - } - ], - "manufacture": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "properties": [ { "name": "key1", @@ -382,22 +393,13 @@ "name": "key2", "value": "val2" } - ], - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" - ] - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "properties": [ { "name": "key1", @@ -408,8 +410,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.xml.bin index 0280b1add..54da2ecc5 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.json.bin index ff9232be7..628efbd7e 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.json.bin @@ -1,130 +1,109 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "lifecycles": [ + { + "phase": "build" + } + ], "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "supplier": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], "manufacturer": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "name": "setuptools", + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -132,14 +111,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -147,21 +125,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -169,55 +141,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -225,39 +184,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -268,30 +257,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -303,145 +367,83 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" - }, - "licenses": [ - { - "license": { - "id": "Apache-2.0", - "text": { - "content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", - "contentType": "text/plain", - "encoding": "base64" - }, - "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" - } } - ], - "lifecycles": [ - { - "phase": "build" - } - ], + }, "manufacture": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, - { - "name": "key2", - "value": "val2" - } - ], "supplier": { + "name": "Cyclone DX", "address": { "country": "US", + "region": "Texas", "locality": "Austin", "postOfficeBoxNumber": "105a", "postalCode": "12345", - "region": "Texas", "streetAddress": "100 Yee-Ha Street" }, + "url": [ + "https://cyclonedx.org/" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" ] }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "text": { + "content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", + "contentType": "text/plain", + "encoding": "base64" + }, + "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" + } + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ] }, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "properties": [ { "name": "key1", @@ -452,8 +454,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.xml.bin index 1c0dc4476..1ace2abfa 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.json.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.json.bin index 4869ed921..3b3fc5134 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.json.bin @@ -1,130 +1,109 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-dings" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "lifecycles": [ + { + "phase": "build" + } + ], "authors": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ], "component": { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "supplier": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], "manufacturer": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "name": "setuptools", + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -132,14 +111,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -147,21 +125,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -169,55 +141,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -225,39 +184,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -268,30 +257,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -303,148 +367,86 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" - }, - "distributionConstraints": { - "tlp": "GREEN" - }, - "licenses": [ - { - "license": { - "id": "Apache-2.0", - "text": { - "content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", - "contentType": "text/plain", - "encoding": "base64" - }, - "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" - } } - ], - "lifecycles": [ - { - "phase": "build" - } - ], + }, "manufacture": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, - { - "name": "key2", - "value": "val2" - } - ], "supplier": { + "name": "Cyclone DX", "address": { "country": "US", + "region": "Texas", "locality": "Austin", "postOfficeBoxNumber": "105a", "postalCode": "12345", - "region": "Texas", "streetAddress": "100 Yee-Ha Street" }, + "url": [ + "https://cyclonedx.org/" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" } - ], - "name": "Cyclone DX", - "url": [ - "https://cyclonedx.org/" ] }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "text": { + "content": "VGVzdCBjb250ZW50IC0gdGhpcyBpcyBub3QgdGhlIEFwYWNoZSAyLjAgbGljZW5zZSE=", + "contentType": "text/plain", + "encoding": "base64" + }, + "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" + } + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], + "distributionConstraints": { + "tlp": "GREEN" + } }, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-dings" + } + ], "properties": [ { "name": "key1", @@ -455,8 +457,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.xml.bin b/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.xml.bin index d188f978f..fb94867fe 100644 --- a/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_just_complete_metadata-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.json.bin index baf6f457b..08fda6042 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.json.bin @@ -1,37 +1,42 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Algorithm", + "type": "cryptographic-asset", "bom-ref": "8182921e-0588-472e-b8f9-9c527c68f067", + "version": "1.0", "cryptoProperties": { + "assetType": "algorithm", "algorithmProperties": { + "primitive": "kem", + "parameterSetIdentifier": "a-parameter-set-id", + "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", + "executionEnvironment": "software-plain-ram", + "implementationPlatform": "generic", "certificationLevel": [ "fips140-1-l1", "fips140-2-l3", "other" ], - "classicalSecurityLevel": 2, + "mode": "ecb", + "padding": "pkcs7", "cryptoFunctions": [ "sign", "unknown" ], - "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", - "executionEnvironment": "software-plain-ram", - "implementationPlatform": "generic", - "mode": "ecb", - "nistQuantumSecurityLevel": 2, - "padding": "pkcs7", - "parameterSetIdentifier": "a-parameter-set-id", - "primitive": "kem" + "classicalSecurityLevel": 2, + "nistQuantumSecurityLevel": 2 }, - "assetType": "algorithm", "oid": "an-oid-here" }, - "name": "My Algorithm", "tags": [ "algorithm" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -39,9 +44,6 @@ "ref": "8182921e-0588-472e-b8f9-9c527c68f067" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -52,8 +54,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.xml.bin index 43214f2cc..00db2aa56 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.json.bin index 819b1821b..aa4f689ec 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.json.bin @@ -1,37 +1,42 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Algorithm", + "type": "cryptographic-asset", "bom-ref": "8182921e-0588-472e-b8f9-9c527c68f067", + "version": "1.0", "cryptoProperties": { + "assetType": "algorithm", "algorithmProperties": { + "primitive": "kem", + "parameterSetIdentifier": "a-parameter-set-id", + "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", + "executionEnvironment": "software-plain-ram", + "implementationPlatform": "generic", "certificationLevel": [ "fips140-1-l1", "fips140-2-l3", "other" ], - "classicalSecurityLevel": 2, + "mode": "ecb", + "padding": "pkcs7", "cryptoFunctions": [ "sign", "unknown" ], - "curve": "9n8y2oxty3ao83n8qc2g2x3qcw4jt4wj", - "executionEnvironment": "software-plain-ram", - "implementationPlatform": "generic", - "mode": "ecb", - "nistQuantumSecurityLevel": 2, - "padding": "pkcs7", - "parameterSetIdentifier": "a-parameter-set-id", - "primitive": "kem" + "classicalSecurityLevel": 2, + "nistQuantumSecurityLevel": 2 }, - "assetType": "algorithm", "oid": "an-oid-here" }, - "name": "My Algorithm", "tags": [ "algorithm" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -39,9 +44,6 @@ "ref": "8182921e-0588-472e-b8f9-9c527c68f067" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -52,8 +54,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.xml.bin index a31cf67d7..600e63d03 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_algorithm-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.json.bin index bb1fdf249..76dfcf262 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.json.bin @@ -1,25 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Certificate", + "type": "cryptographic-asset", "bom-ref": "1f4ed1e4-582a-4fa0-8c38-1b4facc16972", + "version": "1.0", "cryptoProperties": { "assetType": "certificate", "certificateProperties": { - "certificateExtension": "csr", - "certificateFormat": "pem", + "subjectName": "cyclonedx.org", "issuerName": "Cloudflare Inc ECC CA-3", - "notValidAfter": "2024-05-19T00:59:59.999999+00:00", "notValidBefore": "2023-05-19T01:00:00+00:00", - "subjectName": "cyclonedx.org" + "notValidAfter": "2024-05-19T00:59:59.999999+00:00", + "certificateFormat": "pem", + "certificateExtension": "csr" }, "oid": "an-oid-here" }, - "name": "My Certificate", "tags": [ "certificate" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -27,9 +32,6 @@ "ref": "1f4ed1e4-582a-4fa0-8c38-1b4facc16972" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -40,8 +42,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.xml.bin index 777628923..a8e917166 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.json.bin index 1ded17727..2b564e1ac 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.json.bin @@ -1,25 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Certificate", + "type": "cryptographic-asset", "bom-ref": "1f4ed1e4-582a-4fa0-8c38-1b4facc16972", + "version": "1.0", "cryptoProperties": { "assetType": "certificate", "certificateProperties": { - "certificateExtension": "csr", - "certificateFormat": "pem", + "subjectName": "cyclonedx.org", "issuerName": "Cloudflare Inc ECC CA-3", - "notValidAfter": "2024-05-19T00:59:59.999999+00:00", "notValidBefore": "2023-05-19T01:00:00+00:00", - "subjectName": "cyclonedx.org" + "notValidAfter": "2024-05-19T00:59:59.999999+00:00", + "certificateFormat": "pem", + "certificateExtension": "csr" }, "oid": "an-oid-here" }, - "name": "My Certificate", "tags": [ "certificate" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -27,9 +32,6 @@ "ref": "1f4ed1e4-582a-4fa0-8c38-1b4facc16972" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -40,8 +42,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.xml.bin index 81a2ac3ca..5d2aba7f2 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_certificate-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.json.bin index cd0c20076..1ce25e499 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.json.bin @@ -1,58 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "TLS", + "type": "cryptographic-asset", "bom-ref": "26b1ce0f-bec6-4bfe-9db1-03b75a4ed1ec", + "version": "v1.3", "cryptoProperties": { "assetType": "protocol", - "oid": "an-oid-here", "protocolProperties": { + "type": "tls", + "version": "1.3", "cipherSuites": [ { + "name": "TLS_AES_128_CCM_8_SHA256", "identifiers": [ "TLS_AES_128_CCM_8_SHA256" - ], - "name": "TLS_AES_128_CCM_8_SHA256" + ] }, { + "name": "TLS_AES_128_CCM_SHA256", "identifiers": [ "TLS_AES_128_CCM_SHA256" - ], - "name": "TLS_AES_128_CCM_SHA256" + ] }, { + "name": "TLS_AES_128_GCM_SHA256", "identifiers": [ "TLS_AES_128_GCM_SHA256" - ], - "name": "TLS_AES_128_GCM_SHA256" + ] }, { + "name": "TLS_AES_256_GCM_SHA384", "identifiers": [ "TLS_AES_256_GCM_SHA384" - ], - "name": "TLS_AES_256_GCM_SHA384" + ] }, { + "name": "TLS_CHACHA20_POLY1305_SHA256", "identifiers": [ "TLS_CHACHA20_POLY1305_SHA256" - ], - "name": "TLS_CHACHA20_POLY1305_SHA256" + ] } ], "cryptoRefArray": [ "for-test-1", "for-test-2" - ], - "type": "tls", - "version": "1.3" - } + ] + }, + "oid": "an-oid-here" }, - "name": "TLS", "tags": [ "protocl", "tls" - ], - "type": "cryptographic-asset", - "version": "v1.3" + ] } ], "dependencies": [ @@ -60,9 +65,6 @@ "ref": "26b1ce0f-bec6-4bfe-9db1-03b75a4ed1ec" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -73,8 +75,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.xml.bin index 5392e824e..17e7dc860 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.json.bin index 973ed625d..a52f79e7d 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.json.bin @@ -1,58 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "TLS", + "type": "cryptographic-asset", "bom-ref": "26b1ce0f-bec6-4bfe-9db1-03b75a4ed1ec", + "version": "v1.3", "cryptoProperties": { "assetType": "protocol", - "oid": "an-oid-here", "protocolProperties": { + "type": "tls", + "version": "1.3", "cipherSuites": [ { + "name": "TLS_AES_128_CCM_8_SHA256", "identifiers": [ "TLS_AES_128_CCM_8_SHA256" - ], - "name": "TLS_AES_128_CCM_8_SHA256" + ] }, { + "name": "TLS_AES_128_CCM_SHA256", "identifiers": [ "TLS_AES_128_CCM_SHA256" - ], - "name": "TLS_AES_128_CCM_SHA256" + ] }, { + "name": "TLS_AES_128_GCM_SHA256", "identifiers": [ "TLS_AES_128_GCM_SHA256" - ], - "name": "TLS_AES_128_GCM_SHA256" + ] }, { + "name": "TLS_AES_256_GCM_SHA384", "identifiers": [ "TLS_AES_256_GCM_SHA384" - ], - "name": "TLS_AES_256_GCM_SHA384" + ] }, { + "name": "TLS_CHACHA20_POLY1305_SHA256", "identifiers": [ "TLS_CHACHA20_POLY1305_SHA256" - ], - "name": "TLS_CHACHA20_POLY1305_SHA256" + ] } ], "cryptoRefArray": [ "for-test-1", "for-test-2" - ], - "type": "tls", - "version": "1.3" - } + ] + }, + "oid": "an-oid-here" }, - "name": "TLS", "tags": [ "protocl", "tls" - ], - "type": "cryptographic-asset", - "version": "v1.3" + ] } ], "dependencies": [ @@ -60,9 +65,6 @@ "ref": "26b1ce0f-bec6-4bfe-9db1-03b75a4ed1ec" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -73,8 +75,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.xml.bin index 5c91c3b5f..93f6ad10d 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_protocol-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.json.bin index 07cee9c2c..ca88424c9 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.json.bin @@ -1,32 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Encrypted Thing", + "type": "cryptographic-asset", "bom-ref": "332b3cee-078c-4789-ab15-887565b6fac5", + "version": "1.0", "cryptoProperties": { "assetType": "related-crypto-material", - "oid": "an-oid-here", "relatedCryptoMaterialProperties": { - "activationDate": "2023-05-19T01:00:00+00:00", + "type": "digest", + "id": "some-identifier", + "state": "active", "creationDate": "2023-05-19T01:00:00+00:00", + "activationDate": "2023-05-19T01:00:00+00:00", "expirationDate": "2024-05-19T00:59:59.999999+00:00", + "value": "some-random-value", + "size": 32, "format": "a-format", - "id": "some-identifier", "securedBy": { "mechanism": "hard-work" - }, - "size": 32, - "state": "active", - "type": "digest", - "value": "some-random-value" - } + } + }, + "oid": "an-oid-here" }, - "name": "My Encrypted Thing", "tags": [ "data", "encrypted" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -34,9 +39,6 @@ "ref": "332b3cee-078c-4789-ab15-887565b6fac5" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -47,8 +49,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.xml.bin index dca04e899..65fd4815b 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.json.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.json.bin index 9c404d2e5..09a5fddc9 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.json.bin @@ -1,32 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "My Encrypted Thing", + "type": "cryptographic-asset", "bom-ref": "332b3cee-078c-4789-ab15-887565b6fac5", + "version": "1.0", "cryptoProperties": { "assetType": "related-crypto-material", - "oid": "an-oid-here", "relatedCryptoMaterialProperties": { - "activationDate": "2023-05-19T01:00:00+00:00", + "type": "digest", + "id": "some-identifier", + "state": "active", "creationDate": "2023-05-19T01:00:00+00:00", + "activationDate": "2023-05-19T01:00:00+00:00", "expirationDate": "2024-05-19T00:59:59.999999+00:00", + "value": "some-random-value", + "size": 32, "format": "a-format", - "id": "some-identifier", "securedBy": { "mechanism": "hard-work" - }, - "size": 32, - "state": "active", - "type": "digest", - "value": "some-random-value" - } + } + }, + "oid": "an-oid-here" }, - "name": "My Encrypted Thing", "tags": [ "data", "encrypted" - ], - "type": "cryptographic-asset", - "version": "1.0" + ] } ], "dependencies": [ @@ -34,9 +39,6 @@ "ref": "332b3cee-078c-4789-ab15-887565b6fac5" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -47,8 +49,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.xml.bin b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.xml.bin index 239e2c956..c70583e56 100644 --- a/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_v1_6_with_crypto_related_material-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.1.xml.bin index ba1ca960c..dc7416908 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.2.json.bin index ad71ac13f..73c8e457d 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.2.json.bin @@ -1,8 +1,34 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": [ + { + "name": "product-cbom-generator" + } + ], + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "version": "", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,46 +36,20 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": [ - { - "name": "product-cbom-generator" - } - ] - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.2.xml.bin index 627c7c208..58a13bddc 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.3.json.bin index d6c236a0b..1a16b5fb2 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.3.json.bin @@ -1,9 +1,50 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": [ + { + "name": "product-cbom-generator" + } + ], + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "version": "", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "evidence": { + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], "copyright": [ { "text": "Commercial" @@ -11,62 +52,21 @@ { "text": "Commercial 2" } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } ] - }, - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": [ - { - "name": "product-cbom-generator" - } - ] - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.3.xml.bin index 0cc9d8a2a..2cdb1c6e5 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.4.json.bin index 89c09d4fb..92312a099 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.4.json.bin @@ -1,9 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": [ + { + "name": "product-cbom-generator" + } + ], + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "evidence": { + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], "copyright": [ { "text": "Commercial" @@ -11,61 +51,21 @@ { "text": "Commercial 2" } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } ] - }, - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": [ - { - "name": "product-cbom-generator" - } - ] - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.4.xml.bin index ce6a522b4..83b31aba8 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.5.json.bin index 927c25de4..b4867f8ee 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.5.json.bin @@ -1,40 +1,53 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": { + "components": [ + { + "name": "product-cbom-generator", + "type": "application", + "bom-ref": "cbom:generator" + } + ] + }, + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "evidence": { - "callstack": { - "frames": [ - { - "column": 5, - "fullFilename": "path/to/file", - "function": "example_function", - "line": 10, - "module": "example.module", - "package": "example.package", - "parameters": [ - "param1", - "param2" - ] - } - ] - }, - "copyright": [ - { - "text": "Commercial" - }, - { - "text": "Commercial 2" + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" } - ], + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "evidence": { "identity": { - "confidence": 0.1, "field": "hash", + "confidence": 0.1, "methods": [ { - "confidence": 0.1, "technique": "attestation", + "confidence": 0.1, "value": "analysis-tool" } ], @@ -42,6 +55,27 @@ "cbom:generator" ] }, + "occurrences": [ + { + "location": "path/to/file" + } + ], + "callstack": { + "frames": [ + { + "module": "example.module", + "package": "example.package", + "function": "example_function", + "parameters": [ + "param1", + "param2" + ], + "line": 10, + "column": 5, + "fullFilename": "path/to/file" + } + ] + }, "licenses": [ { "license": { @@ -49,60 +83,28 @@ } } ], - "occurrences": [ + "copyright": [ { - "location": "path/to/file" + "text": "Commercial" + }, + { + "text": "Commercial 2" } ] - }, - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": { - "components": [ - { - "bom-ref": "cbom:generator", - "name": "product-cbom-generator", - "type": "application" - } - ] - } - }, "properties": [ { "name": "key1", @@ -113,8 +115,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.5.xml.bin index 32aa5e81a..b3f1f406f 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.6.json.bin index ceeb6976a..4229a90be 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.6.json.bin @@ -1,42 +1,55 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": { + "components": [ + { + "name": "product-cbom-generator", + "type": "application", + "bom-ref": "cbom:generator" + } + ] + }, + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "evidence": { - "callstack": { - "frames": [ - { - "column": 5, - "fullFilename": "path/to/file", - "function": "example_function", - "line": 10, - "module": "example.module", - "package": "example.package", - "parameters": [ - "param1", - "param2" - ] - } - ] - }, - "copyright": [ - { - "text": "Commercial" - }, - { - "text": "Commercial 2" + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" } - ], + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "evidence": { "identity": [ { - "concludedValue": "example-hash", - "confidence": 0.1, "field": "hash", + "confidence": 0.1, + "concludedValue": "example-hash", "methods": [ { - "confidence": 0.1, "technique": "attestation", + "confidence": 0.1, "value": "analysis-tool" } ], @@ -45,13 +58,13 @@ ] }, { - "concludedValue": "example-component", - "confidence": 0.9, "field": "name", + "confidence": 0.9, + "concludedValue": "example-component", "methods": [ { - "confidence": 0.8, "technique": "source-code-analysis", + "confidence": 0.8, "value": "analysis-tool" } ], @@ -60,6 +73,31 @@ ] } ], + "occurrences": [ + { + "location": "path/to/file", + "line": 42, + "offset": 16, + "symbol": "exampleSymbol", + "additionalContext": "Found in source code" + } + ], + "callstack": { + "frames": [ + { + "module": "example.module", + "package": "example.package", + "function": "example_function", + "parameters": [ + "param1", + "param2" + ], + "line": 10, + "column": 5, + "fullFilename": "path/to/file" + } + ] + }, "licenses": [ { "license": { @@ -67,64 +105,28 @@ } } ], - "occurrences": [ + "copyright": [ { - "additionalContext": "Found in source code", - "line": 42, - "location": "path/to/file", - "offset": 16, - "symbol": "exampleSymbol" + "text": "Commercial" + }, + { + "text": "Commercial 2" } ] - }, - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": { - "components": [ - { - "bom-ref": "cbom:generator", - "name": "product-cbom-generator", - "type": "application" - } - ] - } - }, "properties": [ { "name": "key1", @@ -135,8 +137,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.6.xml.bin index 40dfb7649..7ad229a43 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.7.json.bin index a1bf57584..a3cd8d2e0 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.7.json.bin @@ -1,42 +1,55 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "tools": { + "components": [ + { + "name": "product-cbom-generator", + "type": "application", + "bom-ref": "cbom:generator" + } + ] + }, + "component": { + "name": "root-component", + "type": "application", + "bom-ref": "myApp", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ] + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "evidence": { - "callstack": { - "frames": [ - { - "column": 5, - "fullFilename": "path/to/file", - "function": "example_function", - "line": 10, - "module": "example.module", - "package": "example.package", - "parameters": [ - "param1", - "param2" - ] - } - ] - }, - "copyright": [ - { - "text": "Commercial" - }, - { - "text": "Commercial 2" + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" } - ], + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "evidence": { "identity": [ { - "concludedValue": "example-hash", - "confidence": 0.1, "field": "hash", + "confidence": 0.1, + "concludedValue": "example-hash", "methods": [ { - "confidence": 0.1, "technique": "attestation", + "confidence": 0.1, "value": "analysis-tool" } ], @@ -45,13 +58,13 @@ ] }, { - "concludedValue": "example-component", - "confidence": 0.9, "field": "name", + "confidence": 0.9, + "concludedValue": "example-component", "methods": [ { - "confidence": 0.8, "technique": "source-code-analysis", + "confidence": 0.8, "value": "analysis-tool" } ], @@ -60,6 +73,31 @@ ] } ], + "occurrences": [ + { + "location": "path/to/file", + "line": 42, + "offset": 16, + "symbol": "exampleSymbol", + "additionalContext": "Found in source code" + } + ], + "callstack": { + "frames": [ + { + "module": "example.module", + "package": "example.package", + "function": "example_function", + "parameters": [ + "param1", + "param2" + ], + "line": 10, + "column": 5, + "fullFilename": "path/to/file" + } + ] + }, "licenses": [ { "license": { @@ -67,64 +105,28 @@ } } ], - "occurrences": [ + "copyright": [ { - "additionalContext": "Found in source code", - "line": 42, - "location": "path/to/file", - "offset": 16, - "symbol": "exampleSymbol" + "text": "Commercial" + }, + { + "text": "Commercial 2" } ] - }, - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ { + "ref": "myApp", "dependsOn": [ "pkg:pypi/setuptools@50.3.2?extension=tar.gz" - ], - "ref": "myApp" + ] }, { "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "component": { - "bom-ref": "myApp", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "root-component", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00", - "tools": { - "components": [ - { - "bom-ref": "cbom:generator", - "name": "product-cbom-generator", - "type": "application" - } - ] - } - }, "properties": [ { "name": "key1", @@ -135,8 +137,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_evidence-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_evidence-1.7.xml.bin index ca95d432f..a93f39870 100644 --- a/tests/_data/snapshots/get_bom_with_component_evidence-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_evidence-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.1.xml.bin index ba1ca960c..dc7416908 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.json.bin index b96615dbe..1ee76cddb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.xml.bin index bb9597137..a1b7b3385 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.json.bin index 3437dbb74..a761402a4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.xml.bin index 49ba0ae39..6a28cad36 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.json.bin index dcce930d9..4afc798c1 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.xml.bin index 86cbdb059..cff332fc1 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.json.bin index 907820fb9..19a9b648a 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.xml.bin index 4d9bbf6d8..8e0502639 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.json.bin index 801b3e18b..9cc4e7b31 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.xml.bin index 6de92d825..7a9a82e97 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.json.bin index 2e5fc61cc..edc1411fa 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.xml.bin index 07ead6601..d47952a91 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_basic-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.1.xml.bin index 851c9d9b8..ee5a2b7fc 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.1.xml.bin @@ -1,5 +1,5 @@ - + CycloneDX @@ -15,6 +15,7 @@ Apache 2.0 baby! cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:* pkg:pypi/setuptools@50.3.2?extension=tar.gz + false @@ -114,6 +115,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false toml @@ -122,6 +124,7 @@ 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b pkg:pypi/toml@0.10.2?extension=tar.gz + false https://cyclonedx.org diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.json.bin index 66425d453..cc856d91e 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.json.bin @@ -1,55 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "externalReferences": [ - { - "comment": "No comment", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", "description": "This component is awesome", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "scope": "required", "licenses": [ { "license": { @@ -57,12 +39,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -70,14 +67,14 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -85,22 +82,16 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -108,50 +99,36 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -159,66 +136,94 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } - ] - }, - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "scope": "required", - "supplier": { - "contact": [ + ], + "commits": [ { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } } ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] + "notes": "Some notes here please" }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ], + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] + } + ] } ], "dependencies": [ @@ -226,11 +231,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.xml.bin index 523183bd5..35d2c4ce5 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.json.bin index 0a6e9da25..9ac5464ad 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.json.bin @@ -1,77 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -79,12 +39,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -92,14 +67,14 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -107,22 +82,16 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -130,56 +99,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -187,39 +142,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -230,39 +215,59 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "scope": "required", - "supplier": { - "contact": [ + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "text": "Commercial" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "text": "Commercial 2" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ @@ -270,11 +275,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.xml.bin index d43730dbd..b4e407961 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.json.bin index 59b7580b0..4d06b92ce 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.json.bin @@ -1,77 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -79,12 +39,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -92,14 +67,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -107,21 +81,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -129,55 +97,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -185,39 +140,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -228,30 +213,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -263,63 +323,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ @@ -327,11 +332,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.xml.bin index 93ac29b43..9ee4e161b 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.json.bin index 3f9b5e77f..665a1c91c 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.json.bin @@ -1,77 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "supplier": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -79,12 +39,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -92,14 +67,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -107,21 +81,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -129,55 +97,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -185,39 +140,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -228,30 +213,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -263,63 +323,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ @@ -327,9 +332,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -340,8 +342,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.xml.bin index 8a04634ce..b8b1a79f3 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.json.bin index edd7c2122..76d0e0d42 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.json.bin @@ -1,77 +1,43 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "supplier": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -79,12 +45,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -92,14 +73,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -107,21 +87,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -129,55 +103,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -185,39 +146,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -228,30 +219,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -263,69 +329,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ @@ -333,9 +338,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -346,8 +348,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.xml.bin index 2d5c0d920..98f7b9291 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.json.bin index e9022bcaa..605ca87b9 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.json.bin @@ -1,77 +1,43 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "my-specific-bom-ref-for-dings", - "components": [ - { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "supplier": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" }, - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "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" - } - ], - "copyright": "Apache 2.0 baby!", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", - "description": "This component is awesome", - "evidence": { - "copyright": [ + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ { - "text": "Commercial" + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" }, { - "text": "Commercial 2" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } ] }, - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "author": "Test Author", + "publisher": "CycloneDX", + "version": "50.3.2", + "description": "This component is awesome", + "scope": "required", "licenses": [ { "license": { @@ -79,12 +45,27 @@ } } ], - "name": "setuptools", + "copyright": "Apache 2.0 baby!", + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "swid": { + "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", + "name": "Test Application", + "version": "3.4.5", + "text": { + "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", + "contentType": "text/xml", + "encoding": "base64" + } + }, "pedigree": { "ancestors": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ccc8d7ee-4b9c-4750-aee0-a72585152291", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -92,14 +73,13 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "8a3893b3-9923-4adb-a1d3-47456636ba0a", + "author": "Test Author", "licenses": [ { "license": { @@ -107,21 +87,15 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" - } - ], - "commits": [ - { - "message": "A commit message", - "uid": "a-random-uid" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "descendants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "28b2d8ce-def0-446f-a221-58dee0b44acc", + "author": "Test Author", "licenses": [ { "license": { @@ -129,55 +103,42 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "555ca729-93c6-48f3-956e-bdaa4a2f0bfa", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" - } - ], - "notes": "Some notes here please", - "patches": [ - { - "diff": { - "text": { - "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", - "contentType": "text/x-diff", - "encoding": "base64" - }, - "url": "https://acme.com/my-patch.diff" - }, - "type": "backport" + ] } ], "variants": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "ded1d73e-1fca-4302-b520-f1bc53979958", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -185,39 +146,69 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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" + ] } - ] + ], + "commits": [ + { + "uid": "a-random-uid", + "message": "A commit message" + } + ], + "patches": [ + { + "type": "backport", + "diff": { + "text": { + "content": "LS0tIGZvbwkyMDI0LTAzLTA0IDEyOjQxOjExLjQxODc1OTE0NSArMDEwMAorKysgYmFyCTIwMjQtMDMtMDQgMTI6NDE6MjguMzE1NTE3ODQ3ICswMTAwCkBAIC0xLDIgKzEsMiBAQAotaGVsbG8gd29ybGQuCitIZWxsbyB3b3JsZC4KIAo=", + "contentType": "text/x-diff", + "encoding": "base64" + }, + "url": "https://acme.com/my-patch.diff" + } + } + ], + "notes": "Some notes here please" }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -228,30 +219,105 @@ "value": "val2" } ], - "publisher": "CycloneDX", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "components": [ + { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + }, + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + } + ], + "evidence": { + "copyright": [ + { + "text": "Commercial" + }, + { + "text": "Commercial 2" + } + ] + }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -263,69 +329,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "scope": "required", - "supplier": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] - }, - "swid": { - "name": "Test Application", - "tagId": "swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1", - "text": { - "content": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==", - "contentType": "text/xml", - "encoding": "base64" - }, - "version": "3.4.5" - }, - "type": "library", - "version": "50.3.2" + } } ], "dependencies": [ @@ -333,9 +338,6 @@ "ref": "my-specific-bom-ref-for-dings" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -346,8 +348,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.xml.bin index 3f50554d7..f1de89514 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_complete-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.1.xml.bin index 5bc27d5b3..430db342d 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.json.bin index a6d3ed705..62cb05a08 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.xml.bin index 526d38c81..02c85a501 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.json.bin index 80849832e..ca8b812a7 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", + "version": "", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library", - "version": "" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.xml.bin index 22ba57dc0..c269a157d 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.json.bin index abaee83ae..89baf90a6 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", "licenses": [ { "license": { @@ -10,9 +17,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -20,11 +25,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.xml.bin index a906a61c2..439768515 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.json.bin index d071aec94..c267b94ba 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", "licenses": [ { "license": { @@ -10,9 +17,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -20,9 +25,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -33,8 +35,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.xml.bin index 3c66a8419..149a804a6 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.json.bin index cf65f7820..7762ef944 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", "licenses": [ { "license": { @@ -10,9 +17,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -20,9 +25,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -33,8 +35,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.xml.bin index dc1bc798e..ccc0f0adb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.json.bin index 718dd55a0..3df54af98 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.json.bin @@ -1,8 +1,15 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools?extension=tar.gz", + "author": "Test Author", "licenses": [ { "license": { @@ -10,9 +17,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools?extension=tar.gz", - "type": "library" + "purl": "pkg:pypi/setuptools?extension=tar.gz" } ], "dependencies": [ @@ -20,9 +25,6 @@ "ref": "pkg:pypi/setuptools?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -33,8 +35,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.xml.bin index 42eb8c21f..eb0bba6c7 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_no_component_version-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.1.xml.bin index 21439ea9b..c8383fc63 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -11,6 +11,7 @@ cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:* pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.json.bin index e3aa3849a..c0cca404c 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,11 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.xml.bin index 8cefded03..8d5a3ea4c 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.json.bin index 37a7601d5..78008f662 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,11 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.xml.bin index 70870fd80..533c4e2a7 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.json.bin index 7864fb78b..f121ac9eb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,11 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.xml.bin index 1f9da91dd..668d85376 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.json.bin index 2a276928c..90f151d70 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,9 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -35,8 +37,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.xml.bin index 2cfec03f8..c5e454079 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.json.bin index d6ab5aa9d..8f0fc46c7 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,9 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -35,8 +37,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.xml.bin index 776785bbd..48db05281 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.json.bin index cb155a604..8c3a5f7e4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.json.bin @@ -1,9 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -11,10 +18,8 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "cpe": "cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*", + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -22,9 +27,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -35,8 +37,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.xml.bin index a69b8552c..fd493282c 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_cpe-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.1.xml.bin index ba1ca960c..dc7416908 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.json.bin index b96615dbe..1ee76cddb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.xml.bin index bb9597137..a1b7b3385 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.json.bin index 3437dbb74..a761402a4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.xml.bin index 49ba0ae39..6a28cad36 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.json.bin index a71972856..947cc26c4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,30 +18,53 @@ } } ], - "name": "setuptools", "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -45,34 +76,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "type": "library", - "version": "50.3.2" + ] + } } ], "dependencies": [ @@ -80,11 +85,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.xml.bin index e6dc1ff67..5b0ecb16e 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.json.bin index ae0d6c19b..c9f2c4f94 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,30 +18,53 @@ } } ], - "name": "setuptools", "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -45,34 +76,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "type": "library", - "version": "50.3.2" + ] + } } ], "dependencies": [ @@ -80,9 +85,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -93,8 +95,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.xml.bin index 6983758e1..88e0f25d3 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.json.bin index a6411ed97..eeed18bed 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,30 +18,53 @@ } } ], - "name": "setuptools", "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -45,34 +76,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "type": "library", - "version": "50.3.2" + ] + } } ], "dependencies": [ @@ -80,9 +85,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -93,8 +95,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.xml.bin index df54f9c63..d7ab77c19 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.json.bin index 318441702..50f281e3c 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,30 +18,53 @@ } } ], - "name": "setuptools", "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -45,34 +76,8 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "type": "library", - "version": "50.3.2" + ] + } } ], "dependencies": [ @@ -80,9 +85,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -93,8 +95,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.xml.bin index 29d5c2a6f..e229488a1 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_release_notes-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.1.xml.bin index ba1ca960c..dc7416908 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.json.bin index b96615dbe..1ee76cddb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.xml.bin index bb9597137..a1b7b3385 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.json.bin index 3437dbb74..a761402a4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.xml.bin index 49ba0ae39..6a28cad36 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.json.bin index dcce930d9..4afc798c1 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.xml.bin index 86cbdb059..cff332fc1 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.json.bin index 907820fb9..19a9b648a 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.xml.bin index 4d9bbf6d8..8e0502639 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.json.bin index c1abec2cb..147afe0e9 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.json.bin @@ -1,63 +1,68 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", - "authors": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], "manufacturer": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "name": "setuptools", + "authors": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ], + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "omniborId": [ "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64" ], - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "swhid": [ "swh:1:cnt:4d99d2d18326621ccdd70f5ea66c2e2ac236ad8b;origin=https://gitorious.org/ocamlp3l/ocamlp3l_cvs.git;visit=swh:1:snp:d7f1b9eb7ccb596c2622c4780febaa02549830f9;anchor=swh:1:rev:2db189928c94d62a3b4757b3eec68f0a4d4113f0;path=/Examples/SimpleFarm/simplefarm.ml;lines=9-15", "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", "swh:1:cnt:f10371aa7b8ccabca8479196d6cd640676fd4a04;origin=https://github.com/web-platform-tests/wpt;visit=swh:1:snp:b37d435721bbd450624165f334724e3585346499;anchor=swh:1:rev:259d0612af038d14f2cd889a14a3adb6c9e96d96;path=/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/support/x%3Burl=foo/", "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f" - ], - "type": "library", - "version": "50.3.2" + ] } ], "dependencies": [ @@ -65,9 +70,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -78,8 +80,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.xml.bin index e10d5af9d..ce1ef1906 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.json.bin index 29eb56f4a..d3e931693 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.json.bin @@ -1,63 +1,68 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", - "authors": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], "manufacturer": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, - "name": "setuptools", + "authors": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ], + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "omniborId": [ "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64" ], - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "swhid": [ "swh:1:cnt:4d99d2d18326621ccdd70f5ea66c2e2ac236ad8b;origin=https://gitorious.org/ocamlp3l/ocamlp3l_cvs.git;visit=swh:1:snp:d7f1b9eb7ccb596c2622c4780febaa02549830f9;anchor=swh:1:rev:2db189928c94d62a3b4757b3eec68f0a4d4113f0;path=/Examples/SimpleFarm/simplefarm.ml;lines=9-15", "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", "swh:1:cnt:f10371aa7b8ccabca8479196d6cd640676fd4a04;origin=https://github.com/web-platform-tests/wpt;visit=swh:1:snp:b37d435721bbd450624165f334724e3585346499;anchor=swh:1:rev:259d0612af038d14f2cd889a14a3adb6c9e96d96;path=/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/support/x%3Burl=foo/", "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f" - ], - "type": "library", - "version": "50.3.2" + ] } ], "dependencies": [ @@ -65,9 +70,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -78,8 +80,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.xml.bin index d95e4d04e..0d934e19f 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_v16_fields-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.1.xml.bin index ba1ca960c..dc7416908 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.json.bin index b96615dbe..1ee76cddb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.xml.bin index bb9597137..a1b7b3385 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.json.bin index 3437dbb74..a761402a4 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,11 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.xml.bin index 49ba0ae39..6a28cad36 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.json.bin index b020f6c8c..87deae725 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,78 +26,119 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { - "advisories": [ + "bom-ref": "my-vuln-ref-1", + "id": "CVE-2018-7489", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "references": [ { - "url": "http://www.securitytracker.com/id/1040693" + "id": "SOME-OTHER-ID", + "source": { + "name": "OSS Index", + "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" + } + } + ], + "ratings": [ + { + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv3", + "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "justification": "Some justification" }, { - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + "source": { + "name": "OWASP", + "url": "https://owasp.org" + }, + "score": 2.7, + "severity": "low", + "method": "CVSSv3", + "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N", + "justification": "Some other justification" } ], - "affects": [ + "cwes": [ + 22, + 33 + ], + "description": "A description here", + "detail": "Some detail here", + "recommendation": "Upgrade", + "advisories": [ { - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "versions": [ - { - "range": "49.0.0 - 54.0.0", - "status": "affected" - } - ] + "url": "http://www.securitytracker.com/id/1040693" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" } ], - "analysis": { - "detail": "Some extra detail", - "justification": "requires_environment", - "response": [ - "can_not_fix" - ], - "state": "exploitable" - }, - "bom-ref": "my-vuln-ref-1", "created": "2021-09-01T10:50:42.051979+00:00", + "published": "2021-09-02T10:50:42.051979+00:00", + "updated": "2021-09-03T10:50:42.051979+00:00", "credits": { - "individuals": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], "organizations": [ { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] } + ], + "individuals": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } ] }, - "cwes": [ - 22, - 33 + "tools": [ + { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib" + } + ], + "analysis": { + "state": "exploitable", + "justification": "requires_environment", + "response": [ + "can_not_fix" + ], + "detail": "Some extra detail" + }, + "affects": [ + { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "versions": [ + { + "range": "49.0.0 - 54.0.0", + "status": "affected" + } + ] + } ], - "description": "A description here", - "detail": "Some detail here", - "id": "CVE-2018-7489", "properties": [ { "name": "key1", @@ -102,53 +148,7 @@ "name": "key2", "value": "val2" } - ], - "published": "2021-09-02T10:50:42.051979+00:00", - "ratings": [ - { - "justification": "Some justification", - "method": "CVSSv3", - "score": 9.8, - "severity": "critical", - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" - }, - { - "justification": "Some other justification", - "method": "CVSSv3", - "score": 2.7, - "severity": "low", - "source": { - "name": "OWASP", - "url": "https://owasp.org" - }, - "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N" - } - ], - "recommendation": "Upgrade", - "references": [ - { - "id": "SOME-OTHER-ID", - "source": { - "name": "OSS Index", - "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" - } - } - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "tools": [ - { - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX" - } - ], - "updated": "2021-09-03T10:50:42.051979+00:00" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.xml.bin index 554039f1a..c41469d1b 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.json.bin index 14b92331b..a70546396 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,77 +36,122 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { - "advisories": [ + "bom-ref": "my-vuln-ref-1", + "id": "CVE-2018-7489", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "references": [ { - "url": "http://www.securitytracker.com/id/1040693" + "id": "SOME-OTHER-ID", + "source": { + "name": "OSS Index", + "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" + } + } + ], + "ratings": [ + { + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv3", + "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "justification": "Some justification" }, { - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + "source": { + "name": "OWASP", + "url": "https://owasp.org" + }, + "score": 2.7, + "severity": "low", + "method": "CVSSv3", + "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N", + "justification": "Some other justification" } ], - "affects": [ + "cwes": [ + 22, + 33 + ], + "description": "A description here", + "detail": "Some detail here", + "recommendation": "Upgrade", + "workaround": "Describe the workarounds here", + "advisories": [ { - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "versions": [ - { - "range": "49.0.0 - 54.0.0", - "status": "affected" - } - ] + "url": "http://www.securitytracker.com/id/1040693" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" } ], - "analysis": { - "detail": "Some extra detail", - "firstIssued": "2018-09-01T10:50:42.051979+00:00", - "justification": "requires_environment", - "lastUpdated": "2018-09-01T10:50:42.051979+00:00", - "response": [ - "can_not_fix" - ], - "state": "exploitable" - }, - "bom-ref": "my-vuln-ref-1", "created": "2021-09-01T10:50:42.051979+00:00", + "published": "2021-09-02T10:50:42.051979+00:00", + "updated": "2021-09-03T10:50:42.051979+00:00", "credits": { - "individuals": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], "organizations": [ { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] } + ], + "individuals": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } ] }, - "cwes": [ - 22, - 33 + "tools": [ + { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib" + } + ], + "analysis": { + "state": "exploitable", + "justification": "requires_environment", + "response": [ + "can_not_fix" + ], + "detail": "Some extra detail", + "firstIssued": "2018-09-01T10:50:42.051979+00:00", + "lastUpdated": "2018-09-01T10:50:42.051979+00:00" + }, + "affects": [ + { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "versions": [ + { + "range": "49.0.0 - 54.0.0", + "status": "affected" + } + ] + } ], - "description": "A description here", - "detail": "Some detail here", - "id": "CVE-2018-7489", "properties": [ { "name": "key1", @@ -114,54 +161,7 @@ "name": "key2", "value": "val2" } - ], - "published": "2021-09-02T10:50:42.051979+00:00", - "ratings": [ - { - "justification": "Some justification", - "method": "CVSSv3", - "score": 9.8, - "severity": "critical", - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" - }, - { - "justification": "Some other justification", - "method": "CVSSv3", - "score": 2.7, - "severity": "low", - "source": { - "name": "OWASP", - "url": "https://owasp.org" - }, - "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N" - } - ], - "recommendation": "Upgrade", - "references": [ - { - "id": "SOME-OTHER-ID", - "source": { - "name": "OSS Index", - "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" - } - } - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "tools": [ - { - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX" - } - ], - "updated": "2021-09-03T10:50:42.051979+00:00", - "workaround": "Describe the workarounds here" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.xml.bin index 09e41d349..5c96b82be 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.json.bin index 69742402e..d9f243f4f 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,83 +36,128 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { - "advisories": [ + "bom-ref": "my-vuln-ref-1", + "id": "CVE-2018-7489", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "references": [ { - "url": "http://www.securitytracker.com/id/1040693" + "id": "SOME-OTHER-ID", + "source": { + "name": "OSS Index", + "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" + } + } + ], + "ratings": [ + { + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv3", + "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "justification": "Some justification" }, { - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + "source": { + "name": "OWASP", + "url": "https://owasp.org" + }, + "score": 2.7, + "severity": "low", + "method": "CVSSv3", + "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N", + "justification": "Some other justification" } ], - "affects": [ + "cwes": [ + 22, + 33 + ], + "description": "A description here", + "detail": "Some detail here", + "recommendation": "Upgrade", + "workaround": "Describe the workarounds here", + "advisories": [ { - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "versions": [ - { - "range": "49.0.0 - 54.0.0", - "status": "affected" - } - ] + "url": "http://www.securitytracker.com/id/1040693" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" } ], - "analysis": { - "detail": "Some extra detail", - "firstIssued": "2018-09-01T10:50:42.051979+00:00", - "justification": "requires_environment", - "lastUpdated": "2018-09-01T10:50:42.051979+00:00", - "response": [ - "can_not_fix" - ], - "state": "exploitable" - }, - "bom-ref": "my-vuln-ref-1", "created": "2021-09-01T10:50:42.051979+00:00", + "published": "2021-09-02T10:50:42.051979+00:00", + "updated": "2021-09-03T10:50:42.051979+00:00", "credits": { - "individuals": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], "organizations": [ { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] } + ], + "individuals": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } ] }, - "cwes": [ - 22, - 33 + "tools": [ + { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib" + } + ], + "analysis": { + "state": "exploitable", + "justification": "requires_environment", + "response": [ + "can_not_fix" + ], + "detail": "Some extra detail", + "firstIssued": "2018-09-01T10:50:42.051979+00:00", + "lastUpdated": "2018-09-01T10:50:42.051979+00:00" + }, + "affects": [ + { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "versions": [ + { + "range": "49.0.0 - 54.0.0", + "status": "affected" + } + ] + } ], - "description": "A description here", - "detail": "Some detail here", - "id": "CVE-2018-7489", "properties": [ { "name": "key1", @@ -120,54 +167,7 @@ "name": "key2", "value": "val2" } - ], - "published": "2021-09-02T10:50:42.051979+00:00", - "ratings": [ - { - "justification": "Some justification", - "method": "CVSSv3", - "score": 9.8, - "severity": "critical", - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" - }, - { - "justification": "Some other justification", - "method": "CVSSv3", - "score": 2.7, - "severity": "low", - "source": { - "name": "OWASP", - "url": "https://owasp.org" - }, - "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N" - } - ], - "recommendation": "Upgrade", - "references": [ - { - "id": "SOME-OTHER-ID", - "source": { - "name": "OSS Index", - "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" - } - } - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "tools": [ - { - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX" - } - ], - "updated": "2021-09-03T10:50:42.051979+00:00", - "workaround": "Describe the workarounds here" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.xml.bin index 36cb8aa04..5151578bd 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.json.bin index 176d775f2..9abe24dfb 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,10 +18,7 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], "dependencies": [ @@ -21,9 +26,6 @@ "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -34,83 +36,128 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "vulnerabilities": [ { - "advisories": [ + "bom-ref": "my-vuln-ref-1", + "id": "CVE-2018-7489", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "references": [ { - "url": "http://www.securitytracker.com/id/1040693" + "id": "SOME-OTHER-ID", + "source": { + "name": "OSS Index", + "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" + } + } + ], + "ratings": [ + { + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + }, + "score": 9.8, + "severity": "critical", + "method": "CVSSv3", + "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H", + "justification": "Some justification" }, { - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" + "source": { + "name": "OWASP", + "url": "https://owasp.org" + }, + "score": 2.7, + "severity": "low", + "method": "CVSSv3", + "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N", + "justification": "Some other justification" } ], - "affects": [ + "cwes": [ + 22, + 33 + ], + "description": "A description here", + "detail": "Some detail here", + "recommendation": "Upgrade", + "workaround": "Describe the workarounds here", + "advisories": [ { - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "versions": [ - { - "range": "49.0.0 - 54.0.0", - "status": "affected" - } - ] + "url": "http://www.securitytracker.com/id/1040693" + }, + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" } ], - "analysis": { - "detail": "Some extra detail", - "firstIssued": "2018-09-01T10:50:42.051979+00:00", - "justification": "requires_environment", - "lastUpdated": "2018-09-01T10:50:42.051979+00:00", - "response": [ - "can_not_fix" - ], - "state": "exploitable" - }, - "bom-ref": "my-vuln-ref-1", "created": "2021-09-01T10:50:42.051979+00:00", + "published": "2021-09-02T10:50:42.051979+00:00", + "updated": "2021-09-03T10:50:42.051979+00:00", "credits": { - "individuals": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - } - ], "organizations": [ { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] } + ], + "individuals": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + } ] }, - "cwes": [ - 22, - 33 + "tools": [ + { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib" + } + ], + "analysis": { + "state": "exploitable", + "justification": "requires_environment", + "response": [ + "can_not_fix" + ], + "detail": "Some extra detail", + "firstIssued": "2018-09-01T10:50:42.051979+00:00", + "lastUpdated": "2018-09-01T10:50:42.051979+00:00" + }, + "affects": [ + { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "versions": [ + { + "range": "49.0.0 - 54.0.0", + "status": "affected" + } + ] + } ], - "description": "A description here", - "detail": "Some detail here", - "id": "CVE-2018-7489", "properties": [ { "name": "key1", @@ -120,54 +167,7 @@ "name": "key2", "value": "val2" } - ], - "published": "2021-09-02T10:50:42.051979+00:00", - "ratings": [ - { - "justification": "Some justification", - "method": "CVSSv3", - "score": 9.8, - "severity": "critical", - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "vector": "AN/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" - }, - { - "justification": "Some other justification", - "method": "CVSSv3", - "score": 2.7, - "severity": "low", - "source": { - "name": "OWASP", - "url": "https://owasp.org" - }, - "vector": "AV:L/AC:H/PR:N/UI:R/S:C/C:L/I:N/A:N" - } - ], - "recommendation": "Upgrade", - "references": [ - { - "id": "SOME-OTHER-ID", - "source": { - "name": "OSS Index", - "url": "https://ossindex.sonatype.org/component/pkg:pypi/setuptools" - } - } - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-7489" - }, - "tools": [ - { - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX" - } - ], - "updated": "2021-09-03T10:50:42.051979+00:00", - "workaround": "Describe the workarounds here" + ] } ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", diff --git a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.xml.bin index 503b2feb0..bf3196b2a 100644 --- a/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_setuptools_with_vulnerability-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.1.xml.bin index 7f5932c19..6824550bf 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.1.xml.bin @@ -1,5 +1,5 @@ - + toml @@ -8,6 +8,7 @@ 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b pkg:pypi/toml@0.10.2?extension=tar.gz + false https://cyclonedx.org diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.json.bin index a362876ff..8332ba158 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.json.bin @@ -1,24 +1,29 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "dependencies": [ @@ -26,11 +31,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.xml.bin index 12d7e32f5..b37166c17 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.json.bin index f8a990bf3..4ce1b9ef8 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -32,11 +37,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.xml.bin index 1d15dde2f..9ebbaf0d6 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.json.bin index 949596a51..8088b5f38 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -32,11 +37,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.xml.bin index 4c67af37e..647df6339 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.json.bin index 1771c7654..0bc270578 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -32,9 +37,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.xml.bin index 154f20fcb..eff02e80b 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.json.bin index f4fc5c119..5655d79a4 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -32,9 +37,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.xml.bin index 23a587b2b..42315b2cd 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.json.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.json.bin index 995cb2698..6c63366ab 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.json.bin @@ -1,30 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -32,9 +37,6 @@ "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -45,8 +47,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.xml.bin index 3fd0e044b..c94471be6 100644 --- a/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_component_toml_1-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.json.bin index 48f1745d1..39ff065e8 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.xml.bin index d0a7d4c90..013ff9521 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.json.bin index 57b5e590e..7ee9568a7 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.xml.bin index f952637cf..9789b0d42 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.json.bin index 21195512d..570fbf29d 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.json.bin @@ -1,36 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], "definitions": { "standards": [ { "bom-ref": "other-standard", - "description": "Other description", - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "levels": [ - { - "bom-ref": "lvl-3", - "description": "Level 3 description", - "identifier": "LVL-3", - "requirements": [ - "req-3" - ], - "title": "Level 3" - } - ], "name": "Other Standard", + "version": "1.0.0", + "description": "Other description", "owner": "Other Owner", "requirements": [ { "bom-ref": "req-3", + "identifier": "REQ-3", + "title": "Requirement 3", + "text": "some requirement text", "descriptions": [ "Requirement 3 described here", "and here" ], - "identifier": "REQ-3", "openCre": [ "CRE:5-6", "CRE:7-8" @@ -40,63 +41,43 @@ "name": "key3", "value": "val3" } - ], - "text": "some requirement text", - "title": "Requirement 3" - } - ], - "version": "1.0.0" - }, - { - "bom-ref": "some-standard", - "description": "Some description", - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } ], "levels": [ { - "bom-ref": "lvl-1", - "description": "Level 1 description", - "identifier": "LVL-1", - "title": "Level 1" - }, - { - "bom-ref": "lvl-2", - "description": "Level 2 description", - "identifier": "LVL-2", + "bom-ref": "lvl-3", + "identifier": "LVL-3", + "title": "Level 3", + "description": "Level 3 description", "requirements": [ - "req-1", - "req-2" - ], - "title": "Level 2" + "req-3" + ] } ], + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] + }, + { + "bom-ref": "some-standard", "name": "Some Standard", + "version": "1.2.3", + "description": "Some description", "owner": "Some Owner", "requirements": [ { "bom-ref": "req-1", + "identifier": "REQ-1", + "title": "Requirement 1", + "text": "some requirement text", "descriptions": [ "Requirement 1 described here", "and here" ], - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "identifier": "REQ-1", "openCre": [ "CRE:1-2" ], @@ -110,15 +91,21 @@ "value": "val1b" } ], - "text": "some requirement text", - "title": "Requirement 1" + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] }, { "bom-ref": "req-2", + "identifier": "REQ-2", + "title": "Requirement 2", + "text": "some requirement text", "descriptions": [ "Requirement 2 described here" ], - "identifier": "REQ-2", "openCre": [ "CRE:1-2", "CRE:3-4" @@ -129,30 +116,43 @@ "name": "key2", "value": "val2" } - ], - "text": "some requirement text", - "title": "Requirement 2" + ] + } + ], + "levels": [ + { + "bom-ref": "lvl-1", + "identifier": "LVL-1", + "title": "Level 1", + "description": "Level 1 description" + }, + { + "bom-ref": "lvl-2", + "identifier": "LVL-2", + "title": "Level 2", + "description": "Level 2 description", + "requirements": [ + "req-1", + "req-2" + ] } ], - "version": "1.2.3" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.xml.bin index 3e6a145e0..a04bf1638 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.json.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.json.bin index 453cb3e1d..95b0c7952 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.json.bin @@ -1,36 +1,37 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], "definitions": { "standards": [ { "bom-ref": "other-standard", - "description": "Other description", - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "levels": [ - { - "bom-ref": "lvl-3", - "description": "Level 3 description", - "identifier": "LVL-3", - "requirements": [ - "req-3" - ], - "title": "Level 3" - } - ], "name": "Other Standard", + "version": "1.0.0", + "description": "Other description", "owner": "Other Owner", "requirements": [ { "bom-ref": "req-3", + "identifier": "REQ-3", + "title": "Requirement 3", + "text": "some requirement text", "descriptions": [ "Requirement 3 described here", "and here" ], - "identifier": "REQ-3", "openCre": [ "CRE:5-6", "CRE:7-8" @@ -40,63 +41,43 @@ "name": "key3", "value": "val3" } - ], - "text": "some requirement text", - "title": "Requirement 3" - } - ], - "version": "1.0.0" - }, - { - "bom-ref": "some-standard", - "description": "Some description", - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } ], "levels": [ { - "bom-ref": "lvl-1", - "description": "Level 1 description", - "identifier": "LVL-1", - "title": "Level 1" - }, - { - "bom-ref": "lvl-2", - "description": "Level 2 description", - "identifier": "LVL-2", + "bom-ref": "lvl-3", + "identifier": "LVL-3", + "title": "Level 3", + "description": "Level 3 description", "requirements": [ - "req-1", - "req-2" - ], - "title": "Level 2" + "req-3" + ] } ], + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] + }, + { + "bom-ref": "some-standard", "name": "Some Standard", + "version": "1.2.3", + "description": "Some description", "owner": "Some Owner", "requirements": [ { "bom-ref": "req-1", + "identifier": "REQ-1", + "title": "Requirement 1", + "text": "some requirement text", "descriptions": [ "Requirement 1 described here", "and here" ], - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "identifier": "REQ-1", "openCre": [ "CRE:1-2" ], @@ -110,15 +91,21 @@ "value": "val1b" } ], - "text": "some requirement text", - "title": "Requirement 1" + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] }, { "bom-ref": "req-2", + "identifier": "REQ-2", + "title": "Requirement 2", + "text": "some requirement text", "descriptions": [ "Requirement 2 described here" ], - "identifier": "REQ-2", "openCre": [ "CRE:1-2", "CRE:3-4" @@ -129,30 +116,43 @@ "name": "key2", "value": "val2" } - ], - "text": "some requirement text", - "title": "Requirement 2" + ] + } + ], + "levels": [ + { + "bom-ref": "lvl-1", + "identifier": "LVL-1", + "title": "Level 1", + "description": "Level 1 description" + }, + { + "bom-ref": "lvl-2", + "identifier": "LVL-2", + "title": "Level 2", + "description": "Level 2 description", + "requirements": [ + "req-1", + "req-2" + ] } ], - "version": "1.2.3" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] } ] }, - "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.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.xml.bin index 4ea59f611..fcd8ca878 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_and_detailed_standards-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.json.bin index 8f473bd3a..819255b3b 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.xml.bin index df1938ec0..cd45a0833 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.json.bin index 02943890a..296d338fb 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.xml.bin index 8341ff600..1bbb3e29e 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.json.bin index 48f1745d1..39ff065e8 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.json.bin @@ -1,9 +1,9 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.xml.bin index d0a7d4c90..013ff9521 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.json.bin index 57b5e590e..7ee9568a7 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.json.bin @@ -1,4 +1,6 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -12,8 +14,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.xml.bin index f952637cf..9789b0d42 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.json.bin index 9fba8848b..bbe05c07f 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.json.bin @@ -1,21 +1,6 @@ { - "definitions": { - "standards": [ - { - "bom-ref": "some-standard", - "description": "Some description", - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "name": "Some Standard", - "owner": "Some Owner", - "version": "1.2.3" - } - ] - }, + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -29,8 +14,23 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "definitions": { + "standards": [ + { + "bom-ref": "some-standard", + "name": "Some Standard", + "version": "1.2.3", + "description": "Some description", + "owner": "Some Owner", + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] + } + ] + }, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.xml.bin index b983bdf65..aca268ee1 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.json.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.json.bin index 57c9cc0da..8ddcf9e6f 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.json.bin @@ -1,21 +1,6 @@ { - "definitions": { - "standards": [ - { - "bom-ref": "some-standard", - "description": "Some description", - "externalReferences": [ - { - "type": "website", - "url": "https://cyclonedx.org" - } - ], - "name": "Some Standard", - "owner": "Some Owner", - "version": "1.2.3" - } - ] - }, + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00" }, @@ -29,8 +14,23 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "definitions": { + "standards": [ + { + "bom-ref": "some-standard", + "name": "Some Standard", + "version": "1.2.3", + "description": "Some description", + "owner": "Some Owner", + "externalReferences": [ + { + "type": "website", + "url": "https://cyclonedx.org" + } + ] + } + ] + }, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.xml.bin index 88a31730b..ecbcf1994 100644 --- a/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_definitions_standards-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.1.xml.bin index 2a2038c30..bd700cc5f 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false toml @@ -18,6 +19,7 @@ 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b pkg:pypi/toml@0.10.2?extension=tar.gz + false https://cyclonedx.org diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.json.bin index f968a483e..c08a2b149 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.json.bin @@ -1,8 +1,22 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component", + "version": "" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,30 +24,27 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "dependencies": [ @@ -41,26 +52,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.xml.bin index b85b5dd21..68545e6d5 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.json.bin index 190f444c2..164d41dd1 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.json.bin @@ -1,8 +1,22 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component", + "version": "" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,36 +24,33 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -47,26 +58,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.xml.bin index 504eb1969..ff6effbeb 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.json.bin index e0cde06a2..148db7883 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.json.bin @@ -1,8 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,36 +23,33 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -47,25 +57,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.xml.bin index a5860bce4..a0f550534 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.json.bin index 3d8b8f31a..7c85cc013 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.json.bin @@ -1,8 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,36 +23,33 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -47,23 +57,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -74,8 +76,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.xml.bin index 8d72d8b6d..076bd4f51 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.json.bin index 5e2a7641f..a406bb0c7 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.json.bin @@ -1,8 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,36 +23,33 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -47,23 +57,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -74,8 +76,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.xml.bin index 2ae2aa9dd..1c87a9275 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.json.bin index e720662e0..051b9eb5a 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.json.bin @@ -1,8 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 23, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "rootComponent", + "type": "application", + "bom-ref": "root-component" + } + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "setuptools", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,36 +23,33 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "toml", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": [ @@ -47,23 +57,15 @@ "ref": "root-component" }, { + "ref": "setuptools", "dependsOn": [ "toml" - ], - "ref": "setuptools" + ] }, { "ref": "toml" } ], - "metadata": { - "component": { - "bom-ref": "root-component", - "name": "rootComponent", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -74,8 +76,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 23, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.xml.bin index 94379059c..9a750a310 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_hanging-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.1.xml.bin index 9d446f67d..56b67ac4c 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.1.xml.bin @@ -1,5 +1,5 @@ - + setuptools @@ -10,6 +10,7 @@ pkg:pypi/setuptools@50.3.2?extension=tar.gz + false toml @@ -18,6 +19,7 @@ 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b pkg:pypi/toml@0.10.2?extension=tar.gz + false https://cyclonedx.org diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.json.bin index 1782df19c..d0afd9697 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,48 +18,40 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "externalReferences": [ - { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "dependencies": [ { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.xml.bin index b3cd329b3..8e00c174f 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.json.bin index 92977fde4..4a572565d 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,54 +18,46 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.xml.bin index ba7c59ac0..5a664b6d3 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.json.bin index 2d2e250f1..c0249fbe9 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,54 +18,46 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.xml.bin index 92e6747aa..b63ce8327 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.json.bin index 89bd86c2a..4b6e98c7d 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,52 +18,46 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.xml.bin index 6ddad73d2..3307533ec 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.json.bin index 7717cb174..17d5a448d 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,52 +18,46 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.xml.bin index ad60777c0..22b39183b 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.json.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.json.bin index 157eed17a..3430667ee 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.json.bin @@ -1,8 +1,16 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "components": [ { - "author": "Test Author", + "name": "setuptools", + "type": "library", "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", "licenses": [ { "license": { @@ -10,52 +18,46 @@ } } ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" }, { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.xml.bin index 08f4a82e2..2714bd79b 100644 --- a/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_dependencies_valid-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.json.bin index 18150abd0..a362483a7 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.json.bin @@ -1,20 +1,20 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-app", "name": "app", "type": "application", + "bom-ref": "my-app", "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-app" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.xml.bin index 5fb21515b..65b5954c2 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.json.bin index fd64f1450..6ddd79a8d 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.json.bin @@ -1,20 +1,20 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-app", "name": "app", "type": "application", + "bom-ref": "my-app", "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-app" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.xml.bin index 7bb6d933a..3a9fc5f34 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.json.bin index 199835665..d51dd74cd 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.json.bin @@ -1,19 +1,19 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } + }, "dependencies": [ { "ref": "my-app" } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "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" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.xml.bin index 118c192fd..278aa7739 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.json.bin index c37c40f30..2fb3034c0 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.json.bin @@ -1,17 +1,19 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } + }, "dependencies": [ { "ref": "my-app" } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -22,8 +24,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.xml.bin index 77a416bc8..1335a9256 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.json.bin index 7085323c1..6eb16fddd 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.json.bin @@ -1,17 +1,19 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } + }, "dependencies": [ { "ref": "my-app" } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "type": "application" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -22,8 +24,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.xml.bin index d8276254c..949ed7397 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.json.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.json.bin index ae96fe14c..629a4a830 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.json.bin @@ -1,20 +1,22 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-app", "name": "app", - "type": "application" + "type": "application", + "bom-ref": "my-app" }, "distributionConstraints": { "tlp": "AMBER_AND_STRICT" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, + "dependencies": [ + { + "ref": "my-app" + } + ], "properties": [ { "name": "key1", @@ -25,8 +27,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.xml.bin index 2167d67f4..72af629dd 100644 --- a/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_distribution_constraints-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.1.xml.bin index b7b31df00..0d66e6f84 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.1.xml.bin @@ -1,5 +1,5 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.2.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.2.json.bin index 0e507a443..602b4b154 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.2.json.bin @@ -1,9 +1,14 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { - "comment": "No comment", "type": "distribution", - "url": "https://cyclonedx.org" + "url": "https://cyclonedx.org", + "comment": "No comment" }, { "type": "vcs", @@ -14,11 +19,6 @@ "url": "https://cyclonedx.org" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.2.xml.bin index 4fba839e9..a43a38032 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.3.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.3.json.bin index 3e793c509..d1b9ccfd3 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.3.json.bin @@ -1,15 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] }, { "type": "vcs", @@ -20,11 +25,6 @@ "url": "https://cyclonedx.org" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.3.xml.bin index 13a9e149f..2f7f87bda 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.4.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.4.json.bin index 43fbfa6de..83ed4c16c 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.4.json.bin @@ -1,15 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] }, { "type": "vcs", @@ -20,11 +25,6 @@ "url": "https://cyclonedx.org" } ], - "metadata": { - "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" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.4.xml.bin index 7889bb9d4..0c17a3fbf 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.5.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.5.json.bin index 52a6c19d9..2dbdefd2c 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.5.json.bin @@ -1,15 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] }, { "type": "vcs", @@ -20,9 +25,6 @@ "url": "https://cyclonedx.org" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -33,8 +35,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.5.xml.bin index 1a6c87b14..258ef85a2 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.6.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.6.json.bin index 050afd045..b8eee09aa 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.6.json.bin @@ -1,15 +1,20 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] }, { "type": "vcs", @@ -20,9 +25,6 @@ "url": "https://cyclonedx.org" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -33,8 +35,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.6.xml.bin index 6216a6d33..8f1b22354 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.7.json.bin b/tests/_data/snapshots/get_bom_with_external_references-1.7.json.bin index ebeb80240..7934fd6a0 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.7.json.bin @@ -1,17 +1,24 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00" + }, "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] }, { + "type": "vcs", + "url": "https://cyclonedx.org", "properties": [ { "name": "property_1", @@ -21,18 +28,13 @@ "name": "property_2", "value": "value_2" } - ], - "type": "vcs", - "url": "https://cyclonedx.org" + ] }, { "type": "website", "url": "https://cyclonedx.org" } ], - "metadata": { - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -43,8 +45,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_external_references-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_external_references-1.7.xml.bin index dcf64c052..7d98a217d 100644 --- a/tests/_data/snapshots/get_bom_with_external_references-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_external_references-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.1.xml.bin index e6f6adcaa..f57903ccf 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.1.xml.bin @@ -1,5 +1,5 @@ - + c-with-SPDX @@ -10,6 +10,7 @@ https://www.apache.org/licenses/LICENSE-2.0.html + false c-with-expression @@ -17,6 +18,7 @@ Apache-2.0 OR MIT + false c-with-name @@ -31,6 +33,7 @@ this is a license text + false diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.2.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.2.json.bin index c88a0812a..ee4547ffc 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.2.json.bin @@ -1,7 +1,28 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "version": "", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + } + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", + "version": "", "licenses": [ { "license": { @@ -9,24 +30,24 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "c-with-SPDX", - "type": "library", - "version": "" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", + "version": "", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "c-with-expression", - "type": "library", - "version": "" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", + "version": "", "licenses": [ { "license": { @@ -46,54 +67,12 @@ } } } - ], - "name": "c-with-name", - "type": "library", - "version": "" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { @@ -102,19 +81,19 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -135,11 +114,32 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.2.xml.bin index 996e5716f..5316cacfa 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.3.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.3.json.bin index a5407c588..912c50523 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.3.json.bin @@ -1,7 +1,35 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "version": "", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + }, + "licenses": [ + { + "license": { + "id": "CC-BY-1.0" + } + } + ] + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", + "version": "", "licenses": [ { "license": { @@ -9,24 +37,24 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "c-with-SPDX", - "type": "library", - "version": "" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", + "version": "", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "c-with-expression", - "type": "library", - "version": "" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", + "version": "", "licenses": [ { "license": { @@ -46,61 +74,12 @@ } } } - ], - "name": "c-with-name", - "type": "library", - "version": "" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application", - "version": "" - }, - "licenses": [ - { - "license": { - "id": "CC-BY-1.0" - } - } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { @@ -109,19 +88,19 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -142,11 +121,32 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.3.xml.bin index 1b53ee51e..07292c0e3 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.4.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.4.json.bin index a082d8a3d..36ac55ab4 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.4.json.bin @@ -1,6 +1,32 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + }, + "licenses": [ + { + "license": { + "id": "CC-BY-1.0" + } + } + ] + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", "licenses": [ { @@ -9,21 +35,21 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "c-with-SPDX", - "type": "library" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "c-with-expression", - "type": "library" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", "licenses": [ { @@ -44,59 +70,12 @@ } } } - ], - "name": "c-with-name", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" + ] } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application" - }, - "licenses": [ - { - "license": { - "id": "CC-BY-1.0" - } - } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { @@ -105,19 +84,19 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -138,11 +117,32 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.4.xml.bin index 6d81479e8..c77c66877 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.5.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.5.json.bin index a8b28b10a..cfa1decd3 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.5.json.bin @@ -1,6 +1,32 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + }, + "licenses": [ + { + "license": { + "id": "CC-BY-1.0" + } + } + ] + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", "licenses": [ { @@ -9,21 +35,21 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "c-with-SPDX", - "type": "library" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "c-with-expression", - "type": "library" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", "licenses": [ { @@ -44,69 +70,12 @@ } } } - ], - "name": "c-with-name", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" - } - ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application" - }, - "licenses": [ - { - "license": { - "id": "CC-BY-1.0" - } - } - ], - "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", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { @@ -115,19 +84,19 @@ "url": "https://www.apache.org/licenses/LICENSE-2.0.html" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { "expression": "Apache-2.0 OR MIT" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -148,11 +117,42 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.5.xml.bin index fc2bedfd2..a4955873f 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.6.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.6.json.bin index 4e6ef33ff..75db29dff 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.6.json.bin @@ -1,31 +1,57 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + }, + "licenses": [ + { + "license": { + "id": "CC-BY-1.0" + } + } + ] + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", "licenses": [ { "license": { - "acknowledgement": "concluded", "id": "Apache-2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + "acknowledgement": "concluded" } } - ], - "name": "c-with-SPDX", - "type": "library" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", "licenses": [ { - "acknowledgement": "concluded", - "expression": "Apache-2.0 OR MIT" + "expression": "Apache-2.0 OR MIT", + "acknowledgement": "concluded" } - ], - "name": "c-with-expression", - "type": "library" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", "licenses": [ { @@ -46,92 +72,35 @@ } } } - ], - "name": "c-with-name", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" - } - ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application" - }, - "licenses": [ - { - "license": { - "id": "CC-BY-1.0" - } - } - ], - "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", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { "license": { - "acknowledgement": "declared", "id": "Apache-2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + "acknowledgement": "declared" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { - "acknowledgement": "declared", - "expression": "Apache-2.0 OR MIT" + "expression": "Apache-2.0 OR MIT", + "acknowledgement": "declared" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -152,11 +121,42 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.6.xml.bin index 49b31f469..0418bb0e3 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.7.json.bin b/tests/_data/snapshots/get_bom_with_licenses-1.7.json.bin index f095a4692..7378419d0 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.7.json.bin @@ -1,31 +1,57 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "licenses": [ + { + "license": { + "name": "proprietary" + } + } + ] + }, + "licenses": [ + { + "license": { + "id": "CC-BY-1.0" + } + } + ] + }, "components": [ { + "name": "c-with-SPDX", + "type": "library", "bom-ref": "C2", "licenses": [ { "license": { - "acknowledgement": "concluded", "id": "Apache-2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + "acknowledgement": "concluded" } } - ], - "name": "c-with-SPDX", - "type": "library" + ] }, { + "name": "c-with-expression", + "type": "library", "bom-ref": "C1", "licenses": [ { - "acknowledgement": "concluded", - "expression": "Apache-2.0 OR MIT" + "expression": "Apache-2.0 OR MIT", + "acknowledgement": "concluded" } - ], - "name": "c-with-expression", - "type": "library" + ] }, { + "name": "c-with-name", + "type": "library", "bom-ref": "C3", "licenses": [ { @@ -46,92 +72,35 @@ } } } - ], - "name": "c-with-name", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "C1" - }, - { - "ref": "C2" - }, - { - "ref": "C3" - }, - { - "ref": "S1" - }, - { - "ref": "S2" - }, - { - "ref": "S3" - }, - { - "ref": "my-app" - } - ], - "metadata": { - "component": { - "bom-ref": "my-app", - "licenses": [ - { - "license": { - "name": "proprietary" - } - } - ], - "name": "app", - "type": "application" - }, - "licenses": [ - { - "license": { - "id": "CC-BY-1.0" - } - } - ], - "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", "services": [ { + "name": "s-with-SPDX", "bom-ref": "S2", "licenses": [ { "license": { - "acknowledgement": "declared", "id": "Apache-2.0", - "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + "acknowledgement": "declared" } } - ], - "name": "s-with-SPDX" + ] }, { + "name": "s-with-expression", "bom-ref": "S1", "licenses": [ { - "acknowledgement": "declared", - "expression": "Apache-2.0 OR MIT" + "expression": "Apache-2.0 OR MIT", + "acknowledgement": "declared" } - ], - "name": "s-with-expression" + ] }, { + "name": "s-with-name", "bom-ref": "S3", "licenses": [ { @@ -152,11 +121,42 @@ } } } - ], - "name": "s-with-name" + ] + } + ], + "dependencies": [ + { + "ref": "C1" + }, + { + "ref": "C2" + }, + { + "ref": "C3" + }, + { + "ref": "S1" + }, + { + "ref": "S2" + }, + { + "ref": "S3" + }, + { + "ref": "my-app" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_licenses-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_licenses-1.7.xml.bin index b9e91e6db..0a331d4b6 100644 --- a/tests/_data/snapshots/get_bom_with_licenses-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_licenses-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.2.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.2.json.bin index 18150abd0..a362483a7 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.2.json.bin @@ -1,20 +1,20 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-app", "name": "app", "type": "application", + "bom-ref": "my-app", "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-app" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.2.xml.bin index 5fb21515b..65b5954c2 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.3.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.3.json.bin index fd64f1450..6ddd79a8d 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.3.json.bin @@ -1,20 +1,20 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-app", "name": "app", "type": "application", + "bom-ref": "my-app", "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, + "dependencies": [ + { + "ref": "my-app" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.3.xml.bin index 7bb6d933a..3a9fc5f34 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.4.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.4.json.bin index 199835665..d51dd74cd 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.4.json.bin @@ -1,19 +1,19 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } + }, "dependencies": [ { "ref": "my-app" } ], - "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "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" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.4.xml.bin index 118c192fd..278aa7739 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.5.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.5.json.bin index fca2c94b0..e664e3b33 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.5.json.bin @@ -1,15 +1,8 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "type": "application" - }, + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -18,12 +11,21 @@ "phase": "post-build" }, { - "description": "Integration testing specific to the runtime platform", - "name": "platform-integration-testing" + "name": "platform-integration-testing", + "description": "Integration testing specific to the runtime platform" } ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } }, + "dependencies": [ + { + "ref": "my-app" + } + ], "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.5.xml.bin index cfa090977..2fb0abdca 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.6.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.6.json.bin index 194bf22f3..be492d34b 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.6.json.bin @@ -1,15 +1,8 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "type": "application" - }, + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -18,12 +11,21 @@ "phase": "post-build" }, { - "description": "Integration testing specific to the runtime platform", - "name": "platform-integration-testing" + "name": "platform-integration-testing", + "description": "Integration testing specific to the runtime platform" } ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } }, + "dependencies": [ + { + "ref": "my-app" + } + ], "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.6.xml.bin index 7ff8cb108..258ccb172 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.7.json.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.7.json.bin index 205d45ae2..0bd9f3b44 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.7.json.bin @@ -1,15 +1,8 @@ { - "dependencies": [ - { - "ref": "my-app" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { - "component": { - "bom-ref": "my-app", - "name": "app", - "type": "application" - }, + "timestamp": "2023-01-07T13:44:32.312678+00:00", "lifecycles": [ { "phase": "build" @@ -18,12 +11,21 @@ "phase": "post-build" }, { - "description": "Integration testing specific to the runtime platform", - "name": "platform-integration-testing" + "name": "platform-integration-testing", + "description": "Integration testing specific to the runtime platform" } ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app" + } }, + "dependencies": [ + { + "ref": "my-app" + } + ], "properties": [ { "name": "key1", @@ -34,8 +36,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_lifecycles-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_lifecycles-1.7.xml.bin index 2fbb8cb79..cab2165bc 100644 --- a/tests/_data/snapshots/get_bom_with_lifecycles-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_lifecycles-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.1.xml.bin index 7f5932c19..6824550bf 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.1.xml.bin @@ -1,5 +1,5 @@ - + toml @@ -8,6 +8,7 @@ 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b pkg:pypi/toml@0.10.2?extension=tar.gz + false https://cyclonedx.org diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.json.bin index e74a252d2..8c72b70ce 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.json.bin @@ -1,57 +1,57 @@ { - "components": [ - { - "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "externalReferences": [ + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" + "license": { + "id": "MIT" + } } ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, + "components": [ + { + "name": "toml", + "type": "library", + "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } ], - "name": "toml", "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", - "type": "library", - "version": "0.10.2" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] } ], "dependencies": [ { + "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.xml.bin index 0e8acf56f..f02fd080b 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.json.bin index 243e776d7..c49075a18 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.json.bin @@ -1,63 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.xml.bin index 92321491e..e97d5f60e 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.json.bin index 0c91fe36a..b5899f748 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.json.bin @@ -1,63 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.xml.bin index 2d8b15f88..aff7270ba 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.json.bin index a72442f93..9ae7198c0 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.json.bin @@ -1,61 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.xml.bin index 4ad5abd7f..8b5099996 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.json.bin index 9aba46268..b4d679b77 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.json.bin @@ -1,61 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.xml.bin index 26e9a1011..d0d2927cb 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.json.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.json.bin index b78d65964..292ca1eb4 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.json.bin @@ -1,61 +1,63 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "setuptools", + "type": "library", + "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", + "author": "Test Author", + "version": "50.3.2", + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + } + }, "components": [ { + "name": "toml", + "type": "library", "bom-ref": "pkg:pypi/toml@0.10.2?extension=tar.gz", + "version": "0.10.2", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ], + "purl": "pkg:pypi/toml@0.10.2?extension=tar.gz", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "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": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", "dependsOn": [ "pkg:pypi/toml@0.10.2?extension=tar.gz" - ], - "ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz" + ] }, { "ref": "pkg:pypi/toml@0.10.2?extension=tar.gz" } ], - "metadata": { - "component": { - "author": "Test Author", - "bom-ref": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "setuptools", - "purl": "pkg:pypi/setuptools@50.3.2?extension=tar.gz", - "type": "library", - "version": "50.3.2" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -66,8 +68,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.xml.bin index ced8a82fe..6c1da06c8 100644 --- a/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_metadata_component_and_dependencies-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.1.xml.bin index 27b2bce0f..be076d795 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.1.xml.bin @@ -1,5 +1,5 @@ - + comp @@ -12,6 +12,7 @@ foo license + false diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.json.bin index 3a40a57c4..d2838e9bf 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.json.bin @@ -1,7 +1,13 @@ { - "components": [ - { - "bom-ref": "my-compo", + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "app", + "type": "application", + "bom-ref": "my-app", + "version": "", "licenses": [ { "license": { @@ -13,26 +19,15 @@ "name": "foo license" } } - ], - "name": "comp", - "type": "library", - "version": "" + ] } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, + }, + "components": [ { - "ref": "my-serv" - } - ], - "metadata": { - "component": { - "bom-ref": "my-app", + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "version": "", "licenses": [ { "license": { @@ -44,16 +39,12 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application", - "version": "" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + ] + } + ], "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -66,11 +57,20 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.xml.bin index 39f4e66bd..fa9b01afe 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.json.bin index 469d49f3d..bbfee9dae 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.json.bin @@ -1,38 +1,13 @@ { - "components": [ - { - "bom-ref": "my-compo", - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "name": "foo license" - } - } - ], - "name": "comp", - "type": "library", - "version": "" - } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, - { - "ref": "my-serv" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { + "name": "app", + "type": "application", "bom-ref": "my-app", + "version": "", "licenses": [ { "license": { @@ -44,10 +19,7 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application", - "version": "" + ] }, "licenses": [ { @@ -60,12 +32,31 @@ "name": "foo license" } } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "components": [ + { + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "version": "", + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "name": "foo license" + } + } + ] + } + ], "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -78,11 +69,20 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.xml.bin index a4a52cfd5..b0bd53e17 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.json.bin index 21df9fed9..634162398 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.json.bin @@ -1,36 +1,11 @@ { - "components": [ - { - "bom-ref": "my-compo", - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "name": "foo license" - } - } - ], - "name": "comp", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, - { - "ref": "my-serv" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { + "name": "app", + "type": "application", "bom-ref": "my-app", "licenses": [ { @@ -43,9 +18,7 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application" + ] }, "licenses": [ { @@ -58,12 +31,30 @@ "name": "foo license" } } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "components": [ + { + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "name": "foo license" + } + } + ] + } + ], "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -76,11 +67,20 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.xml.bin index ee81caf9a..d6271102b 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.json.bin index 134e1f9a6..7144986ef 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.json.bin @@ -1,36 +1,11 @@ { - "components": [ - { - "bom-ref": "my-compo", - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "name": "foo license" - } - } - ], - "name": "comp", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, - { - "ref": "my-serv" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { + "name": "app", + "type": "application", "bom-ref": "my-app", "licenses": [ { @@ -43,9 +18,7 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application" + ] }, "licenses": [ { @@ -58,22 +31,30 @@ "name": "foo license" } } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, + "components": [ { - "name": "key2", - "value": "val2" + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "name": "foo license" + } + } + ] } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -86,11 +67,30 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.xml.bin index 8ece98969..dd23d8666 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.json.bin index 1d8ab1298..6a9ec1681 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.json.bin @@ -1,36 +1,11 @@ { - "components": [ - { - "bom-ref": "my-compo", - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "name": "foo license" - } - } - ], - "name": "comp", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, - { - "ref": "my-serv" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { + "name": "app", + "type": "application", "bom-ref": "my-app", "licenses": [ { @@ -43,9 +18,7 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application" + ] }, "licenses": [ { @@ -58,22 +31,30 @@ "name": "foo license" } } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, + "components": [ { - "name": "key2", - "value": "val2" + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "name": "foo license" + } + } + ] } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -86,11 +67,30 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.xml.bin index 84091db59..f6f94ee2a 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.json.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.json.bin index d19b61443..c47f897e2 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.json.bin @@ -1,36 +1,11 @@ { - "components": [ - { - "bom-ref": "my-compo", - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "name": "foo license" - } - } - ], - "name": "comp", - "type": "library" - } - ], - "dependencies": [ - { - "ref": "my-app" - }, - { - "ref": "my-compo" - }, - { - "ref": "my-serv" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { + "name": "app", + "type": "application", "bom-ref": "my-app", "licenses": [ { @@ -43,9 +18,7 @@ "name": "foo license" } } - ], - "name": "app", - "type": "application" + ] }, "licenses": [ { @@ -58,22 +31,30 @@ "name": "foo license" } } - ], - "timestamp": "2023-01-07T13:44:32.312678+00:00" + ] }, - "properties": [ - { - "name": "key1", - "value": "val1" - }, + "components": [ { - "name": "key2", - "value": "val2" + "name": "comp", + "type": "library", + "bom-ref": "my-compo", + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "name": "foo license" + } + } + ] } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { + "name": "serv", "bom-ref": "my-serv", "licenses": [ { @@ -86,11 +67,30 @@ "name": "foo license" } } - ], - "name": "serv" + ] + } + ], + "dependencies": [ + { + "ref": "my-app" + }, + { + "ref": "my-compo" + }, + { + "ref": "my-serv" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.xml.bin index 956d77389..3e474a415 100644 --- a/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_multiple_licenses-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.2.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.2.json.bin index 8a17945d0..2344ba049 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.2.json.bin @@ -1,48 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -50,96 +54,92 @@ } } ], - "name": "my-first-service", - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ], "services": [ { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "no-group", "version": "3.2.1", + "authenticated": true, "x-trust-boundary": false }, { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.2.xml.bin index a4612acde..173412312 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.3.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.3.json.bin index 5e480c8cc..5a4528848 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.3.json.bin @@ -1,54 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -56,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -67,95 +77,85 @@ "value": "val2" } ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "services": [ { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "no-group", "version": "3.2.1", + "authenticated": true, "x-trust-boundary": false }, { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.3.xml.bin index 9b260cd67..f2085b769 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.4.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.4.json.bin index 13797a133..51b068d0b 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.4.json.bin @@ -1,54 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -56,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -67,46 +77,84 @@ "value": "val2" } ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "services": [ + { + "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, + "group": "no-group", + "version": "3.2.1", + "authenticated": true, + "x-trust-boundary": false + }, + { + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" + } + ], "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -118,103 +166,55 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "services": [ - { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", - "name": "second-nested-service", - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "3.2.1", - "x-trust-boundary": false - }, - { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" - } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.4.xml.bin index e3e327ac7..3a710dbb5 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.5.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.5.json.bin index 11b528976..f2dd799a8 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.5.json.bin @@ -1,64 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,46 +77,84 @@ "value": "val2" } ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "services": [ + { + "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, + "group": "no-group", + "version": "3.2.1", + "authenticated": true, + "x-trust-boundary": false + }, + { + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" + } + ], "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -128,103 +166,65 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "services": [ - { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", - "name": "second-nested-service", - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "3.2.1", - "x-trust-boundary": false - }, - { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" - } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.5.xml.bin index 570fba7fe..1558c1829 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.6.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.6.json.bin index e14693242..9ee25f3b4 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.6.json.bin @@ -1,64 +1,58 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +60,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,52 +83,90 @@ "value": "val2" } ], - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "services": [ + { + "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, + "group": "no-group", + "version": "3.2.1", + "authenticated": true, + "x-trust-boundary": false + }, + { + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" + } + ], "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -134,115 +178,71 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "services": [ - { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", - "name": "second-nested-service", - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "3.2.1", - "x-trust-boundary": false - }, - { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" - } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.6.xml.bin index 24ce8e390..5c2a23faf 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.7.json.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.7.json.bin index edb0cc6cb..4190f6bac 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.7.json.bin @@ -1,64 +1,58 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +60,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,52 +83,90 @@ "value": "val2" } ], - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" + "services": [ + { + "name": "second-nested-service", + "bom-ref": "my-specific-bom-ref-for-second-nested-service", + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, + "group": "no-group", + "version": "3.2.1", + "authenticated": true, + "x-trust-boundary": false + }, + { + "name": "first-nested-service", + "bom-ref": "my-specific-bom-ref-for-first-nested-service" + } + ], "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -134,115 +178,71 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "services": [ - { - "authenticated": true, - "bom-ref": "my-specific-bom-ref-for-second-nested-service", - "group": "no-group", - "name": "second-nested-service", - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "3.2.1", - "x-trust-boundary": false - }, - { - "bom-ref": "my-specific-bom-ref-for-first-nested-service", - "name": "first-nested-service" - } - ], - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service", "services": [ { - "bom-ref": "yet-another-nested-service", - "group": "what-group", "name": "yet-another-nested-service", + "bom-ref": "yet-another-nested-service", "provider": { + "name": "CycloneDX", "address": { "country": "GB", - "locality": "Cheshire", "region": "England", + "locality": "Cheshire", "streetAddress": "100 Main Street" }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], "contact": [ { - "email": "someone@somewhere.tld", "name": "A N Other", + "email": "someone@somewhere.tld", "phone": "+44 (0)1234 567890" }, { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" + "name": "Paul Horton", + "email": "paul.horton@owasp.org" } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" ] }, + "group": "what-group", "version": "6.5.4" }, { - "bom-ref": "my-specific-bom-ref-for-another-nested-service", - "name": "another-nested-service" + "name": "another-nested-service", + "bom-ref": "my-specific-bom-ref-for-another-nested-service" } ] } ], - "version": 1, + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" + } + ], "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_nested_services-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_nested_services-1.7.xml.bin index f166a3a9e..1a5360d52 100644 --- a/tests/_data/snapshots/get_bom_with_nested_services-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_nested_services-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.2.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.2.json.bin index 50a81b634..d684ea207 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.2.json.bin @@ -1,48 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -50,34 +54,30 @@ } } ], - "name": "my-first-service", - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "1.2.3", - "x-trust-boundary": true + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment" + } + ] }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.2.xml.bin index de5d73bfa..9a1e81ab7 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.3.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.3.json.bin index c677d7b6b..c56d2fd3b 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.3.json.bin @@ -1,54 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -56,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -66,34 +76,24 @@ "name": "key2", "value": "val2" } - ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, - "version": "1.2.3", - "x-trust-boundary": true + ] }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.3.xml.bin index 5ea783f0e..175af7668 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.4.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.4.json.bin index 02bd8ecf6..a1fdac6b3 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.4.json.bin @@ -1,54 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -56,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -67,46 +77,52 @@ "value": "val2" } ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -118,41 +134,25 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.4.xml.bin index 762dff5a0..e52d34591 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.5.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.5.json.bin index 7672db574..68b7925fd 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.5.json.bin @@ -1,64 +1,52 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +54,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,46 +77,52 @@ "value": "val2" } ], - "provider": { - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -128,41 +134,35 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.5.xml.bin index 7fb7fc504..33aba60d2 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.6.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.6.json.bin index 45b78218c..f756135cb 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.6.json.bin @@ -1,64 +1,58 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +60,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,52 +83,52 @@ "value": "val2" } ], - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -134,41 +140,35 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.6.xml.bin index 7a054cfa1..a5d39d558 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.7.json.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.7.json.bin index 9aa33fa2d..4f41fbfa9 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.7.json.bin @@ -1,64 +1,58 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "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", + }, "services": [ { - "authenticated": false, + "name": "my-first-service", "bom-ref": "my-specific-bom-ref-for-my-first-service", - "data": [ - { - "classification": "public", - "flow": "outbound" - } - ], + "provider": { + "name": "CycloneDX", + "address": { + "country": "GB", + "region": "England", + "locality": "Cheshire", + "streetAddress": "100 Main Street" + }, + "url": [ + "https://cyclonedx.org", + "https://cyclonedx.org/docs" + ], + "contact": [ + { + "name": "A N Other", + "email": "someone@somewhere.tld", + "phone": "+44 (0)1234 567890" + }, + { + "name": "Paul Horton", + "email": "paul.horton@owasp.org" + } + ] + }, + "group": "a-group", + "version": "1.2.3", "description": "Description goes here", "endpoints": [ "/api/thing/1", "/api/thing/2" ], - "externalReferences": [ + "authenticated": false, + "x-trust-boundary": true, + "data": [ { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + "flow": "outbound", + "classification": "public" } ], - "group": "a-group", "licenses": [ { "license": { @@ -66,7 +60,19 @@ } } ], - "name": "my-first-service", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ], "properties": [ { "name": "key1", @@ -77,52 +83,52 @@ "value": "val2" } ], - "provider": { - "address": { - "country": "GB", - "locality": "Cheshire", - "region": "England", - "streetAddress": "100 Main Street" - }, - "contact": [ - { - "email": "someone@somewhere.tld", - "name": "A N Other", - "phone": "+44 (0)1234 567890" - }, - { - "email": "paul.horton@owasp.org", - "name": "Paul Horton" - } - ], - "name": "CycloneDX", - "url": [ - "https://cyclonedx.org", - "https://cyclonedx.org/docs" - ] - }, "releaseNotes": { + "type": "major", + "title": "Release Notes Title", + "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", + "description": "This release is a test release", + "timestamp": "2023-08-15T01:23:45.678900+00:00", "aliases": [ "First Test Release" ], - "description": "This release is a test release", - "featuredImage": "https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png", + "tags": [ + "alpha", + "test" + ], + "resolves": [ + { + "type": "security", + "id": "CVE-2021-44228", + "name": "Apache Log3Shell", + "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", + "source": { + "name": "NVD", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" + }, + "references": [ + "https://central.sonatype.org/news/20211213_log4shell_help", + "https://logging.apache.org/log4j/2.x/security.html" + ] + } + ], "notes": [ { - "locale": "en-GB", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-GB" }, { - "locale": "en-US", "text": { "content": "U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==", "contentType": "text/plain; charset=UTF-8", "encoding": "base64" - } + }, + "locale": "en-US" } ], "properties": [ @@ -134,41 +140,35 @@ "name": "key2", "value": "val2" } - ], - "resolves": [ - { - "description": "Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...", - "id": "CVE-2021-44228", - "name": "Apache Log3Shell", - "references": [ - "https://central.sonatype.org/news/20211213_log4shell_help", - "https://logging.apache.org/log4j/2.x/security.html" - ], - "source": { - "name": "NVD", - "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-44228" - }, - "type": "security" - } - ], - "socialImage": "https://cyclonedx.org/cyclonedx-icon.png", - "tags": [ - "alpha", - "test" - ], - "timestamp": "2023-08-15T01:23:45.678900+00:00", - "title": "Release Notes Title", - "type": "major" - }, - "version": "1.2.3", - "x-trust-boundary": true + ] + } }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "properties": [ + { + "name": "key1", + "value": "val1" + }, + { + "name": "key2", + "value": "val2" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_services_complex-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_services_complex-1.7.xml.bin index 770f7a844..0aa99fbd1 100644 --- a/tests/_data/snapshots/get_bom_with_services_complex-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_complex-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.2.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.2.json.bin index 7a7ff2b9f..d63a9b91d 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.2.json.bin @@ -1,36 +1,36 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.2" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.2.xml.bin index e5233acfd..41f227c0c 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.3.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.3.json.bin index cbd632516..43010dd91 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.3.json.bin @@ -1,36 +1,36 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.3" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.3.xml.bin index 7904f82f5..9617079d3 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.4.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.4.json.bin index 9834ec210..46703470b 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.4.json.bin @@ -1,36 +1,36 @@ { - "dependencies": [ - { - "ref": "my-specific-bom-ref-for-cpl" - }, - { - "ref": "my-specific-bom-ref-for-my-first-service" - }, - { - "ref": "my-specific-bom-ref-for-my-second-service" - } - ], + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", "name": "cyclonedx-python-lib", "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" + } }, - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", "services": [ { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" }, { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], + "dependencies": [ + { + "ref": "my-specific-bom-ref-for-cpl" + }, + { + "ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "ref": "my-specific-bom-ref-for-my-second-service" } ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.4.xml.bin index b85a5a8e7..9afe0e20b 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.5.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.5.json.bin index 7152a3c58..e8d8e07c3 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.5.json.bin @@ -1,4 +1,25 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "cyclonedx-python-lib", + "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", + "version": "1.0.0" + } + }, + "services": [ + { + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], "dependencies": [ { "ref": "my-specific-bom-ref-for-cpl" @@ -10,15 +31,6 @@ "ref": "my-specific-bom-ref-for-my-second-service" } ], - "metadata": { - "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", - "name": "cyclonedx-python-lib", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -29,18 +41,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "services": [ - { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" - }, - { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" - } - ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.5" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.5.xml.bin index 040f39ab4..945208022 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.6.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.6.json.bin index 284142963..7195f6929 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.6.json.bin @@ -1,4 +1,25 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "cyclonedx-python-lib", + "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", + "version": "1.0.0" + } + }, + "services": [ + { + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], "dependencies": [ { "ref": "my-specific-bom-ref-for-cpl" @@ -10,15 +31,6 @@ "ref": "my-specific-bom-ref-for-my-second-service" } ], - "metadata": { - "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", - "name": "cyclonedx-python-lib", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -29,18 +41,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "services": [ - { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" - }, - { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" - } - ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.6.xml.bin index 94f67e284..e14783fe3 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.7.json.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.7.json.bin index 65181aeb5..ab02fba2f 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.7.json.bin @@ -1,4 +1,25 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, + "metadata": { + "timestamp": "2023-01-07T13:44:32.312678+00:00", + "component": { + "name": "cyclonedx-python-lib", + "type": "library", + "bom-ref": "my-specific-bom-ref-for-cpl", + "version": "1.0.0" + } + }, + "services": [ + { + "name": "my-first-service", + "bom-ref": "my-specific-bom-ref-for-my-first-service" + }, + { + "name": "my-second-service", + "bom-ref": "my-specific-bom-ref-for-my-second-service" + } + ], "dependencies": [ { "ref": "my-specific-bom-ref-for-cpl" @@ -10,15 +31,6 @@ "ref": "my-specific-bom-ref-for-my-second-service" } ], - "metadata": { - "component": { - "bom-ref": "my-specific-bom-ref-for-cpl", - "name": "cyclonedx-python-lib", - "type": "library", - "version": "1.0.0" - }, - "timestamp": "2023-01-07T13:44:32.312678+00:00" - }, "properties": [ { "name": "key1", @@ -29,18 +41,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "services": [ - { - "bom-ref": "my-specific-bom-ref-for-my-first-service", - "name": "my-first-service" - }, - { - "bom-ref": "my-specific-bom-ref-for-my-second-service", - "name": "my-second-service" - } - ], - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_services_simple-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_services_simple-1.7.xml.bin index 5fe84e749..8376f96cf 100644 --- a/tests/_data/snapshots/get_bom_with_services_simple-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_services_simple-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.2.json.bin index ca38e5f0c..bd33a7c8c 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.2.json.bin @@ -1,30 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", "hashes": [ { "alg": "SHA-256", "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.2.xml.bin index 32920edd2..4c9d01102 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.3.json.bin index 1eb342c29..d096a01cd 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.3.json.bin @@ -1,30 +1,30 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", "hashes": [ { "alg": "SHA-256", "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.3.xml.bin index aee9da630..5a5e75406 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.4.json.bin index 3a26a1c6d..744b68640 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.4.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,42 +41,37 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", + "hashes": [ + { + "alg": "SHA-256", + "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + ] } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.4.xml.bin index aae5b797a..a3ae90afa 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.5.json.bin index 173988c27..88f989708 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.5.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,34 +41,31 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", + "hashes": [ + { + "alg": "SHA-256", + "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + ] } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" @@ -80,8 +82,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.5.xml.bin index 4800c7ba1..242a28d89 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.6.json.bin index 5eb714cbf..1e464b515 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.6.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,34 +41,31 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", + "hashes": [ + { + "alg": "SHA-256", + "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + ] } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" @@ -80,8 +82,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.6.xml.bin index fc5013d85..11b1b691c 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools-1.7.json.bin index 59086d2f5..0755b0fa1 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.7.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,34 +41,31 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", + "hashes": [ + { + "alg": "SHA-256", + "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" + ] } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-tool-b" @@ -80,8 +82,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools-1.7.xml.bin index 378ffa176..a4ad7c97b 100644 --- a/tests/_data/snapshots/get_bom_with_tools-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.json.bin index 0ca50ca7e..5b73ceeef 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.json.bin @@ -1,19 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { - "name": "other-component", - "vendor": "acme" + "vendor": "acme", + "name": "other-component" }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "name": "test-component" @@ -23,8 +25,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.xml.bin index e726653de..0caaaf018 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.json.bin index 25fd5c202..d98f45476 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.json.bin @@ -1,19 +1,21 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { - "name": "other-component", - "vendor": "acme" + "vendor": "acme", + "name": "other-component" }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "name": "test-component" @@ -23,8 +25,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.xml.bin index 0dfe73304..400d71b63 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.json.bin index 16407cc30..8318c2f25 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,18 +41,15 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { - "name": "other-component", - "vendor": "acme" + "vendor": "acme", + "name": "other-component" }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "name": "test-component" @@ -57,8 +59,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.xml.bin index f5504a7a4..15924bba8 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.json.bin index d66bbf232..973c4be5a 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.json.bin @@ -1,61 +1,78 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - } - ] + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "group": "acme" + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "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": "test-component", + "type": "library" + } + ], + "services": [ + { + "name": "other-service", + "group": "acme" + }, + { + "name": "test-service" + } + ] + } }, "properties": [ { @@ -67,8 +84,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.xml.bin index 40ae59a7c..e3fcf6ef0 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.5.xml.bin @@ -1,53 +1,63 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - - acme - other-service - - - test-component - - - test-service - + + + acme + other-component + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.json.bin index 0cf661c0b..4ba8af92c 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.json.bin @@ -1,61 +1,79 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - } - ] + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "group": "acme" + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], + "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": "test-component", + "type": "library" + } + ], + "services": [ + { + "name": "other-service", + "group": "acme" + }, + { + "name": "test-service" + } + ] + } }, "properties": [ { @@ -67,8 +85,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.xml.bin index 89d558fb5..3b4cd6278 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.6.xml.bin @@ -1,53 +1,63 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - - acme - other-service - - - test-component - - - test-service - + + + acme + other-component + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.json.bin index 6583b10e8..909dd6400 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.json.bin @@ -1,61 +1,79 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - } - ] + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "group": "acme" + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], + "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": "test-component", + "type": "library" + } + ], + "services": [ + { + "name": "other-service", + "group": "acme" + }, + { + "name": "test-service" + } + ] + } }, "properties": [ { @@ -67,8 +85,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.xml.bin index 9b6643125..e4b21af4b 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_duplicated_tools_irreversible_migrate-1.7.xml.bin @@ -1,53 +1,63 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - - acme - other-service - - - test-component - - - test-service - + + + acme + other-component + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.json.bin index ca5d7d521..4ef7a8572 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.json.bin @@ -1,36 +1,38 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", "hashes": [ { "alg": "SHA-256", "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-component" @@ -43,8 +45,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.xml.bin index 42294a3c5..358bc167f 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.json.bin index eefffde73..d3847ef5a 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.json.bin @@ -1,36 +1,38 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", "hashes": [ { "alg": "SHA-256", "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + ] }, { "name": "test-component" @@ -43,8 +45,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.xml.bin index b734059fe..64bbe0c61 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.json.bin index 4d6c2c33e..8a0106e5a 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,74 +41,71 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } ], - "name": "other-component", - "vendor": "acme" - }, - { "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "name": "other-service", - "vendor": "acme" + ] }, { + "vendor": "acme", + "name": "other-service", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], + ] + }, + { + "vendor": "example", + "name": "test-tool-a", + "version": "1.33.7", "hashes": [ { "alg": "SHA-256", "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" } ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] }, { "name": "test-component" @@ -116,8 +118,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.xml.bin index 55e694f91..38d614201 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.json.bin index f0ab4915b..1fd229a30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.json.bin @@ -1,120 +1,114 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "name": "other-service", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" - } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" - }, - { - "name": "test-component" - }, - { - "name": "test-service" - }, - { - "name": "test-tool-b" - } - ] + } + ], + "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": "test-component", + "type": "library", + "bom-ref": "test-component" + } + ], + "services": [ + { + "name": "other-service", + "bom-ref": "other-service", + "group": "acme", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "test-service", + "bom-ref": "test-service" + } + ] + } }, "properties": [ { @@ -126,8 +120,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.xml.bin index e0cee50f0..7c3ff74bb 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.5.xml.bin @@ -1,94 +1,84 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - acme - other-service - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - example - test-tool-a - 1.33.7 - - adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6 - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - test-component - - - test-service - - - test-tool-b - + + + acme + other-component + + 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca + + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.json.bin index d16d05983..112c9f179 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.json.bin @@ -1,120 +1,115 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "name": "other-service", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" - } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" - }, - { - "name": "test-component" - }, - { - "name": "test-service" - }, - { - "name": "test-tool-b" - } - ] + } + ], + "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": "test-component", + "type": "library", + "bom-ref": "test-component" + } + ], + "services": [ + { + "name": "other-service", + "bom-ref": "other-service", + "group": "acme", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "test-service", + "bom-ref": "test-service" + } + ] + } }, "properties": [ { @@ -126,8 +121,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.xml.bin index 5b560874d..5f199917d 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.6.xml.bin @@ -1,94 +1,84 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - acme - other-service - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - example - test-tool-a - 1.33.7 - - adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6 - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - test-component - - - test-service - - - test-tool-b - + + + acme + other-component + + 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca + + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.json.bin index 71c821b55..5352089de 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.json.bin @@ -1,120 +1,115 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "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" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" - } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "name": "other-service", - "vendor": "acme" - }, - { - "externalReferences": [ - { - "comment": "No comment", - "hashes": [ - { - "alg": "SHA-256", - "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + "tools": { + "components": [ + { + "name": "other-component", + "type": "application", + "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", + "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" - } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6" - } - ], - "name": "test-tool-a", - "vendor": "example", - "version": "1.33.7" - }, - { - "name": "test-component" - }, - { - "name": "test-service" - }, - { - "name": "test-tool-b" - } - ] + } + ], + "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": "test-component", + "type": "library", + "bom-ref": "test-component" + } + ], + "services": [ + { + "name": "other-service", + "bom-ref": "other-service", + "group": "acme", + "externalReferences": [ + { + "type": "distribution", + "url": "https://cyclonedx.org", + "comment": "No comment", + "hashes": [ + { + "alg": "SHA-256", + "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" + } + ] + } + ] + }, + { + "name": "test-service", + "bom-ref": "test-service" + } + ] + } }, "properties": [ { @@ -126,8 +121,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.xml.bin index d634f1825..43b9e62c2 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_and_tools_irreversible_migrate-1.7.xml.bin @@ -1,94 +1,84 @@ - + 2023-01-07T13:44:32.312678+00:00 - - CycloneDX - cyclonedx-python-lib - TESTING - - - https://github.com/CycloneDX/cyclonedx-python-lib/actions - - - https://pypi.org/project/cyclonedx-python-lib/ - - - https://cyclonedx-python-library.readthedocs.io/ - - - https://github.com/CycloneDX/cyclonedx-python-lib/issues - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE - - - https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md - - - https://github.com/CycloneDX/cyclonedx-python-lib - - - https://github.com/CycloneDX/cyclonedx-python-lib/#readme - - - - - acme - other-component - - 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - acme - other-service - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - example - test-tool-a - 1.33.7 - - adbbbe72c8f023b4a2d96a3978f69d94873ab2fef424e0298287c3368519c1a6 - - - - https://cyclonedx.org - No comment - - 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b - - - - - - test-component - - - test-service - - - test-tool-b - + + + acme + other-component + + 49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca + + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + CycloneDX + cyclonedx-python-lib + TESTING + Python library for CycloneDX + + + Apache-2.0 + + + + + https://github.com/CycloneDX/cyclonedx-python-lib/actions + + + https://pypi.org/project/cyclonedx-python-lib/ + + + https://cyclonedx-python-library.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python-lib/issues + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python-lib + + + https://github.com/CycloneDX/cyclonedx-python-lib/#readme + + + + + test-component + + + + + acme + other-service + + + https://cyclonedx.org + No comment + + 806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b + + + + + + test-service + + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.json.bin index ea32ff1c3..6430c1d87 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.json.bin @@ -1,25 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "name": "test-component" @@ -29,8 +31,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.xml.bin index ec74cfb13..474502d07 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.json.bin index fbeec8f3f..433199ba3 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.json.bin @@ -1,25 +1,27 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "name": "test-component" @@ -29,8 +31,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.xml.bin index 514e1f503..34fb39bf4 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.json.bin index c45daad3e..f87f6cff4 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,50 +41,47 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "acme", + "name": "other-component", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "vendor": "acme" + ] }, { + "vendor": "acme", + "name": "other-service", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "name": "other-service", - "vendor": "acme" + ] }, { "name": "test-component" @@ -89,8 +91,6 @@ } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.xml.bin index 53304d725..37f0aff99 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.json.bin index f040c90ad..1fd229a30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.json.bin @@ -1,35 +1,48 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,47 +76,36 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ], "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -118,8 +120,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.xml.bin index 4a7bcd8c1..7c3ff74bb 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.json.bin index eb1ff770e..112c9f179 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.json.bin @@ -1,35 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,48 +77,36 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "acknowledgement": "declared", - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ], "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -119,8 +121,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.xml.bin index 84aced327..5f199917d 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.json.bin index 72516a164..5352089de 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.json.bin @@ -1,35 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,48 +77,36 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "acknowledgement": "declared", - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ], "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -119,8 +121,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.xml.bin index 71349a426..43b9e62c2 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_and_service_migrate-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.json.bin index b0ee39eae..c4fe2b5e3 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.json.bin @@ -1,29 +1,29 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { "name": "test-component" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.xml.bin index 5614334ae..33c694c00 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.json.bin index 6d5ee9158..a50612a5f 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.json.bin @@ -1,29 +1,29 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "cyclonedx-python-lib", "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", "version": "TESTING" }, { + "vendor": "acme", + "name": "other-component", "hashes": [ { "alg": "SHA-256", "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" } - ], - "name": "other-component", - "vendor": "acme" + ] }, { "name": "test-component" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.xml.bin index 469b6dfc5..45d0d37ed 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.json.bin index a56d92b9b..0adeecdad 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.json.bin @@ -1,8 +1,13 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "TESTING", "externalReferences": [ { "type": "build-system", @@ -36,41 +41,36 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "name": "cyclonedx-python-lib", - "vendor": "CycloneDX", - "version": "TESTING" + ] }, { + "vendor": "acme", + "name": "other-component", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "vendor": "acme" + ] }, { "name": "test-component" } ] }, - "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.xml.bin index d64c901e8..812f2a14f 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.json.bin index f89e6e2ca..1f4d4c577 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.json.bin @@ -1,35 +1,48 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,23 +76,12 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ] } @@ -94,8 +96,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.xml.bin index aa2849081..33ec2b681 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.json.bin index dea1d9d91..314c9f964 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.json.bin @@ -1,35 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,24 +77,12 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "acknowledgement": "declared", - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ] } @@ -95,8 +97,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.xml.bin index 2f8ceecf9..88b8df036 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.json.bin index 63512c80b..4636a2d8f 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.json.bin @@ -1,35 +1,49 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "components": [ { + "name": "other-component", + "type": "application", "bom-ref": "other-component", + "group": "acme", + "hashes": [ + { + "alg": "SHA-256", + "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" + } + ], "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "hashes": [ - { - "alg": "SHA-256", - "content": "49b420bd8d8182542a76d4422e0c7890dcc88a3d8ddad04da06366d8c40ac8ca" - } - ], - "name": "other-component", - "type": "application" + ] }, { + "name": "cyclonedx-python-lib", + "type": "library", + "group": "CycloneDX", + "version": "TESTING", "description": "Python library for CycloneDX", + "licenses": [ + { + "license": { + "id": "Apache-2.0", + "acknowledgement": "declared" + } + } + ], "externalReferences": [ { "type": "build-system", @@ -63,24 +77,12 @@ "type": "website", "url": "https://github.com/CycloneDX/cyclonedx-python-lib/#readme" } - ], - "group": "CycloneDX", - "licenses": [ - { - "license": { - "acknowledgement": "declared", - "id": "Apache-2.0" - } - } - ], - "name": "cyclonedx-python-lib", - "type": "library", - "version": "TESTING" + ] }, { - "bom-ref": "test-component", "name": "test-component", - "type": "library" + "type": "library", + "bom-ref": "test-component" } ] } @@ -95,8 +97,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.xml.bin index 46131bf9f..6f18b38fe 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_component_migrate-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.1.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.1.xml.bin index 55ef5cda2..145de8c30 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.1.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.1.xml.bin @@ -1,4 +1,4 @@ - + diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.json.bin index 020949980..ab19331f6 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.json.bin @@ -1,18 +1,18 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.xml.bin index 266aa5b62..340187470 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.2.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.json.bin index 62a2e4c3d..d34b9b7a5 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.json.bin @@ -1,18 +1,18 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { - "name": "other-service", - "vendor": "acme" + "vendor": "acme", + "name": "other-service" }, { "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.xml.bin index 97729c4e3..19d8b8140 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.3.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.json.bin index bcf21a66e..0d2334b89 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.json.bin @@ -1,31 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": [ { + "vendor": "acme", + "name": "other-service", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "name": "other-service", - "vendor": "acme" + ] }, { "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.xml.bin index af666d2c9..b011aacd6 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.4.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.json.bin index c5e9c6e87..f38c15b3a 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.json.bin @@ -1,29 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -38,8 +40,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.xml.bin index 3a8ba335d..035bcf7e4 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.5.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.json.bin index a9293a54d..9e9fe51aa 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.json.bin @@ -1,29 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -38,8 +40,6 @@ "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" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.xml.bin index e33e4dc1f..c0fa2af02 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.6.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.json.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.json.bin index 5feaa83e5..d1cb134a1 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.json.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.json.bin @@ -1,29 +1,31 @@ { + "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", + "version": 1, "metadata": { "timestamp": "2023-01-07T13:44:32.312678+00:00", "tools": { "services": [ { + "name": "other-service", "bom-ref": "other-service", + "group": "acme", "externalReferences": [ { + "type": "distribution", + "url": "https://cyclonedx.org", "comment": "No comment", "hashes": [ { "alg": "SHA-256", "content": "806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b" } - ], - "type": "distribution", - "url": "https://cyclonedx.org" + ] } - ], - "group": "acme", - "name": "other-service" + ] }, { - "bom-ref": "test-service", - "name": "test-service" + "name": "test-service", + "bom-ref": "test-service" } ] } @@ -38,8 +40,6 @@ "value": "val2" } ], - "serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac", - "version": 1, "$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.7" diff --git a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.xml.bin b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.xml.bin index cda60f02e..3df91ba8f 100644 --- a/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.xml.bin +++ b/tests/_data/snapshots/get_bom_with_tools_with_service_migrate-1.7.xml.bin @@ -1,5 +1,5 @@ - + 2023-01-07T13:44:32.312678+00:00 diff --git a/tests/test_model_bom.py b/tests/test_model_bom.py index 030ee4a56..e9d2bd7c1 100644 --- a/tests/test_model_bom.py +++ b/tests/test_model_bom.py @@ -66,7 +66,8 @@ def test_equal(self) -> None: self.assertNotEqual(a, c) def test_sort(self) -> None: - expected_order = [2, 1, 3, 0] + # Sort order is alphabetical by TLP value string + expected_order = [1, 2, 3, 0] # AMBER, AMBER_AND_STRICT, CLEAR, RED dcs = [ DistributionConstraints(tlp=TlpClassification.RED), DistributionConstraints(tlp=TlpClassification.AMBER), diff --git a/tests/test_model_component.py b/tests/test_model_component.py index 44f59a121..0e084fef9 100644 --- a/tests/test_model_component.py +++ b/tests/test_model_component.py @@ -395,7 +395,8 @@ def test_sort(self) -> None: ] # expected sort order: (type, [diff], sorted(resolves)) - expected_order = [5, 4, 3, 2, 1, 0] + # Empty resolves sorts before non-empty (standard tuple comparison) + expected_order = [5, 4, 2, 3, 1, 0] patches = [ Patch(type=PatchClassification.MONKEY), Patch(type=PatchClassification.MONKEY, diff=diff_b), diff --git a/tests/test_model_vulnerability.py b/tests/test_model_vulnerability.py index 6c90a8adb..1934533c7 100644 --- a/tests/test_model_vulnerability.py +++ b/tests/test_model_vulnerability.py @@ -423,8 +423,10 @@ def test_sort(self) -> None: class TestModelVulnerabilityAnalysis(TestCase): def test_sort(self) -> None: - # expected sort order: ([state], [justification], [responses], [detail], [first_issued], [last_updated]) - expected_order = [3, 1, 0, 2, 5, 4] + # expected sort order: ([state], [justification], [responses], [detail]) + # first_issued and last_updated are not part of the sort key + # Empty responses sorts before non-empty (standard tuple comparison) + expected_order = [3, 0, 1, 2, 4, 5] analyses = [ VulnerabilityAnalysis(state=ImpactAnalysisState.EXPLOITABLE), VulnerabilityAnalysis(state=ImpactAnalysisState.EXPLOITABLE,