Skip to content
30 changes: 29 additions & 1 deletion cyclonedx/model/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from .license import License, LicenseExpression, LicenseRepository, _LicenseRepositorySerializationHelper
from .lifecycle import Lifecycle, LifecycleRepository, _LifecycleRepositoryHelper
from .service import Service
from .signature import JsfSignature, _JsfSignatureSerializationHelper
from .tool import Tool, ToolRepository, _ToolRepositoryHelper
from .vulnerability import Vulnerability

Expand Down Expand Up @@ -444,6 +445,7 @@ def __init__(
vulnerabilities: Optional[Iterable[Vulnerability]] = None,
properties: Optional[Iterable[Property]] = None,
definitions: Optional[Definitions] = None,
signature: Optional[JsfSignature] = None,
) -> None:
"""
Create a new Bom that you can manually/programmatically add data to later.
Expand All @@ -461,6 +463,7 @@ def __init__(
self.dependencies = dependencies or []
self.properties = properties or []
self.definitions = definitions or Definitions()
self.signature = signature

@property
@serializable.type_mapping(UrnUuidHelper)
Expand Down Expand Up @@ -694,6 +697,31 @@ def definitions(self) -> Optional[Definitions]:
def definitions(self, definitions: Definitions) -> None:
self._definitions = definitions

@property
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.view(SchemaVersion1Dot7)
@serializable.type_mapping(_JsfSignatureSerializationHelper)
def signature(self) -> Optional[JsfSignature]:
"""
Enveloped signature in JSON Signature Format (JSF).

.. note::
JSON-only. There is no XSD/XML equivalent in any CycloneDX schema version.

.. note::
Introduced in CycloneDX v1.4

Returns:
`JsfSignature` if set else `None`
"""
return self._signature

@signature.setter
def signature(self, signature: Optional[JsfSignature]) -> None:
self._signature = signature

def get_component_by_purl(self, purl: Optional['PackageURL']) -> Optional[Component]:
"""
Get a Component already in the Bom by its PURL
Expand Down Expand Up @@ -871,7 +899,7 @@ def __comparable_tuple(self) -> _ComparableTuple:
self.components), _ComparableTuple(self.services),
_ComparableTuple(self.external_references), _ComparableTuple(
self.dependencies), _ComparableTuple(self.properties),
_ComparableTuple(self.vulnerabilities),
_ComparableTuple(self.vulnerabilities), self.signature,
))

def __eq__(self, other: object) -> bool:
Expand Down
30 changes: 29 additions & 1 deletion cyclonedx/model/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
from .issue import IssueType
from .license import License, LicenseRepository, _LicenseRepositorySerializationHelper
from .release_note import ReleaseNotes
from .signature import JsfSignature, _JsfSignatureSerializationHelper


@serializable.serializable_class(ignore_unknown_during_deserialization=True)
Expand Down Expand Up @@ -1013,6 +1014,7 @@ def __init__(
swhids: Optional[Iterable[Swhid]] = None,
crypto_properties: Optional[CryptoProperties] = None,
tags: Optional[Iterable[str]] = None,
signature: Optional[JsfSignature] = None,
# Deprecated in v1.6
author: Optional[str] = None,
) -> None:
Expand Down Expand Up @@ -1044,6 +1046,7 @@ def __init__(
self.release_notes = release_notes
self.crypto_properties = crypto_properties
self.tags = tags or []
self.signature = signature
# spec-deprecated properties below
self.author = author
self.modified = modified
Expand Down Expand Up @@ -1684,6 +1687,31 @@ def tags(self) -> 'SortedSet[str]':
def tags(self, tags: Iterable[str]) -> None:
self._tags = SortedSet(tags)

@property
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.view(SchemaVersion1Dot7)
@serializable.type_mapping(_JsfSignatureSerializationHelper)
def signature(self) -> Optional[JsfSignature]:
"""
Enveloped signature in JSON Signature Format (JSF).

.. note::
JSON-only. There is no XSD/XML equivalent in any CycloneDX schema version.

.. note::
Introduced in CycloneDX v1.4

Returns:
`JsfSignature` if set else `None`
"""
return self._signature

@signature.setter
def signature(self, signature: Optional[JsfSignature]) -> None:
self._signature = signature

def get_all_nested_components(self, include_self: bool = False) -> set['Component']:
components = set()
if include_self:
Expand Down Expand Up @@ -1714,7 +1742,7 @@ def __comparable_tuple(self) -> _ComparableTuple:
_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),
self.crypto_properties, _ComparableTuple(self.tags), self.signature,
self.is_external,
))

Expand Down
30 changes: 29 additions & 1 deletion cyclonedx/model/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from .dependency import Dependable
from .license import License, LicenseRepository, _LicenseRepositorySerializationHelper
from .release_note import ReleaseNotes
from .signature import JsfSignature, _JsfSignatureSerializationHelper


@serializable.serializable_class(ignore_unknown_during_deserialization=True)
Expand Down Expand Up @@ -73,6 +74,7 @@ def __init__(
properties: Optional[Iterable[Property]] = None,
services: Optional[Iterable['Service']] = None,
release_notes: Optional[ReleaseNotes] = None,
signature: Optional[JsfSignature] = None,
) -> None:
self._bom_ref = _bom_ref_from_str(bom_ref)
self.provider = provider
Expand All @@ -89,6 +91,7 @@ def __init__(
self.services = services or []
self.release_notes = release_notes
self.properties = properties or []
self.signature = signature

@property
@serializable.json_name('bom-ref')
Expand Down Expand Up @@ -361,6 +364,31 @@ def release_notes(self) -> Optional[ReleaseNotes]:
def release_notes(self, release_notes: Optional[ReleaseNotes]) -> None:
self._release_notes = release_notes

@property
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.view(SchemaVersion1Dot7)
@serializable.type_mapping(_JsfSignatureSerializationHelper)
def signature(self) -> Optional[JsfSignature]:
"""
Enveloped signature in JSON Signature Format (JSF).

.. note::
JSON-only. There is no XSD/XML equivalent in any CycloneDX schema version.

.. note::
Introduced in CycloneDX v1.4

Returns:
`JsfSignature` if set else `None`
"""
return self._signature

@signature.setter
def signature(self, signature: Optional[JsfSignature]) -> None:
self._signature = signature

def __comparable_tuple(self) -> _ComparableTuple:
return _ComparableTuple((
self.group, self.name, self.version,
Expand All @@ -369,7 +397,7 @@ def __comparable_tuple(self) -> _ComparableTuple:
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
self.x_trust_boundary, self.signature
))

def __eq__(self, other: object) -> bool:
Expand Down
Loading