from loguru import logger import yaml import uuid from packageurl import PackageURL from cyclonedx.builder.this import this_component as cdx_lib_component from cyclonedx.factory.license import LicenseFactory from cyclonedx.model.bom import Bom from cyclonedx.model.component import Component, ComponentType from cyclonedx.model.contact import OrganizationalEntity from cyclonedx.model import XsUri from cyclonedx.model import ExternalReference from cyclonedx.output.json import JsonV1Dot5 class MyLocalConverterException(Exception): pass def __converterClassifierToComponentType(classifier): componentType = '' match classifier: case 'APPLICATION': componentType = ComponentType.APPLICATION case 'FRAMEWORK': componentType = ComponentType.FRAMEWORK case 'LIBRARY': componentType = ComponentType.LIBRARY case 'CONTAINER': componentType = ComponentType.CONTAINER case 'OPERATING_SYSTEM': componentType = ComponentType.OPERATING_SYSTEM case 'DEVICE': componentType = ComponentType.DEVICE case 'FIRMWARE': componentType = ComponentType.FIRMWARE case 'FILE': componentType = ComponentType.FILE case 'PLATFORM': componentType = ComponentType.PLATFORM case 'DEVICE_DRIVER': componentType = ComponentType.DEVICE_DRIVER case 'MACHINE_LEARNING_MODEL': componentType = ComponentType.MACHINE_LEARNING_MODEL case 'DATA': componentType = ComponentType.DATA case _: raise MyLocalConverterException(f"No componentType for {classifier} found") return componentType def minimalSbomFormatConverter(minimalSbom, classifier): logger.info(f"Minimal input: {minimalSbom}") lc_factory = LicenseFactory() minimalSbomObject = yaml.safe_load(minimalSbom) logger.debug(f"{minimalSbomObject=}") bom = Bom( version=minimalSbomObject['sbomVersion'] ) bom.metadata.tools.components.add(cdx_lib_component()) bom.metadata.tools.components.add(Component( name='sbom-dt-dd', type=ComponentType.APPLICATION )) bom.metadata.component = root_component = Component( name=minimalSbomObject['product'], type=__converterClassifierToComponentType(minimalSbomObject['classifier']), description=minimalSbomObject['description'], version=minimalSbomObject['version'], licenses=[lc_factory.make_from_string(minimalSbomObject['license'])], supplier=OrganizationalEntity( name=minimalSbomObject['supplier']['name'], urls=[XsUri(minimalSbomObject['supplier']['url'])] ), bom_ref = f"urn:uuid:{uuid.uuid4()}" ) component = Component( type=__converterClassifierToComponentType(minimalSbomObject['classifier']), name=f"{minimalSbomObject['supplier']['name']}´s own code", version=minimalSbomObject['version'], licenses=[lc_factory.make_from_string(minimalSbomObject['license'])], supplier=OrganizationalEntity( name=minimalSbomObject['supplier']['name'], urls=[XsUri(minimalSbomObject['supplier']['url'])] ), bom_ref = f"urn:uuid:{uuid.uuid4()}" ) bom.components.add(component) bom.register_dependency(root_component, [component]) for minimalComponentDescription in minimalSbomObject['components']: component = Component( type=ComponentType.LIBRARY, name=minimalComponentDescription['name'], version=minimalComponentDescription['version'], licenses=[lc_factory.make_from_string(minimalComponentDescription['license'])], bom_ref = f"urn:uuid:{uuid.uuid4()}" ) if 'cpe' in minimalComponentDescription: component.cpe = minimalComponentDescription['cpe'] if 'purl' in minimalComponentDescription: component.purl = PackageURL.from_string(minimalComponentDescription['purl']) bom.components.add(component) bom.register_dependency(root_component, [component]) outputSbom = JsonV1Dot5(bom).output_as_string(indent=2) logger.info(outputSbom) with open('/tmp/bom.json', 'w') as f: f.write(outputSbom) return (outputSbom, minimalSbomObject['product'], minimalSbomObject['version'], minimalSbomObject['classifier'], minimalSbomObject['description'])