Skip to content

feat: support bom.properties for CycloneDX v1.5+ #585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 33 additions & 20 deletions cyclonedx/model/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ def __init__(self, *, components: Optional[Iterable[Component]] = None,
serial_number: Optional[UUID] = None, version: int = 1,
metadata: Optional[BomMetaData] = None,
dependencies: Optional[Iterable[Dependency]] = None,
vulnerabilities: Optional[Iterable[Vulnerability]] = None) -> None:
vulnerabilities: Optional[Iterable[Vulnerability]] = None,
properties: Optional[Iterable[Property]] = None) -> None:
"""
Create a new Bom that you can manually/programmatically add data to later.

Expand All @@ -325,6 +326,7 @@ def __init__(self, *, components: Optional[Iterable[Component]] = None,
self.external_references = external_references or [] # type:ignore[assignment]
self.vulnerabilities = vulnerabilities or [] # type:ignore[assignment]
self.dependencies = dependencies or [] # type:ignore[assignment]
self.properties = properties or [] # type:ignore[assignment]

@property
@serializable.type_mapping(UrnUuidHelper)
Expand Down Expand Up @@ -364,7 +366,7 @@ def version(self, version: int) -> None:
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_sequence(1)
@serializable.xml_sequence(10)
def metadata(self) -> BomMetaData:
"""
Get our internal metadata object for this Bom.
Expand All @@ -385,7 +387,7 @@ def metadata(self, metadata: BomMetaData) -> None:
@serializable.include_none(SchemaVersion1Dot0)
@serializable.include_none(SchemaVersion1Dot1)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'component')
@serializable.xml_sequence(2)
@serializable.xml_sequence(20)
def components(self) -> 'SortedSet[Component]':
"""
Get all the Components currently in this Bom.
Expand All @@ -406,7 +408,7 @@ def components(self, components: Iterable[Component]) -> None:
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'service')
@serializable.xml_sequence(3)
@serializable.xml_sequence(30)
def services(self) -> 'SortedSet[Service]':
"""
Get all the Services currently in this Bom.
Expand All @@ -428,7 +430,7 @@ def services(self, services: Iterable[Service]) -> None:
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'reference')
@serializable.xml_sequence(4)
@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.
Expand All @@ -449,7 +451,7 @@ def external_references(self, external_references: Iterable[ExternalReference])
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'dependency')
@serializable.xml_sequence(5)
@serializable.xml_sequence(50)
def dependencies(self) -> 'SortedSet[Dependency]':
return self._dependencies

Expand All @@ -470,25 +472,35 @@ def dependencies(self, dependencies: Iterable[Dependency]) -> None:
# def compositions(self, ...) -> None:
# ... # TODO Since CDX 1.3

# @property
# ...
# @serializable.view(SchemaVersion1Dot3)
# @serializable.view(SchemaVersion1Dot4)
# @serializable.view(SchemaVersion1Dot5)
# @serializable.xml_sequence(7)
# def properties(self) -> ...:
# ... # TODO Since CDX 1.3
#
# @properties.setter
# def properties(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.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`
"""
return self._properties

@properties.setter
def properties(self, properties: Iterable[Property]) -> None:
self._properties = SortedSet(properties)

@property
@serializable.view(SchemaVersion1Dot4)
@serializable.view(SchemaVersion1Dot5)
@serializable.view(SchemaVersion1Dot6)
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'vulnerability')
@serializable.xml_sequence(8)
@serializable.xml_sequence(80)
def vulnerabilities(self) -> 'SortedSet[Vulnerability]':
"""
Get all the Vulnerabilities in this BOM.
Expand Down Expand Up @@ -682,7 +694,8 @@ def __eq__(self, other: object) -> bool:
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.vulnerabilities), tuple(self.dependencies)
tuple(self.external_references), tuple(self.dependencies), tuple(self.properties),
tuple(self.vulnerabilities),
))

def __repr__(self) -> str:
Expand Down
28 changes: 4 additions & 24 deletions docs/schema-support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,16 @@ The following sub-sections aim to explain what support this library provides and
by calling out support for data as defined in the latest CycloneDX standard specification, regardless of whether it is
supported in prior versions of the CycloneDX schema.

Root Level Schema Support
-------------------------

+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| Data Path | Supported? | Notes |
+============================+===============+===================================================================================================+
| ``bom[@version]`` | Yes | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom[@serialNumber]`` | Yes | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.metadata`` | Yes | Not supported: ``lifecycles`` |
| ``bom.metadata`` | Yes | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.components`` | Yes | Not supported: ``modified`` (as it is deprecated), ``modelCard``, ``data``, ``signature``. |
| ``bom.components`` | Yes | Not supported: ``modified`` (as it is deprecated), ``signature``. |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.services`` | Yes | Not supported: ``signature``. |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
Expand All @@ -43,6 +40,8 @@ Root Level Schema Support
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.compositions`` | No | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.properties`` | Yes | Supported when outputting to Schema Version >= 1.5. See `schema specification bug 130`_ |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.vulnerabilities`` | Yes | Note: Prior to CycloneDX 1.4, these were present under ``bom.components`` via a schema extension. |
| | | Note: As of ``cyclonedx-python-lib`` ``>3.0.0``, Vulnerability are modelled differently |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
Expand All @@ -54,27 +53,8 @@ Root Level Schema Support
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.definitions`` | No | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.properties`` | No | See `schema specification bug 130`_ |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+
| ``bom.signature`` | No | |
+----------------------------+---------------+---------------------------------------------------------------------------------------------------+

Internal Model Schema Support
-----------------------------

+----------------------------+---------------+----------------------------------------------------------------------------------------------+
| Internal Model | Supported? | Notes |
+============================+===============+==============================================================================================+
| ``ComponentEvidence`` |Yes | Not currently supported: ``callstack``, ``identity``, ``occurrences``. |
+----------------------------+---------------+----------------------------------------------------------------------------------------------+
| ``DisjunctiveLicense`` |Yes | Not currently supported: ``@bom-ref``, ``licensing``, ``properties``. |
+----------------------------+---------------+----------------------------------------------------------------------------------------------+
| ``LicenseExpression`` |Yes | Not currently supported: ``@bom-ref`` |
+----------------------------+---------------+----------------------------------------------------------------------------------------------+
| ``OrganizationalContact`` |Yes | Not currently supported: ``@bom-ref`` |
+----------------------------+---------------+----------------------------------------------------------------------------------------------+
| ``OrganizationalEntity`` |Yes | Not currently supported: ``@bom-ref`` |
+----------------------------+---------------+----------------------------------------------------------------------------------------------+

.. _schema specification bug 130: https://github.com/CycloneDX/specification/issues/130

1 change: 1 addition & 0 deletions tests/_data/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def _make_bom(**kwargs: Any) -> Bom:
bom = Bom(**kwargs)
bom.serial_number = BOM_SERIAL_NUMBER
bom.metadata.timestamp = BOM_TIMESTAMP
bom.properties = get_properties_1()
return bom


Expand Down
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_ComponentScope-1.5.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@
}
]
},
"properties": [
{
"name": "key1",
"value": "val1"
},
{
"name": "key2",
"value": "val2"
}
],
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_ComponentScope-1.5.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@
<dependency ref="scoped-OPTIONAL"/>
<dependency ref="scoped-REQUIRED"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_ComponentScope-1.6.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@
}
]
},
"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",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_ComponentScope-1.6.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,8 @@
<dependency ref="scoped-OPTIONAL"/>
<dependency ref="scoped-REQUIRED"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_ComponentType-1.5.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,16 @@
}
]
},
"properties": [
{
"name": "key1",
"value": "val1"
},
{
"name": "key2",
"value": "val2"
}
],
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_ComponentType-1.5.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@
<dependency ref="typed-OPERATING_SYSTEM"/>
<dependency ref="typed-PLATFORM"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_ComponentType-1.6.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@
}
]
},
"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",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_ComponentType-1.6.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,8 @@
<dependency ref="typed-OPERATING_SYSTEM"/>
<dependency ref="typed-PLATFORM"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_DataFlow-1.5.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
}
]
},
"properties": [
{
"name": "key1",
"value": "val1"
},
{
"name": "key2",
"value": "val2"
}
],
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"services": [
{
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_DataFlow-1.5.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
<dependencies>
<dependency ref="dummy"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_DataFlow-1.6.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@
}
]
},
"properties": [
{
"name": "key1",
"value": "val1"
},
{
"name": "key2",
"value": "val2"
}
],
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"services": [
{
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_DataFlow-1.6.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
<dependencies>
<dependency ref="dummy"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_Encoding-1.5.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
}
]
},
"properties": [
{
"name": "key1",
"value": "val1"
},
{
"name": "key2",
"value": "val2"
}
],
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
"version": 1,
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_Encoding-1.5.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
<dependencies>
<dependency ref="dummy"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
10 changes: 10 additions & 0 deletions tests/_data/snapshots/enum_Encoding-1.6.json.bin
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
}
]
},
"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",
Expand Down
4 changes: 4 additions & 0 deletions tests/_data/snapshots/enum_Encoding-1.6.xml.bin
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@
<dependencies>
<dependency ref="dummy"/>
</dependencies>
<properties>
<property name="key1">val1</property>
<property name="key2">val2</property>
</properties>
</bom>
Loading
Loading