anthonyharrison / lib4sbom

Library to ingest and generate SBOMs
Apache License 2.0
14 stars 10 forks source link

Functionality Questions for CycloneDX SBOM #12

Closed rhaley-starfish closed 9 months ago

rhaley-starfish commented 10 months ago

Hello Anthony!

I've been very pleased to work with your library for the last few weeks. I have a number of questions that relates to our particular use case producing CycloneDX SBOMs. I have listed all the questions here, but would be happy to open separate tickets if you like. Also, if these turn out to be new features or bugs that you want to include but don't have time to implement, please let me know and I will look at implementing them myself. I have included the python file that helped me generate these questions.

Thanks so much! Russ

from lib4sbom.data.file import SBOMFile
from lib4sbom.data.package import SBOMPackage
from lib4sbom.generator import SBOMGenerator
from lib4sbom.sbom import SBOMData, SBOM
from lib4sbom.data.relationship import SBOMRelationship

import hashlib

def generate_clinician_sbom():
    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")

    sbom_packages = {}

    # Atlantis
    atlantis_pkg = SBOMPackage()
    atlantis_pkg.set_name("Atlantis")
    atlantis_pkg.set_version("1.22.0")
    atlantis_pkg.set_supplier("Author", "Proxyman")
    atlantis_pkg.set_homepage("https://proxyman.io/")
    atlantis_pkg.set_licensedeclared("Apache-2.0")
    atlantis_pkg.set_id(atlantis_pkg.get_name().lower() + "proxyman.io@" + atlantis_pkg.get_value('version'))
    sbom_packages[(atlantis_pkg.get_name(), atlantis_pkg.get_value('version'))] = \
        atlantis_pkg.get_package()

    # Cocoa Lumberjack
    cocoalumberjack_pkg = SBOMPackage()
    cocoalumberjack_pkg.set_name("CocoaLumberjack")
    cocoalumberjack_pkg.set_version("3.8.1")
    cocoalumberjack_pkg.set_supplier("Author", "CocoaLumberjack")
    cocoalumberjack_pkg.set_homepage("https://github.com/CocoaLumberjack")
    cocoalumberjack_pkg.set_licensedeclared("BSD-3-Clause")
    cocoalumberjack_pkg.set_id(cocoalumberjack_pkg.get_name().lower() + "@" + cocoalumberjack_pkg.get_value('version'))
    sbom_packages[(cocoalumberjack_pkg.get_name(), cocoalumberjack_pkg.get_value('version'))] = \
        cocoalumberjack_pkg.get_package()

    # GBDeviceInfo
    gbdeviceinfo_pkg = SBOMPackage()
    gbdeviceinfo_pkg.set_name("GBDeviceInfo")
    gbdeviceinfo_pkg.set_version("7.2.0")
    gbdeviceinfo_pkg.set_supplier("Author", "Luka Mirosevic")
    gbdeviceinfo_pkg.set_homepage("https://github.com/lmirosevic/GBDeviceInfo")
    gbdeviceinfo_pkg.set_licensedeclared("Apache-2.0")
    gbdeviceinfo_pkg.set_id(gbdeviceinfo_pkg.get_name().lower() + "@" + gbdeviceinfo_pkg.get_value('version'))
    gbdeviceinfo_pkg.set_externalreference("vcs", "vcs", "https://github.com/lmirosevic/GBDeviceInfo")
    sbom_packages[(gbdeviceinfo_pkg.get_name(), gbdeviceinfo_pkg.get_value('version'))] = \
        gbdeviceinfo_pkg.get_package()

    # swift-log
    swiftlog_pkg = SBOMPackage()
    swiftlog_pkg.set_name("swift-log")
    swiftlog_pkg.set_version("1.5.2")
    swiftlog_pkg.set_supplier("Author", "Apple Inc.")
    swiftlog_pkg.set_homepage("https://github.com/apple/swift-log")
    # swiftlog_pkg.set_licensedeclared("Apache-2.0")
    swiftlog_pkg.set_licenseconcluded("Apache-2.0")
    swiftlog_pkg.set_id(swiftlog_pkg.get_name().lower() + ".apple.com@" + swiftlog_pkg.get_value('version'))
    sbom_packages[(swiftlog_pkg.get_name(), swiftlog_pkg.get_value('version'))] = \
        swiftlog_pkg.get_package()

    # SwiftTrace
    swifttrace_pkg = SBOMPackage()
    swifttrace_pkg.set_name("SwiftTrace")
    swifttrace_pkg.set_version("8.4.6")
    swifttrace_pkg.set_supplier("Author", "John Holdsworth")
    swifttrace_pkg.set_homepage("https://github.com/johnno1962/SwiftTrace")
    swifttrace_pkg.set_licensedeclared("Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
                                       "of this software and associated documentation files (the \"Software\"), to deal\n"
                                       "in the Software without restriction, including without limitation the rights\n"
                                       "to use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\n"
                                       "copies of the Software, and to permit persons to whom the Software is\n"
                                       "furnished to do so, subject to the following conditions:\n\n"
                                       "The above copyright notice and this permission notice shall be included in\n"
                                       "all copies or substantial portions of the Software.\n\n"
                                       "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
                                       "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
                                       "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
                                       "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
                                       "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
                                       "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"
                                       "THE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\n"
                                       "following github project which is licensed under the terms of that project:\n\n"
                                       "https:\/\/github.com\/OliverLetterer\/imp_implementationForwardingToSelector\n\n"
                                       "Now uses the very handy https:\/\/github.com\/facebook\/fishhook.\n"
                                       "See the source and header files for licensing details.\n")
    swifttrace_pkg.set_id(swifttrace_pkg.get_name().lower() + "@" + swifttrace_pkg.get_value('version'))
    sbom_packages[(swifttrace_pkg.get_name(), swifttrace_pkg.get_value('version'))] = \
        swifttrace_pkg.get_package()

    sbom.add_packages(sbom_packages)
    # relationships = {}
    # rel1 = SBOMRelationship()
    # rel1.set_relationship("CDXRef-DOCUMENT", "CONTAINS", "1-Atlantis")
    # # relationships.append(rel1)
    # # relationships.update(rel1)
    # relationships[(rel1.get_source(), rel1.get_target())] = rel1.get_relationship()
    # sbom.add_relationships(relationships)
    sbg = SBOMGenerator(format='json', sbom_type='cyclonedx')

    sbg.generate("iOSApp", sbom.get_sbom())
    # sbg.generate("iOSApp", sbom.get_sbom(), "mybomy-bom.json")

Output:

{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:62ae0766-846d-4c9d-89f7-c484712e81ba",
  "version": 1,
  "metadata": {
    "timestamp": "2023-08-25T11:55:22Z",
    "tools": [
      {
        "name": "lib4sbom",
        "version": "0.4.2"
      }
    ],
    "component": {
      "type": "application",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "iOSApp"
    }
  },
  "components": [
    {
      "type": "library",
      "bom-ref": "1-Atlantis",
      "name": "Atlantis",
      "version": "1.22.0",
      "supplier": {
        "name": "Proxyman"
      },
      "cpe": "cpe:/a:Proxyman:Atlantis:1.22.0",
      "externalReferences": [
        {
          "url": "https://proxyman.io/",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "2-CocoaLumberjack",
      "name": "CocoaLumberjack",
      "version": "3.8.1",
      "supplier": {
        "name": "CocoaLumberjack"
      },
      "cpe": "cpe:/a:CocoaLumberjack:CocoaLumberjack:3.8.1",
      "externalReferences": [
        {
          "url": "https://github.com/CocoaLumberjack",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "3-GBDeviceInfo",
      "name": "GBDeviceInfo",
      "version": "7.2.0",
      "supplier": {
        "name": "Luka Mirosevic"
      },
      "cpe": "cpe:/a:Luka_Mirosevic:GBDeviceInfo:7.2.0",
      "externalReferences": [
        {
          "url": "https://github.com/lmirosevic/GBDeviceInfo",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "4-swift-log",
      "name": "swift-log",
      "version": "1.5.2",
      "supplier": {
        "name": "Apple Inc."
      },
      "cpe": "cpe:/a:Apple_Inc.:swift-log:1.5.2",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/apple/swift-log",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "5-SwiftTrace",
      "name": "SwiftTrace",
      "version": "8.4.6",
      "supplier": {
        "name": "John Holdsworth"
      },
      "cpe": "cpe:/a:John_Holdsworth:SwiftTrace:8.4.6",
      "externalReferences": [
        {
          "url": "https://github.com/johnno1962/SwiftTrace",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    }
  ],
  "dependencies": []
}
anthonyharrison commented 10 months ago

Thanks for the comments and suggestions @rhaley-starfish .

When I started lib4sbom, the goal was to create a library which allowed the generation of both SPDX and CycloneDX SBOMs using a common data model. As time has ,progressed, and particularly with the latest CycloneDX 1.5 release, there are now more features which are unique to one or other of the SBOM standards.

Some of your comments look like oversights or bugs) to me as multiple SPDX ID licenses should be supported although licence text is not currently supported), and others look relatively easy to accommodate (e.g. metadata settings). However I would question why you would want to explicitly set the UUID - the criteria is that it is unique which is why an automatic function call is used.

rhaley-starfish commented 10 months ago

"however I would question why you would want to explicitly set the UUID - the criteria is that it is unique which is why an automatic function call is used."

My understanding is that unique UUID for each generated SBOM is recommended, not required. The thought was to assign a UUID to each software project and use the document version number for each generation. That way we could trace the SBOM back to a project/software with the UUID. Otherwise we need to rely on external items like project name or file name.

I am going to be talking to some SBOM professionals at Cybeats on Thursday so I can ask them if this is a bad idea. :)

anthonyharrison commented 10 months ago

@rhaley-starfish I think I have addressed most of the issues ( I haven't done the relationships or vulnerabilities comments) . Before I push the changes up, can you check that I am meeting what you are looking for?

Note that I am not sure that CycloneDX allows the license text to be specified as you have done with the SwiftTrace package.

The revised code is (hopefully you can easily spot the differences)

from lib4sbom.data.file import SBOMFile
from lib4sbom.data.package import SBOMPackage
from lib4sbom.data.document import SBOMDocument
from lib4sbom.generator import SBOMGenerator
from lib4sbom.sbom import SBOMData, SBOM
from lib4sbom.data.relationship import SBOMRelationship

import hashlib

def generate_clinician_sbom():
    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")
    sbom.set_uuid("My_uuid_1234")

    sbom_doc = SBOMDocument()
    sbom_doc.set_metadata_type("firmware")
    sbom.add_document(sbom_doc.get_document())

    sbom_packages = {}

    # Atlantis
    atlantis_pkg = SBOMPackage()
    atlantis_pkg.set_name("Atlantis")
    atlantis_pkg.set_version("1.22.0")
    atlantis_pkg.set_supplier("Author", "Proxyman-Friend")
    atlantis_pkg.set_homepage("https://proxyman.io/")
    atlantis_pkg.set_licensedeclared("Apache-2.0")
    atlantis_pkg.set_id(atlantis_pkg.get_name().lower() + "proxyman.io@" + atlantis_pkg.get_value('version'))
    sbom_packages[(atlantis_pkg.get_name(), atlantis_pkg.get_value('version'))] = \
        atlantis_pkg.get_package()

    # Cocoa Lumberjack
    cocoalumberjack_pkg = SBOMPackage()
    cocoalumberjack_pkg.set_name("CocoaLumberjack")
    cocoalumberjack_pkg.set_version("3.8.1")
    cocoalumberjack_pkg.set_supplier("Author", "CocoaLumberjack")
    cocoalumberjack_pkg.set_homepage("https://github.com/CocoaLumberjack")
    cocoalumberjack_pkg.set_licensedeclared("BSD-3-Clause")
    cocoalumberjack_pkg.set_id(cocoalumberjack_pkg.get_name().lower() + "@" + cocoalumberjack_pkg.get_value('version'))
    sbom_packages[(cocoalumberjack_pkg.get_name(), cocoalumberjack_pkg.get_value('version'))] = \
        cocoalumberjack_pkg.get_package()

    # GBDeviceInfo
    gbdeviceinfo_pkg = SBOMPackage()
    gbdeviceinfo_pkg.set_name("GBDeviceInfo")
    gbdeviceinfo_pkg.set_version("7.2.0")
    gbdeviceinfo_pkg.set_supplier("Author", "Luka Mirosevic")
    gbdeviceinfo_pkg.set_homepage("https://github.com/lmirosevic/GBDeviceInfo")
    gbdeviceinfo_pkg.set_licensedeclared("Apache-2.0")
    gbdeviceinfo_pkg.set_id(gbdeviceinfo_pkg.get_name().lower() + "@" + gbdeviceinfo_pkg.get_value('version'))
    gbdeviceinfo_pkg.set_externalreference("vcs", "vcs", "https://github.com/lmirosevic/GBDeviceInfo")
    sbom_packages[(gbdeviceinfo_pkg.get_name(), gbdeviceinfo_pkg.get_value('version'))] = \
        gbdeviceinfo_pkg.get_package()

    # swift-log
    swiftlog_pkg = SBOMPackage()
    swiftlog_pkg.set_name("swift-log")
    swiftlog_pkg.set_version("1.5.2")
    swiftlog_pkg.set_supplier("Author", "Apple Inc.")
    swiftlog_pkg.set_homepage("https://github.com/apple/swift-log")
    # swiftlog_pkg.set_licensedeclared("Apache-2.0")
    swiftlog_pkg.set_licenseconcluded("Apache-2.0")
    swiftlog_pkg.set_id(swiftlog_pkg.get_name().lower() + ".apple.com@" + swiftlog_pkg.get_value('version'))
    sbom_packages[(swiftlog_pkg.get_name(), swiftlog_pkg.get_value('version'))] = \
        swiftlog_pkg.get_package()

    # SwiftTrace
    swifttrace_pkg = SBOMPackage()
    swifttrace_pkg.set_name("SwiftTrace")
    swifttrace_pkg.set_version("8.4.6")
    swifttrace_pkg.set_supplier("Author", "John Holdsworth")
    swifttrace_pkg.set_homepage("https://github.com/johnno1962/SwiftTrace")
    swifttrace_pkg.set_licensedeclared("Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
                                       "of this software and associated documentation files (the \"Software\"), to deal\n"
                                       "in the Software without restriction, including without limitation the rights\n"
                                       "to use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\n"
                                       "copies of the Software, and to permit persons to whom the Software is\n"
                                       "furnished to do so, subject to the following conditions:\n\n"
                                       "The above copyright notice and this permission notice shall be included in\n"
                                       "all copies or substantial portions of the Software.\n\n"
                                       "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
                                       "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
                                       "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
                                       "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
                                       "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
                                       "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"
                                       "THE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\n"
                                       "following github project which is licensed under the terms of that project:\n\n"
                                       "https:\/\/github.com\/OliverLetterer\/imp_implementationForwardingToSelector\n\n"
                                       "Now uses the very handy https:\/\/github.com\/facebook\/fishhook.\n"
                                       "See the source and header files for licensing details.\n")
    swifttrace_pkg.set_id(swifttrace_pkg.get_name().lower() + "@" + swifttrace_pkg.get_value('version'))
    sbom_packages[(swifttrace_pkg.get_name(), swifttrace_pkg.get_value('version'))] = \
        swifttrace_pkg.get_package()

    sbom.add_packages(sbom_packages)
    # relationships = {}
    # rel1 = SBOMRelationship()
    # rel1.set_relationship("CDXRef-DOCUMENT", "CONTAINS", "1-Atlantis")
    # # relationships.append(rel1)
    # # relationships.update(rel1)
    # relationships[(rel1.get_source(), rel1.get_target())] = rel1.get_relationship()
    # sbom.add_relationships(relationships)
    sbg = SBOMGenerator(format='json', sbom_type='cyclonedx', application="My_app", version="0.1Beta")

    sbg.generate("iOSApp", sbom.get_sbom())
    # sbg.generate("iOSApp", sbom.get_sbom(), "mybomy-bom.json")

generate_clinician_sbom()

The output I am now generating is

{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "My_uuid_1234",
  "version": 1,
  "metadata": {
    "timestamp": "2023-09-07T16:49:28Z",
    "tools": [
      {
        "name": "My_app",
        "version": "0.1Beta"
      }
    ],
    "component": {
      "type": "FIRMWARE",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "iOSApp"
    }
  },
  "components": [
    {
      "type": "library",
      "bom-ref": "atlantisproxyman.io@1.22.0",
      "name": "Atlantis",
      "version": "1.22.0",
      "supplier": {
        "name": "Proxyman-Friend"
      },
      "cpe": "cpe:/a:Proxyman-Friend:Atlantis:1.22.0",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://proxyman.io/",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "cocoalumberjack@3.8.1",
      "name": "CocoaLumberjack",
      "version": "3.8.1",
      "supplier": {
        "name": "CocoaLumberjack"
      },
      "cpe": "cpe:/a:CocoaLumberjack:CocoaLumberjack:3.8.1",
      "licenses": [
        {
          "license": {
            "id": "BSD-3-Clause",
            "url": "https://opensource.org/licenses/BSD-3-Clause"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/CocoaLumberjack",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "gbdeviceinfo@7.2.0",
      "name": "GBDeviceInfo",
      "version": "7.2.0",
      "supplier": {
        "name": "Luka Mirosevic"
      },
      "cpe": "cpe:/a:Luka_Mirosevic:GBDeviceInfo:7.2.0",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/lmirosevic/GBDeviceInfo",
          "type": "website",
          "comment": "Home page for project"
        },
        {
          "url": "https://github.com/lmirosevic/GBDeviceInfo",
          "type": "vcs",
          "comment": "vcs"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swift-log.apple.com@1.5.2",
      "name": "swift-log",
      "version": "1.5.2",
      "supplier": {
        "name": "Apple Inc ."
      },
      "cpe": "cpe:/a:Apple_Inc_.:swift-log:1.5.2",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/apple/swift-log",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swifttrace@8.4.6",
      "name": "SwiftTrace",
      "version": "8.4.6",
      "supplier": {
        "name": "John Holdsworth"
      },
      "cpe": "cpe:/a:John_Holdsworth:SwiftTrace:8.4.6",
      "licenses": [
        {
          "license": {
            "name": "Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\\/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\nfollowing github project which is licensed under the terms of that project:\n\nhttps:\\/\\/github.com\\/OliverLetterer\\/imp_implementationForwardingToSelector\n\nNow uses the very handy https:\\/\\/github.com\\/facebook\\/fishhook.\nSee the source and header files for licensing details.\n"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/johnno1962/SwiftTrace",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    }
  ],
  "dependencies": []
}
rhaley-starfish commented 10 months ago

Hi Anthony. This looks like a really great start. I noticed the following details. If these are just reporting discrepancies feel free to ignore;

If you could put your changes on a branch I can run some tests next week? I want to try generating SBOMs with lib4sbom and then importing/exporting in Cybeats and re-importing to lib4sbom.

anthonyharrison commented 10 months ago

@rhaley-starfish

  • metadata.tool value was not lib4sbom (I am assuming that's a test data problem) This is overridden in the call to the SBOMGenerator class. It defaults to lib4sbom iof not specified

  • metadata.component.type is upper case and the specification calls for lower case That was an error. Fixed

  • If we are setting document.uuid then we also need to be able to set version ( I think that was in the last fix, but haven't checked) Now Added.

This code snippet should achieve what I think you are looking for.


    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")
    sbom.set_uuid("My_uuid_1234")
    sbom.set_bom_version("2")

    sbom_doc = SBOMDocument()
    sbom_doc.set_metadata_type("firmware")
    sbom_doc.set_metadata_supplier("Acme Inc.")
    sbom_doc.set_metadata_version("1.0a")
    sbom.add_document(sbom_doc.get_document())
``

Is there anything missing? I will push up a new release in the next few days when I have finished testing.
rhaley-starfish commented 10 months ago

@rhaley-starfish

  • metadata.tool value was not lib4sbom (I am assuming that's a test data problem) This is overridden in the call to the SBOMGenerator class. It defaults to lib4sbom iof not specified

  • metadata.component.type is upper case and the specification calls for lower case That was an error. Fixed

  • If we are setting document.uuid then we also need to be able to set version ( I think that was in the last fix, but haven't checked) Now Added.

This code snippet should achieve what I think you are looking for.

    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")
    sbom.set_uuid("My_uuid_1234")
    sbom.set_bom_version("2")

    sbom_doc = SBOMDocument()
    sbom_doc.set_metadata_type("firmware")
    sbom_doc.set_metadata_supplier("Acme Inc.")
    sbom_doc.set_metadata_version("1.0a")
    sbom.add_document(sbom_doc.get_document())
``

Is there anything missing? I will push up a new release in the next few days when I have finished testing.

Just relationships and vulnerabilities. Everything else looks good. Thanks!

anthonyharrison commented 10 months ago

@rhaley-starfish

I think I have addressed all of your issues I have updated the example to include:

from lib4sbom.data.file import SBOMFile
from lib4sbom.data.package import SBOMPackage
from lib4sbom.data.document import SBOMDocument
from lib4sbom.data.vulnerability import Vulnerability
from lib4sbom.generator import SBOMGenerator
from lib4sbom.sbom import SBOMData, SBOM
from lib4sbom.data.relationship import SBOMRelationship

def generate_sbom():
    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")
    sbom.set_uuid("My_uuid_1234")
    sbom.set_bom_version("2")

    sbom_doc = SBOMDocument()
    sbom_doc.set_metadata_type("firmware")
    sbom_doc.set_metadata_supplier("Acme Inc.")
    sbom_doc.set_metadata_version("1.0a")
    sbom.add_document(sbom_doc.get_document())

    sbom_packages = {}

    # To Level Package
    parent_app = "iOSApp"
    iosapp_pkg = SBOMPackage()
    iosapp_pkg.set_name(parent_app)
    iosapp_pkg.set_version("1")
    iosapp_pkg.set_supplier("Author", "RH")
    iosapp_pkg.set_type("Application")
    iosapp_pkg.set_licensedeclared("Apache-2.0")
    sbom_packages[(iosapp_pkg.get_name(), iosapp_pkg.get_value('version'))] = \
        iosapp_pkg.get_package()

    # swift-log
    swiftlog_pkg = SBOMPackage()
    swiftlog_pkg.set_name("swift-log")
    swiftlog_pkg.set_version("1.5.2")
    swiftlog_pkg.set_supplier("Author", "Apple Inc.")
    swiftlog_pkg.set_homepage("https://github.com/apple/swift-log")
    # swiftlog_pkg.set_licensedeclared("Apache-2.0")
    swiftlog_pkg.set_licenseconcluded("Apache-2.0")
    swiftlog_pkg.set_id(swiftlog_pkg.get_name().lower() + ".apple.com@" + swiftlog_pkg.get_value('version'))
    sbom_packages[(swiftlog_pkg.get_name(), swiftlog_pkg.get_value('version'))] = \
        swiftlog_pkg.get_package()

    # SwiftTrace
    swifttrace_pkg = SBOMPackage()
    swifttrace_pkg.set_name("SwiftTrace")
    swifttrace_pkg.set_version("8.4.6")
    swifttrace_pkg.set_supplier("Author", "John Holdsworth")
    swifttrace_pkg.set_homepage("https://github.com/johnno1962/SwiftTrace")
    swifttrace_pkg.set_licensedeclared("Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
                                       "of this software and associated documentation files (the \"Software\"), to deal\n"
                                       "in the Software without restriction, including without limitation the rights\n"
                                       "to use, copy, modify, merge, publish, distribute, sublicense, and\/or sell\n"
                                       "copies of the Software, and to permit persons to whom the Software is\n"
                                       "furnished to do so, subject to the following conditions:\n\n"
                                       "The above copyright notice and this permission notice shall be included in\n"
                                       "all copies or substantial portions of the Software.\n\n"
                                       "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
                                       "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
                                       "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
                                       "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
                                       "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n"
                                       "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n"
                                       "THE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\n"
                                       "following github project which is licensed under the terms of that project:\n\n"
                                       "https:\/\/github.com\/OliverLetterer\/imp_implementationForwardingToSelector\n\n"
                                       "Now uses the very handy https:\/\/github.com\/facebook\/fishhook.\n"
                                       "See the source and header files for licensing details.\n",
                                       name="SwiftTrace License")
    swifttrace_pkg.set_id(swifttrace_pkg.get_name().lower() + "@" + swifttrace_pkg.get_value('version'))
    sbom_packages[(swifttrace_pkg.get_name(), swifttrace_pkg.get_value('version'))] = \
        swifttrace_pkg.get_package()

    sbom.add_packages(sbom_packages)
    relationships = []
    sbom_relationship = SBOMRelationship()

    for package in sbom.get_packages():
        # Add relationship. All components are direct dependencies.
        sbom_relationship.initialise()
        if package["name"] == parent_app:
            # Parent component
            sbom_relationship.set_relationship(
                "iOSApp_Application", "DESCRIBES", parent_app
            )
        else:
            sbom_relationship.set_relationship(
                    parent_app, "DEPENDS_ON", package["name"]
            )
        relationships.append(sbom_relationship.get_relationship())
    sbom.add_relationships(relationships)

    #### VULNERABILITIES - Normally separate from SBOM
    vulnerabilities = []

    vulnerability = Vulnerability(validation="cyclonedx")
    vulnerability.set_id("CVE-2020-2345")
    vulnerability.set_name(swifttrace_pkg.get_name())
    vulnerability.set_release(swifttrace_pkg.get_value("version"))
    vulnerability.set_value("bom-ref", swifttrace_pkg.get_value("id"))
    vulnerability.set_status("not_affected")
    vulnerability.set_comment("Vulnerable function is not used.")
    vulnerabilities.append(vulnerability.get_vulnerability())

    vulnerability = Vulnerability(validation="cyclonedx")
    vulnerability.set_id("CVE-2023-1235")
    vulnerability.set_name(swifttrace_pkg.get_name())
    vulnerability.set_release(swifttrace_pkg.get_value("version"))
    vulnerability.set_value("bom-ref", swifttrace_pkg.get_value("id"))
    vulnerability.set_status("in_triage")
    vulnerabilities.append(vulnerability.get_vulnerability())

    sbom.add_vulnerabilities(vulnerabilities)

    sbg = SBOMGenerator(format='tag', sbom_type='cyclonedx')

    sbg.generate("iOSApp_Application", sbom.get_sbom())
    # sbg.generate("iOSApp", sbom.get_sbom(), "mybomy-bom.json")

generate_sbom()
``
(I have reduced some of the packages for brevity).

The resulting SBOM 

``json`
{
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "My_uuid_1234",
  "version": "2",
  "metadata": {
    "timestamp": "2023-09-11T18:03:57Z",
    "tools": [
      {
        "name": "lib4sbom",
        "version": "0.5.0"
      }
    ],
    "component": {
      "type": "firmware",
      "supplier": "Acme Inc.",
      "version": "1.0a",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "iOSApp_Application"
    }
  },
  "components": [
    {
      "type": "application",
      "bom-ref": "iOSApp_1",
      "name": "iOSApp",
      "version": "1",
      "supplier": {
        "name": "RH"
      },
      "cpe": "cpe:/a:RH:iOSApp:1",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swift-log.apple.com@1.5.2",
      "name": "swift-log",
      "version": "1.5.2",
      "supplier": {
        "name": "Apple Inc ."
      },
      "cpe": "cpe:/a:Apple_Inc_.:swift-log:1.5.2",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/apple/swift-log",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swifttrace@8.4.6",
      "name": "SwiftTrace",
      "version": "8.4.6",
      "supplier": {
        "name": "John Holdsworth"
      },
      "cpe": "cpe:/a:John_Holdsworth:SwiftTrace:8.4.6",
      "licenses": [
        {
          "license": {
            "name": "SwiftTrace License",
            "text": "Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\\/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\nfollowing github project which is licensed under the terms of that project:\n\nhttps:\\/\\/github.com\\/OliverLetterer\\/imp_implementationForwardingToSelector\n\nNow uses the very handy https:\\/\\/github.com\\/facebook\\/fishhook.\nSee the source and header files for licensing details.\n"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/johnno1962/SwiftTrace",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "CDXRef-DOCUMENT",
      "dependsOn": [
        "1-iOSApp"
      ]
    },
    {
      "ref": "1-iOSApp",
      "dependsOn": [
        "2-swift-log",
        "3-SwiftTrace"
      ]
    }
  ],
  "vulnerabilities": [
    {
      "bom-ref": "swifttrace@8.4.6",
      "id": "CVE-2020-2345",
      "source": {
        "name": "NVD",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-2345"
      },
      "analysis": {
        "state": "not_affected",
        "detail": "Vulnerable function is not used."
      }
    },
    {
      "bom-ref": "swifttrace@8.4.6",
      "id": "CVE-2023-1235",
      "source": {
        "name": "NVD",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-1235"
      },
      "analysis": {
        "state": "in_triage"
      }
    }
  ]
}

If you clone the latest repo, you should be able to reproduce the code.

Let me know if you have any further comments before I will formally release version 0.5.0 of lib4sbom.

rhaley-starfish commented 10 months ago

Fantastic! I will try it out tonight.

rhaley-starfish commented 10 months ago

Hi. Once again, I am NOT a python expert. I am getting an odd error:

(script down below)

C:\temp> python.exe .\inmedix-sbom-firmware2.py
Traceback (most recent call last):
  File "C:\temp\sbom-firmware2.py", line 79, in <module>
    generate_clinician_sbom()
  File "C:\temp\sbom-firmware2.py", line 76, in generate_clinician_sbom
    sbg.generate("inmedix-ans-01", sbom.get_sbom())
  File "C:\Users\russh\git\lib4sbom\build\lib\lib4sbom\generator.py", line 81, in generate
    self._generate_cyclonedx(project_name, sbom_data)
  File "C:\Users\russh\git\lib4sbom\build\lib\lib4sbom\generator.py", line 302, in _generate_cyclonedx
    self.bom.generateComponent(file["name"], "file", file)
  File "C:\Users\russh\git\lib4sbom\build\lib\lib4sbom\cyclonedx\cyclonedx_generator.py", line 195, in generateComponent
    self.generateJSONComponent(id, type, package)
  File "C:\Users\russh\git\lib4sbom\build\lib\lib4sbom\cyclonedx\cyclonedx_generator.py", line 263, in generateJSONComponent
    license_definition = package["licensedeclared"]
                         ~~~~~~~^^^^^^^^^^^^^^^^^^^

I added some debug and printed out the package variable and it's a "file" object that doesn't have either licensedeclared or licenseconcluded but it still falls into the if statement at line 259 (Python is messed man...)???

if "licenseconcluded" or "licensedeclared" in package:
    print(package)

{'name': 'inmedix-ans-01_settings.hex', 'id': 'inmedix-ans-01_settings.hex', 'checksum': [['SHA-1', '49108a02f3faf3ddbff489b2a9e0d252b7f91289']]}

Here is the script:

import sys  
# sys.path.append('C:\\Users\\russh\\git\\lib4sbom\\build\\lib')
sys.path.append('C:\\Users\\russh\\git\\lib4sbom')
from lib4sbom.data.file import SBOMFile
from lib4sbom.data.package import SBOMPackage
from lib4sbom.data.document import SBOMDocument
from lib4sbom.generator import SBOMGenerator
from lib4sbom.sbom import SBOMData, SBOM
from lib4sbom.data.relationship import SBOMRelationship

import hashlib
from uuid import uuid4

def generate_clinician_sbom():
    sbom = SBOM()
    sbom.set_type(sbom_type='cyclonedx')
    sbom.set_version("1.4")
    sbom.set_uuid(str(uuid4()))
    sbom.set_bom_version("2")

    sbom_doc = SBOMDocument()
    sbom_doc.set_name("Clientware-ans-01")
    sbom_doc.set_version("1.7.9")
    sbom_doc.set_type("firmware")

    # sbom_doc.set_metadata_type("firmware")
    sbom.add_document(sbom_doc.get_document())

    sbom_packages = {}

    # NordicSemi Drivers
    nsdrivers_pkg = SBOMPackage()
    nsdrivers_pkg.set_name("libnRF5.a")
    nsdrivers_pkg.set_version("17.0.2")
    nsdrivers_pkg.set_supplier("Author", "Nordic Semiconductor")
    nsdrivers_pkg.set_homepage("https://nordicsemi.com/")
    nsdrivers_pkg.set_licensedeclared("MIT")
    nsdrivers_pkg.set_id(nsdrivers_pkg.get_name().lower() + "nordicsemi@" + nsdrivers_pkg.get_value('version'))
    sbom_packages[(nsdrivers_pkg.get_name(), nsdrivers_pkg.get_value('version'))] =nsdrivers_pkg.get_package()

  # NordicSemi Softdevice
    nssoftdev_pkg = SBOMPackage()
    nssoftdev_pkg.set_name("s140_nrf52_7.2.0_softdeviceq")
    nssoftdev_pkg.set_filename("s140_nrf52_7.2.0_softdevice.hex")
    nssoftdev_pkg.set_version("7.2.0")
    nssoftdev_pkg.set_supplier("Author", "Nordic Semiconductor")
    nssoftdev_pkg.set_homepage("https://nordicsemi.com/")
    nssoftdev_pkg.set_licensedeclared("MIT")
    nssoftdev_pkg.set_id(nssoftdev_pkg.get_name().lower() + "nordicsemi@" + nssoftdev_pkg.get_value('version'))
    sbom_packages[(nssoftdev_pkg.get_name(), nssoftdev_pkg.get_value('version'))] =nssoftdev_pkg.get_package()

  # NordicSemi Bootloader
    nssoftdev_pkg = SBOMPackage()
    nssoftdev_pkg.set_name("ndk17.bootloader.nordicsemi")
    nssoftdev_pkg.set_type("library")
    nssoftdev_pkg.set_version("17.0.2")
    nssoftdev_pkg.set_supplier("Author", "Nordic Semiconductor")
    nssoftdev_pkg.set_homepage("https://nordicsemi.com/")
    nssoftdev_pkg.set_licensedeclared("MIT")
    nssoftdev_pkg.set_id(nssoftdev_pkg.get_name().lower() + "nordicsemi@" + nssoftdev_pkg.get_value('version'))
    sbom_packages[(nssoftdev_pkg.get_name(), nssoftdev_pkg.get_value('version'))] =nssoftdev_pkg.get_package()

    sbom_file = SBOMFile()
    sbom_files = {}
    sbom_file.initialise()
    sbom_file.set_name("Clientware-ans-01_settings.hex")
    # sbom_file.set_filename("Clientware-ans-01_settings.hex")
    file_hash = "49108A02F3FAF3DDBFF489B2A9E0D252B7F91289" 
    sbom_file.set_checksum("SHA-1", file_hash)
    sbom_file.set_id(sbom_file.get_name().lower())
    sbom_files[sbom_file.get_name()] = sbom_file.get_file()

    sbom.add_files(sbom_files)
    sbom.add_packages(sbom_packages)
    sbg = SBOMGenerator(format='json', sbom_type='cyclonedx')

    sbg.generate("Clientware-ans-01", sbom.get_sbom())
    # sbg.generate("Clientware-ans-01", sbom.get_sbom(), "mybomy-bom.json")

generate_clinician_sbom()
rhaley-starfish commented 10 months ago

Ha ha. Answered my own question 2 seconds later:

cyclonedx\cyclonedx_generator.py - line 259 should be:

    if "licenseconcluded" in package or "licensedeclared" in package:
rhaley-starfish commented 10 months ago
anthonyharrison commented 10 months ago

@rhaley-starfish

  • SBOMFile: "id" is being overwritten with "name" somewhere during generation. I tried debugging it but can't tell where it is getting overwritten.

Fixed. However. the sbom_file.set_id(sbom_file.get_name().lower()) results in the id and the name being the same! I assume the set_id call needs to be something else!

  • Relationships still isn't generating any output. I was hoping Relationships would turn into cyclonedx dependencies?

The latest example doesn't have any relationships defined. You need to have a top level component and then define the relationships. See example test.py in the examples directory

  • There seems to be an error in the readme. In the Relationship example you initialize a dictionary, not a list. sbom_relationships = {} should be sbom_relationships = []

Thanks!

Note that the calls to SBOMDocument need to be changed

    sbom_doc = SBOMDocument()
    sbom_doc.set_name("Clientware-ans-01")
    sbom_doc.set_version("1.7.9")
    sbom_doc.set_type("firmware")

to

    sbom_doc = SBOMDocument()
    sbom_doc.set_metadata_version("1.7.9")
    sbom_doc.set_metadata_type("firmware")

I need to tidy up the SBOMDocument section in the README and add a new section to describe the SBOM object as it could be clearer!

rhaley-starfish commented 9 months ago

I'm using commit 6b007bf and I have run into issues validating the SBOM. I am generating with examples/test.py and validating with Cybeats SBOM Studio.

Validating JSON BOM...
Validation failed:
#
#/serialNumber: must match pattern "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
#/version: must be integer
#/metadata/component/supplier: must be object
#/components/2/licenses/0/license/text: must be object
BOM is not valid.

So:

 "licenses": [
        {
          "license": {
            "name": "SwiftTrace License",
            "text": {"content":"..."}
             }
          }

Here is a corrected "valid" sbom generated from test.py

    {
  "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json",
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:1a738f42-bdf3-4c6e-bd79-373579334e1b",
  "version": 2,
  "metadata": {
    "timestamp": "2023-09-12T21:04:03Z",
    "tools": [
      {
        "name": "lib4sbom",
        "version": "0.5.0"
      }
    ],
    "component": {
      "type": "firmware",
      "supplier": {"name":"Acme Inc."},
      "version": "1.0a",
      "bom-ref": "CDXRef-DOCUMENT",
      "name": "iOSApp_Application"
    }
  },
  "components": [
    {
      "type": "application",
      "bom-ref": "iOSApp_Application",
      "name": "iOSApp",
      "version": "1",
      "supplier": {
        "name": "RH"
      },
      "cpe": "cpe:/a:RH:iOSApp:1",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swift-log.apple.com@1.5.2",
      "name": "swift-log",
      "version": "1.5.2",
      "supplier": {
        "name": "Apple Inc ."
      },
      "cpe": "cpe:/a:Apple_Inc_.:swift-log:1.5.2",
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0",
            "url": "https://www.apache.org/licenses/LICENSE-2.0"
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/apple/swift-log",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    },
    {
      "type": "library",
      "bom-ref": "swifttrace@8.4.6",
      "name": "SwiftTrace",
      "version": "8.4.6",
      "supplier": {
        "name": "John Holdsworth"
      },
      "cpe": "cpe:/a:John_Holdsworth:SwiftTrace:8.4.6",
      "licenses": [
        {
          "license": {
            "name": "SwiftTrace License",
            "text": {"content":"Copyright (c) 2015 John Holdsworth\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and\\/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nThis software contains code written by Oliver Letterer obtained from the\nfollowing github project which is licensed under the terms of that project:\n\nhttps:\\/\\/github.com\\/OliverLetterer\\/imp_implementationForwardingToSelector\n\nNow uses the very handy https:\\/\\/github.com\\/facebook\\/fishhook.\nSee the source and header files for licensing details.\n"}
          }
        }
      ],
      "externalReferences": [
        {
          "url": "https://github.com/johnno1962/SwiftTrace",
          "type": "website",
          "comment": "Home page for project"
        }
      ]
    }
  ],
  "dependencies": [
    {
      "ref": "CDXRef-DOCUMENT",
      "dependsOn": [
        "iOSApp_Application"
      ]
    },
    {
      "ref": "iOSApp_Application",
      "dependsOn": [
        "swift-log.apple.com@1.5.2",
        "swifttrace@8.4.6"
      ]
    }
  ],
  "vulnerabilities": [
    {
      "bom-ref": "swifttrace@8.4.6",
      "id": "CVE-2020-2345",
      "source": {
        "name": "NVD",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-2345"
      },
      "analysis": {
        "state": "not_affected",
        "detail": "Vulnerable function is not used."
      }
    },
    {
      "bom-ref": "swifttrace@8.4.6",
      "id": "CVE-2023-1235",
      "source": {
        "name": "NVD",
        "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-1235"
      },
      "analysis": {
        "state": "in_triage"
      }
    }
  ]
}
anthonyharrison commented 9 months ago
  • The serialNumber needs to start with "urn:uuid:". Did your previous set_uuid() add that automatically? I can't remember. Would be nice if it did.

There was no validation on the set_uuid as regards the format. As it is not the normal way of operating, I had assumed that a user specifying a uuid had already ensured that the uuid was in the correct format. However I will add a check to prove that it starts with 'urn:uuid'. - if it doesn't, it will be ignored. The auto-generated uuid does conform to the format.

  • The SBOM version needs to be an integer. The latest build has it in quotes (string)

The set_bom_version parameter can be a string or an integer. Changing the call to set_bom_version(2) will work but I now also convert a string to an integer

  • metadata.component.supplier needs to be an object with a minimum of name: "supplier": {"name":"Acme Inc."},

My mistake. Corrected

My mistake. Corrected

rhaley-starfish commented 9 months ago

I really appreciate your work on this. I've been able to generate and upload a firmware SBOM to Cybeats Studio. I'm happy with the changes.

anthonyharrison commented 9 months ago

Changes included in Release 0.5.0