diff --git a/cyclonedx/model/service.py b/cyclonedx/model/service.py
index 10597370..9f78b69f 100644
--- a/cyclonedx/model/service.py
+++ b/cyclonedx/model/service.py
@@ -67,6 +67,7 @@ def __init__(
endpoints: Optional[Iterable[XsUri]] = None,
authenticated: Optional[bool] = None,
x_trust_boundary: Optional[bool] = None,
+ trust_zone: Optional[str] = None,
data: Optional[Iterable[DataClassification]] = None,
licenses: Optional[Iterable[License]] = None,
external_references: Optional[Iterable[ExternalReference]] = None,
@@ -83,6 +84,7 @@ def __init__(
self.endpoints = endpoints or []
self.authenticated = authenticated
self.x_trust_boundary = x_trust_boundary
+ self.trust_zone = trust_zone
self.data = data or []
self.licenses = licenses or []
self.external_references = external_references or []
@@ -239,16 +241,25 @@ def x_trust_boundary(self) -> Optional[bool]:
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.view(SchemaVersion1Dot5)
+ @serializable.view(SchemaVersion1Dot6)
+ @serializable.view(SchemaVersion1Dot7)
+ @serializable.xml_sequence(9)
+ def trust_zone(self) -> Optional[str]:
+ """
+ The name of the trust zone the service resides in.
+
+ Supported from CycloneDX v1.5 onwards.
+
+ Returns:
+ `str` if set else `None`
+ """
+ return self._trust_zone
+
+ @trust_zone.setter
+ def trust_zone(self, trust_zone: Optional[str]) -> None:
+ self._trust_zone = trust_zone
@property
@serializable.xml_array(serializable.XmlArraySerializationType.NESTED, 'classification')
@@ -369,7 +380,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.trust_zone
))
def __eq__(self, other: object) -> bool:
diff --git a/tests/_data/models.py b/tests/_data/models.py
index 565f56ec..3138bd06 100644
--- a/tests/_data/models.py
+++ b/tests/_data/models.py
@@ -620,7 +620,7 @@ def get_bom_with_services_complex() -> Bom:
XsUri('/api/thing/1'),
XsUri('/api/thing/2')
],
- authenticated=False, x_trust_boundary=True, data=[
+ authenticated=False, x_trust_boundary=True, trust_zone='internal\tvpc', data=[
DataClassification(flow=DataFlow.OUTBOUND, classification='public')
],
licenses=[DisjunctiveLicense(name='Commercial')],
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 7672db57..cb6d3173 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
@@ -154,6 +154,7 @@
"title": "Release Notes Title",
"type": "major"
},
+ "trustZone": "internal\tvpc",
"version": "1.2.3",
"x-trust-boundary": true
},
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 7fb7fc50..bb929035 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
@@ -33,6 +33,7 @@
false
true
+ internal vpc
public
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 45b78218..14ee1b0c 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
@@ -160,6 +160,7 @@
"title": "Release Notes Title",
"type": "major"
},
+ "trustZone": "internal\tvpc",
"version": "1.2.3",
"x-trust-boundary": true
},
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 7a054cfa..8920017d 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
@@ -39,6 +39,7 @@
false
true
+ internal vpc
public
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 9aa33fa2..3c58418f 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
@@ -160,6 +160,7 @@
"title": "Release Notes Title",
"type": "major"
},
+ "trustZone": "internal\tvpc",
"version": "1.2.3",
"x-trust-boundary": true
},
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 770f7a84..642dd969 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
@@ -39,6 +39,7 @@
false
true
+ internal vpc
public
diff --git a/tests/test_model_service.py b/tests/test_model_service.py
index c66c2521..94f87da5 100644
--- a/tests/test_model_service.py
+++ b/tests/test_model_service.py
@@ -18,6 +18,8 @@
from unittest import TestCase
+from sortedcontainers import SortedSet
+
from cyclonedx.model.service import Service
from tests import reorder
@@ -35,6 +37,7 @@ def test_minimal_service(self) -> None:
self.assertFalse(s.endpoints)
self.assertIsNone(s.authenticated)
self.assertIsNone(s.x_trust_boundary)
+ self.assertIsNone(s.trust_zone)
self.assertFalse(s.data)
self.assertFalse(s.licenses)
self.assertFalse(s.external_references)
@@ -57,6 +60,7 @@ def test_service_with_services(self) -> None:
self.assertFalse(parent_service.endpoints)
self.assertIsNone(parent_service.authenticated)
self.assertIsNone(parent_service.x_trust_boundary)
+ self.assertIsNone(parent_service.trust_zone)
self.assertFalse(parent_service.data)
self.assertFalse(parent_service.licenses)
self.assertFalse(parent_service.external_references)
@@ -80,3 +84,19 @@ def test_sort(self) -> None:
sorted_services = sorted(services)
expected_services = reorder(services, expected_order)
self.assertListEqual(sorted_services, expected_services)
+
+ def test_trust_zone_default(self) -> None:
+ s = Service(name='my-test-service')
+ self.assertIsNone(s.trust_zone)
+
+ def test_trust_zone_setter(self) -> None:
+ s = Service(name='my-test-service', trust_zone='internal-vpc')
+ self.assertEqual('internal-vpc', s.trust_zone)
+ s.trust_zone = 'public-internet'
+ self.assertEqual('public-internet', s.trust_zone)
+
+ def test_trust_zone_affects_equality_and_sorted_set_membership(self) -> None:
+ s1 = Service(name='my-test-service', trust_zone='internal-vpc')
+ s2 = Service(name='my-test-service', trust_zone='public-internet')
+ self.assertNotEqual(s1, s2)
+ self.assertEqual(2, len(SortedSet((s1, s2))))