This CycloneDX module for Python can generate valid CycloneDX bill-of-material document containing an aggregate of all project dependencies.
This module is not designed for standalone use. If you're looking for a tool to run to generate CycloneDX software bill-of-materials documents, why not checkout:
Or you can use this module yourself in your application to generate SBOMs.
CycloneDX is a lightweight BOM specification that is easily created, human-readable, and simple to parse.
Install from pypi.org as you would any other Python module:
pip install cyclonedx-python-lib
This module break out into three key areas:
- Parser: Use a parser that suits your needs to automatically gather information about your environment or application
- Model: Internal models used to unify data from different parsers
- Output: Choose and configure an output which allows you to define output format as well as the CycloneDX schema version
You can use one of the parsers to obtain information about your project or environment. Available parsers:
| Parser | Class / Import | Description |
|---|---|---|
| Environment | from cyclonedx.parser.environment import EnvironmentParser |
Looks at the packaged installed in your current Python environment. |
| RequirementsParser | from cyclonedx.parser.requirements import RequirementsParser |
Parses a multiline string that you provide that conforms to the requirements.txt PEP-508 standard. |
| RequirementsFileParser | from cyclonedx.parser.requirements import RequirementsFileParser |
Parses a file that you provide the path to that conforms to the requirements.txt PEP-508 standard. |
from cyclonedx.parser.environment import EnvironmentParser
parser = EnvironmentParser()
You can create a BOM Model from either an Parser instance or manually using the methods avaialbel directly on the Bom class.
from cyclonedx.model.bom import Bom
from cyclonedx.parser.environment import EnvironmentParser
parser = EnvironmentParser()
bom = Bom.from_parser(parser=parser)
Once you have an instance of a Bom you can produce output in either JSON or XML against any of the supporting CycloneDX schema versions as you require.
We provide two helper methods:
- Output to string (for you to do with as you require)
- Output directly to a filename you provide
from cyclonedx.output import get_instance, OutputFormat
outputter = get_instance(bom=bom, output_format=OutputFormat.JSON)
outputter.output_as_string()
from cyclonedx.output import get_instance, SchemaVersion
outputter = get_instance(bom=bom, schema_version=SchemaVersion.V1_2)
outputter.output_to_file(filename='/tmp/sbom-v1.2.xml')
This library is a work in progress and complete support for all parts of the CycloneDX schema will come in future releases.
Here is a summary of the parts of the schema supported by this library:
Note: We refer throughout using XPath, but the same is true for both XML and JSON output formats.
| XPath | Support v1.3 | Support v1.2 | Support v1.1 | Support v1.0 | Notes |
|---|---|---|---|---|---|
/bom |
Y | Y | Y | Y | This is the root element and is supported with all it's defined attributes. |
/bom/metadata |
Y | Y | N/A | N/A |
Only timestamp is currently supported
|
/bom/components |
Y | Y | Y | Y | |
/bom/components/component |
|||||
./author |
Y | Y | N/A | N/A | |
./name |
Y | Y | Y | Y | |
./version |
Y | Y | Y | Y | |
./purl |
Y | Y | Y | Y | |
- N/A is where the CycloneDX standard does not include this
- If the table above does not refer to an element, it is not currently supported
We endeavour to support all functionality for all current actively supported Python versions. However, some features may not be possible/present in older Python versions due to their lack of support.
Remember:
It is worth noting that this is NOT SUPPORTED by Sonatype, and is a contribution of ours to the open source community (read: you!)
- Use this contribution at the risk tolerance that you have
- Do NOT file Sonatype support tickets related to
cyclonedx-python-libsupport in regard to this project - DO file issues here on GitHub, so that the community can pitch in
Phew, that was easier than I thought. Last but not least of all - have fun!