Skip to content

Commit 209b3d1

Browse files
committed
feat: add support for component's evidences according to spec
Signed-off-by: Arun <[email protected]>
1 parent cb1a359 commit 209b3d1

15 files changed

+1730
-32
lines changed

cyclonedx/model/component.py

Lines changed: 713 additions & 32 deletions
Large diffs are not rendered by default.

tests/_data/models.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,23 @@
4444
from cyclonedx.model.bom import Bom, BomMetaData
4545
from cyclonedx.model.bom_ref import BomRef
4646
from cyclonedx.model.component import (
47+
AnalysisTechnique,
48+
CallStack,
4749
Commit,
4850
Component,
4951
ComponentEvidence,
5052
ComponentScope,
5153
ComponentType,
5254
Diff,
55+
Identity,
56+
IdentityFieldType,
57+
Method,
58+
Occurrence,
5359
OmniborId,
5460
Patch,
5561
PatchClassification,
5662
Pedigree,
63+
StackFrame,
5764
Swhid,
5865
Swid,
5966
)
@@ -455,6 +462,35 @@ def get_bom_with_component_setuptools_complete() -> Bom:
455462
return _make_bom(components=[get_component_setuptools_complete()])
456463

457464

465+
def get_bom_with_component_evidence() -> Bom:
466+
bom = _make_bom()
467+
tool_component = Component(
468+
name='product-cbom-generator',
469+
type=ComponentType.APPLICATION,
470+
bom_ref='cbom:generator'
471+
)
472+
bom.metadata.tools.components.add(tool_component)
473+
bom.metadata.component = Component(
474+
name='root-component',
475+
type=ComponentType.APPLICATION,
476+
licenses=[DisjunctiveLicense(id='MIT')],
477+
bom_ref='myApp',
478+
)
479+
component = Component(
480+
name='setuptools', version='50.3.2',
481+
bom_ref='pkg:pypi/[email protected]?extension=tar.gz',
482+
purl=PackageURL(
483+
type='pypi', name='setuptools', version='50.3.2', qualifiers='extension=tar.gz'
484+
),
485+
licenses=[DisjunctiveLicense(id='MIT')],
486+
author='Test Author'
487+
)
488+
component.evidence = get_component_evidence_basic(tool=tool_component.bom_ref, bom_ref='ref:setuptools')
489+
bom.components.add(component)
490+
bom.register_dependency(bom.metadata.component, depends_on=[component])
491+
return bom
492+
493+
458494
def get_bom_with_component_setuptools_with_vulnerability() -> Bom:
459495
bom = _make_bom()
460496
component = get_component_setuptools_simple()
@@ -737,6 +773,55 @@ def get_component_setuptools_complete(include_pedigree: bool = True) -> Componen
737773
return component
738774

739775

776+
def get_component_evidence_basic(tool: BomRef, bom_ref: str) -> ComponentEvidence:
777+
"""
778+
Returns a basic ComponentEvidence object for testing.
779+
"""
780+
return ComponentEvidence(
781+
identity=[
782+
Identity(
783+
field=IdentityFieldType.NAME,
784+
confidence=Decimal('0.9'),
785+
concluded_value='example-component',
786+
methods=[
787+
Method(
788+
technique=AnalysisTechnique.SOURCE_CODE_ANALYSIS,
789+
confidence=Decimal('0.8'), value='analysis-tool'
790+
)
791+
],
792+
tools=[tool]
793+
)
794+
],
795+
occurrences=[
796+
Occurrence(
797+
location='path/to/file',
798+
line=42,
799+
offset=16,
800+
symbol='exampleSymbol',
801+
additional_context='Found in source code',
802+
bom_ref=bom_ref,
803+
)
804+
],
805+
callstack=CallStack(
806+
frames=[
807+
StackFrame(
808+
package='example.package',
809+
module='example.module',
810+
function='example_function',
811+
parameters=['param1', 'param2'],
812+
line=10,
813+
column=5,
814+
full_filename='path/to/file',
815+
)
816+
]
817+
),
818+
licenses=[DisjunctiveLicense(id='MIT')],
819+
copyright=[
820+
Copyright(text='Commercial'), Copyright(text='Commercial 2')
821+
]
822+
)
823+
824+
740825
def get_component_setuptools_simple(
741826
bom_ref: Optional[str] = 'pkg:pypi/[email protected]?extension=tar.gz'
742827
) -> Component:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" ?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.0" version="1">
3+
<components>
4+
<component type="library">
5+
<name>setuptools</name>
6+
<version>50.3.2</version>
7+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
8+
<modified>false</modified>
9+
</component>
10+
</components>
11+
</bom>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" ?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.1" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
3+
<components>
4+
<component type="library" bom-ref="pkg:pypi/[email protected]?extension=tar.gz">
5+
<name>setuptools</name>
6+
<version>50.3.2</version>
7+
<licenses>
8+
<license>
9+
<id>MIT</id>
10+
</license>
11+
</licenses>
12+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
13+
</component>
14+
</components>
15+
</bom>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"components": [
3+
{
4+
"author": "Test Author",
5+
"bom-ref": "pkg:pypi/[email protected]?extension=tar.gz",
6+
"licenses": [
7+
{
8+
"license": {
9+
"id": "MIT"
10+
}
11+
}
12+
],
13+
"name": "setuptools",
14+
"purl": "pkg:pypi/[email protected]?extension=tar.gz",
15+
"type": "library",
16+
"version": "50.3.2"
17+
}
18+
],
19+
"dependencies": [
20+
{
21+
"dependsOn": [
22+
"pkg:pypi/[email protected]?extension=tar.gz"
23+
],
24+
"ref": "myApp"
25+
},
26+
{
27+
"ref": "pkg:pypi/[email protected]?extension=tar.gz"
28+
}
29+
],
30+
"metadata": {
31+
"component": {
32+
"bom-ref": "myApp",
33+
"licenses": [
34+
{
35+
"license": {
36+
"id": "MIT"
37+
}
38+
}
39+
],
40+
"name": "root-component",
41+
"type": "application",
42+
"version": ""
43+
},
44+
"timestamp": "2023-01-07T13:44:32.312678+00:00",
45+
"tools": [
46+
{
47+
"name": "product-cbom-generator"
48+
}
49+
]
50+
},
51+
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
52+
"version": 1,
53+
"$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json",
54+
"bomFormat": "CycloneDX",
55+
"specVersion": "1.2"
56+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" ?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.2" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
3+
<metadata>
4+
<timestamp>2023-01-07T13:44:32.312678+00:00</timestamp>
5+
<tools>
6+
<tool>
7+
<name>product-cbom-generator</name>
8+
</tool>
9+
</tools>
10+
<component type="application" bom-ref="myApp">
11+
<name>root-component</name>
12+
<version/>
13+
<licenses>
14+
<license>
15+
<id>MIT</id>
16+
</license>
17+
</licenses>
18+
</component>
19+
</metadata>
20+
<components>
21+
<component type="library" bom-ref="pkg:pypi/[email protected]?extension=tar.gz">
22+
<author>Test Author</author>
23+
<name>setuptools</name>
24+
<version>50.3.2</version>
25+
<licenses>
26+
<license>
27+
<id>MIT</id>
28+
</license>
29+
</licenses>
30+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
31+
</component>
32+
</components>
33+
<dependencies>
34+
<dependency ref="myApp">
35+
<dependency ref="pkg:pypi/[email protected]?extension=tar.gz"/>
36+
</dependency>
37+
<dependency ref="pkg:pypi/[email protected]?extension=tar.gz"/>
38+
</dependencies>
39+
</bom>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"components": [
3+
{
4+
"author": "Test Author",
5+
"bom-ref": "pkg:pypi/[email protected]?extension=tar.gz",
6+
"evidence": {
7+
"copyright": [
8+
{
9+
"text": "Commercial"
10+
},
11+
{
12+
"text": "Commercial 2"
13+
}
14+
],
15+
"licenses": [
16+
{
17+
"license": {
18+
"id": "MIT"
19+
}
20+
}
21+
]
22+
},
23+
"licenses": [
24+
{
25+
"license": {
26+
"id": "MIT"
27+
}
28+
}
29+
],
30+
"name": "setuptools",
31+
"purl": "pkg:pypi/[email protected]?extension=tar.gz",
32+
"type": "library",
33+
"version": "50.3.2"
34+
}
35+
],
36+
"dependencies": [
37+
{
38+
"dependsOn": [
39+
"pkg:pypi/[email protected]?extension=tar.gz"
40+
],
41+
"ref": "myApp"
42+
},
43+
{
44+
"ref": "pkg:pypi/[email protected]?extension=tar.gz"
45+
}
46+
],
47+
"metadata": {
48+
"component": {
49+
"bom-ref": "myApp",
50+
"licenses": [
51+
{
52+
"license": {
53+
"id": "MIT"
54+
}
55+
}
56+
],
57+
"name": "root-component",
58+
"type": "application",
59+
"version": ""
60+
},
61+
"timestamp": "2023-01-07T13:44:32.312678+00:00",
62+
"tools": [
63+
{
64+
"name": "product-cbom-generator"
65+
}
66+
]
67+
},
68+
"serialNumber": "urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac",
69+
"version": 1,
70+
"$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json",
71+
"bomFormat": "CycloneDX",
72+
"specVersion": "1.3"
73+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" ?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.3" serialNumber="urn:uuid:1441d33a-e0fc-45b5-af3b-61ee52a88bac" version="1">
3+
<metadata>
4+
<timestamp>2023-01-07T13:44:32.312678+00:00</timestamp>
5+
<tools>
6+
<tool>
7+
<name>product-cbom-generator</name>
8+
</tool>
9+
</tools>
10+
<component type="application" bom-ref="myApp">
11+
<name>root-component</name>
12+
<version/>
13+
<licenses>
14+
<license>
15+
<id>MIT</id>
16+
</license>
17+
</licenses>
18+
</component>
19+
</metadata>
20+
<components>
21+
<component type="library" bom-ref="pkg:pypi/[email protected]?extension=tar.gz">
22+
<author>Test Author</author>
23+
<name>setuptools</name>
24+
<version>50.3.2</version>
25+
<licenses>
26+
<license>
27+
<id>MIT</id>
28+
</license>
29+
</licenses>
30+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
31+
<evidence>
32+
<licenses>
33+
<license>
34+
<id>MIT</id>
35+
</license>
36+
</licenses>
37+
<copyright>
38+
<text>Commercial</text>
39+
<text>Commercial 2</text>
40+
</copyright>
41+
</evidence>
42+
</component>
43+
</components>
44+
<dependencies>
45+
<dependency ref="myApp">
46+
<dependency ref="pkg:pypi/[email protected]?extension=tar.gz"/>
47+
</dependency>
48+
<dependency ref="pkg:pypi/[email protected]?extension=tar.gz"/>
49+
</dependencies>
50+
</bom>

0 commit comments

Comments
 (0)