1515 An fetched project generates an sbom
1616"""
1717
18+ from decimal import Decimal
1819from typing import List
1920
2021from cyclonedx .builder .this import this_component as cdx_lib_component
2122from cyclonedx .model import ExternalReference , ExternalReferenceType , XsUri
2223from cyclonedx .model .bom import Bom
2324from cyclonedx .model .component import Component , ComponentType
24- from cyclonedx .model .license import LicenseExpression
25- from cyclonedx .model .tool import Tool
25+ from cyclonedx .model .component_evidence import (
26+ AnalysisTechnique ,
27+ ComponentEvidence ,
28+ Identity ,
29+ IdentityField ,
30+ Method ,
31+ Occurrence ,
32+ )
33+ from cyclonedx .model .contact import OrganizationalEntity
34+ from cyclonedx .model .license import DisjunctiveLicense as CycloneDxLicense
2635from cyclonedx .output import make_outputter
2736from cyclonedx .schema import OutputFormat , SchemaVersion
2837
4049class SbomReporter (Reporter ):
4150 """Reporter for generating SBoM's."""
4251
43- dfetch_tool = Tool (vendor = "dfetch-org" , name = "dfetch" , version = dfetch .__version__ )
52+ dfetch_tool = Component (
53+ type = ComponentType .APPLICATION ,
54+ supplier = OrganizationalEntity (name = "dfetch-org" ),
55+ name = "dfetch" ,
56+ version = dfetch .__version__ ,
57+ bom_ref = f"dfetch-{ dfetch .__version__ } " ,
58+ licenses = [CycloneDxLicense (name = "MIT License" , id = "MIT" )],
59+ external_references = [
60+ ExternalReference (
61+ type = ExternalReferenceType .VCS ,
62+ url = XsUri ("https://github.com/dfetch-org/dfetch" ),
63+ ),
64+ ExternalReference (
65+ type = ExternalReferenceType .BUILD_SYSTEM ,
66+ url = XsUri ("https://github.com/dfetch-org/dfetch/actions" ),
67+ ),
68+ ExternalReference (
69+ type = ExternalReferenceType .ISSUE_TRACKER ,
70+ url = XsUri ("https://github.com/dfetch-org/dfetch/issues" ),
71+ ),
72+ ExternalReference (
73+ type = ExternalReferenceType .DISTRIBUTION ,
74+ url = XsUri ("https://pypi.org/project/dfetch/" ),
75+ ),
76+ ExternalReference (
77+ type = ExternalReferenceType .DOCUMENTATION ,
78+ url = XsUri ("https://dfetch.readthedocs.io/" ),
79+ ),
80+ ExternalReference (
81+ type = ExternalReferenceType .LICENSE ,
82+ url = XsUri ("https://github.com/dfetch-org/dfetch/blob/main/LICENSE" ),
83+ ),
84+ ExternalReference (
85+ type = ExternalReferenceType .RELEASE_NOTES ,
86+ url = XsUri (
87+ "https://github.com/dfetch-org/dfetch/blob/main/CHANGELOG.rst"
88+ ),
89+ ),
90+ ExternalReference (
91+ type = ExternalReferenceType .WEBSITE ,
92+ url = XsUri ("https://dfetch-org.github.io/" ),
93+ ),
94+ ],
95+ )
4496
4597 name = "SBoM"
4698
4799 def __init__ (self ) -> None :
48100 """Start the report."""
49101 self ._bom = Bom ()
50- self ._bom .metadata .tools .tools .add (self .dfetch_tool )
102+ self ._bom .metadata .tools .components .add (self .dfetch_tool )
51103 self ._bom .metadata .tools .components .add (cdx_lib_component ())
52104
53105 def add_project (
@@ -66,6 +118,47 @@ def add_project(
66118 version = version ,
67119 type = ComponentType .LIBRARY ,
68120 purl = purl ,
121+ evidence = ComponentEvidence (
122+ occurrences = [Occurrence (location = "dfetch.yaml" )],
123+ identity = [
124+ Identity (
125+ field = IdentityField .NAME ,
126+ tools = [self .dfetch_tool .bom_ref ],
127+ methods = [
128+ Method (
129+ technique = AnalysisTechnique .MANIFEST_ANALYSIS ,
130+ confidence = Decimal .from_float (0.4 ),
131+ value = "Name as used for project in dfetch.yaml" ,
132+ )
133+ ],
134+ concluded_value = project .name ,
135+ ),
136+ Identity (
137+ field = IdentityField .VERSION ,
138+ tools = [self .dfetch_tool .bom_ref ],
139+ methods = [
140+ Method (
141+ technique = AnalysisTechnique .MANIFEST_ANALYSIS ,
142+ confidence = Decimal .from_float (0.4 ),
143+ value = "Version as used for project in dfetch.yaml" ,
144+ )
145+ ],
146+ concluded_value = version ,
147+ ),
148+ Identity (
149+ field = IdentityField .PURL ,
150+ tools = [self .dfetch_tool .bom_ref ],
151+ methods = [
152+ Method (
153+ technique = AnalysisTechnique .MANIFEST_ANALYSIS ,
154+ confidence = Decimal .from_float (0.4 ),
155+ value = "Determined from the VCS url as used for project in dfetch.yaml" ,
156+ )
157+ ],
158+ concluded_value = purl .to_string (),
159+ ),
160+ ],
161+ ),
69162 )
70163
71164 if purl .type == "github" :
@@ -96,7 +189,12 @@ def add_project(
96189 )
97190
98191 for lic in licenses :
99- component .licenses .add (LicenseExpression (lic .name ))
192+ cdx_license = CycloneDxLicense (name = lic .name , id = lic .spdx_id )
193+
194+ component .licenses .add (cdx_license )
195+ if component .evidence :
196+ component .evidence .licenses .add (cdx_license .bom_ref )
197+
100198 self ._bom .components .add (component )
101199
102200 def dump_to_file (self , outfile : str ) -> bool :
0 commit comments