Skip to content

Commit 7fb6da9

Browse files
madpahjkowalleck
andauthored
Support for CycloneDX schema version 1.4 (#108)
BREAKING CHANGE: Support for CycloneDX 1.4. This includes: - Support for `tools` having `externalReferences` - Allowing `version` for a `Component` to be optional in 1.4 - Support for `releaseNotes` per `Component` - Support for the core schema implementation of Vulnerabilities (VEX) Other changes included in this PR: - Unit tests now include schema validation (we've left schema validation out of the core library due to dependency bloat) - Fixes to ensure schema is adhered to in 1.0 - URI's are now used throughout the library through a new `XsUri` class to provide URI validation - Documentation is now hosted on readthedocs.org (https://cyclonedx-python-library.readthedocs.io/) - `$schema` is now included in JSON BOMs - Concrete Parsers how now been moved into downstream projects to keep this libraries focus on modelling and outputting CycloneDX - see https://github.com/CycloneDX/cyclonedx-python - Added reference to release of this library on Anaconda Signed-off-by: Paul Horton <[email protected]> Signed-off-by: Jan Kowalleck <[email protected]> Co-authored-by: Paul Horton <[email protected]> Co-authored-by: Jan Kowalleck <[email protected]>
1 parent 3058afc commit 7fb6da9

File tree

100 files changed

+10510
-3735
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+10510
-3735
lines changed

.github/workflows/docs.yml

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
1-
name: Manual Release Candidate
1+
name: Manual Pre Release Publish
22

33
on:
44
workflow_dispatch:
55
inputs:
6-
branch:
7-
description: 'Branch to produce Release Candidate from'
6+
release_candidate_suffix:
7+
description: 'RC Suffix e.g. rc0, beta1, alpha2. Do not include a leading hyphen.'
88
required: true
99
type: string
10-
rc_number:
11-
description: 'RC Number'
12-
default: 0
13-
required: true
14-
type: number
1510

1611
jobs:
17-
release:
12+
release_candidate:
1813
runs-on: ubuntu-latest
19-
concurrency: release
14+
concurrency: release_candidate
2015
steps:
2116
- name: Checkout code
2217
uses: actions/checkout@v2
@@ -31,12 +26,13 @@ jobs:
3126
poetry config virtualenvs.create false
3227
poetry install
3328
python -m pip install python-semantic-release
34-
- name: Determine RC candidate version
29+
- name: Apply Pre Release Version
3530
run: |
36-
RC_VERSION="$(python-semantic-release --noop --major print-version)rc${{ inputs.rc_number }})"
31+
RC_VERSION="$(semantic-release --noop --major print-version)-${{ github.event.inputs.release_candidate_suffix }}"
3732
echo "RC Version will be: ${RC_VERSION}"
38-
# - name: Python Semantic Release
39-
# uses: relekang/python-semantic-release@master
40-
# with:
41-
# github_token: ${{ secrets.GITHUB_TOKEN }}
42-
# pypi_token: ${{ secrets.PYPI_TOKEN }}
33+
poetry version ${RC_VERSION}
34+
poetry build
35+
- name: Publish Pre Release 📦 to PyPI
36+
uses: pypa/gh-action-pypi-publish@master
37+
with:
38+
password: ${{ secrets.PYPI_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ html/
2626

2727
# mypy caches
2828
/.mypy_cache
29+
30+
# Exlude built docs
31+
docs/_build

.readthedocs.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# encoding: utf-8
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
#
15+
# SPDX-License-Identifier: Apache-2.0
16+
17+
# Read the Docs configuration file
18+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
19+
20+
# Required
21+
version: 2
22+
23+
# Set the version of Python and other tools you might need
24+
build:
25+
os: ubuntu-20.04
26+
tools:
27+
python: "3.9"
28+
# You can also specify other tool versions:
29+
# nodejs: "16"
30+
# rust: "1.55"
31+
# golang: "1.17"
32+
33+
# Build documentation in the docs/ directory with Sphinx
34+
sphinx:
35+
configuration: docs/conf.py
36+
37+
# Formats
38+
formats: all
39+
40+
# Optionally declare the Python requirements required to build your docs
41+
python:
42+
install:
43+
- method: pip
44+
path: .
45+
- requirements: docs/requirements.txt

README.md

Lines changed: 5 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
[![shield_gh-workflow-test]][link_gh-workflow-test]
44
[![shield_pypi-version]][link_pypi]
5+
[![shield_conda-forge-version]][link_conda-forge]
56
[![shield_license]][license_file]
67
[![shield_website]][link_website]
78
[![shield_slack]][link_slack]
@@ -22,199 +23,7 @@ Additionally, you can use this module yourself in your application to programmat
2223

2324
CycloneDX is a lightweight BOM specification that is easily created, human-readable, and simple to parse.
2425

25-
## Installation
26-
27-
Install from pypi.org as you would any other Python module:
28-
29-
```shell
30-
pip install cyclonedx-python-lib
31-
```
32-
33-
## Architecture
34-
35-
This module break out into three key areas:
36-
37-
1. **Parser**: Use a parser that suits your needs to automatically gather information about your environment or
38-
application
39-
2. **Model**: Internal models used to unify data from different parsers
40-
3. **Output**: Choose and configure an output which allows you to define output format as well as the CycloneDX schema
41-
version
42-
43-
### Parsing
44-
45-
You can use one of the parsers to obtain information about your project or environment. Available parsers:
46-
47-
| Parser | Class / Import | Description |
48-
| ------- | ------ | ------ |
49-
| CondaListJsonParser | `from cyclonedx.parser.conda import CondaListJsonParser` | Parses input provided as a `str` that is output from `conda list --json` |
50-
| CondaListExplicitParser | `from cyclonedx.parser.conda import CondaListExplicitParser` | Parses input provided as a `str` that is output from `conda list --explicit` or `conda list --explicit --md5` |
51-
| Environment | `from cyclonedx.parser.environment import EnvironmentParser` | Looks at the packaged installed in your current Python environment. |
52-
| PipEnvParser | `from cyclonedx.parser.pipenv import PipEnvParser` | Parses `Pipfile.lock` content passed in as a string. |
53-
| PipEnvFileParser | `from cyclonedx.parser.pipenv import PipEnvFileParser` | Parses the `Pipfile.lock` file at the supplied path. |
54-
| PoetryParser | `from cyclonedx.parser.poetry import PoetryParser` | Parses `poetry.lock` content passed in as a string. |
55-
| PoetryFileParser | `from cyclonedx.parser.poetry import PoetryFileParser` | Parses the `poetry.lock` file at the supplied path. |
56-
| RequirementsParser | `from cyclonedx.parser.requirements import RequirementsParser` | Parses a multiline string that you provide that conforms to the `requirements.txt` [PEP-508] standard. |
57-
| 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. |
58-
59-
#### Example
60-
61-
```py
62-
from cyclonedx.parser.environment import EnvironmentParser
63-
64-
parser = EnvironmentParser()
65-
```
66-
67-
#### Notes on Requirements parsing
68-
69-
CycloneDX software bill-of-materials require pinned versions of requirements. If your `requirements.txt` does not have
70-
pinned versions, warnings will be recorded and the dependencies without pinned versions will be excluded from the
71-
generated CycloneDX. CycloneDX schemas (from version 1.0+) require a component to have a version when included in a
72-
CycloneDX bill of materials (according to schema).
73-
74-
If you need to use a `requirements.txt` in your project that does not have pinned versions an acceptable workaround
75-
might be to:
76-
77-
```shell
78-
pip install -r requirements.txt
79-
pip freeze > requirements-frozen.txt
80-
```
81-
82-
You can then feed in the frozen requirements from `requirements-frozen.txt` _or_ use the `Environment` parser one you
83-
have `pip install`ed your dependencies.
84-
85-
### Modelling
86-
87-
You can create a BOM Model from either a Parser instance or manually using the methods avaialbel directly on the `Bom` class.
88-
89-
The model also supports definition of vulnerabilities for output using the CycloneDX schema extension for
90-
[Vulnerability Disclosures](https://cyclonedx.org/use-cases/#vulnerability-disclosure) as of version 0.3.0.
91-
92-
**Note:** Known vulnerabilities associated with Components can be sourced from various data sources, but this library
93-
will not source them for you. Perhaps look at [Jake][jake] if you're interested in this.
94-
95-
#### Example from a Parser
96-
97-
```py
98-
from cyclonedx.model.bom import Bom
99-
from cyclonedx.parser.environment import EnvironmentParser
100-
101-
parser = EnvironmentParser()
102-
bom = Bom.from_parser(parser=parser)
103-
```
104-
105-
### Generating Output
106-
107-
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.
108-
109-
We provide two helper methods:
110-
111-
* Output to string (for you to do with as you require)
112-
* Output directly to a filename you provide
113-
114-
#### Example as JSON
115-
116-
```py
117-
from cyclonedx.output import get_instance, OutputFormat
118-
119-
outputter = get_instance(bom=bom, output_format=OutputFormat.JSON)
120-
outputter.output_as_string()
121-
```
122-
123-
#### Example as XML
124-
125-
```py
126-
from cyclonedx.output import get_instance, SchemaVersion
127-
128-
outputter = get_instance(bom=bom, schema_version=SchemaVersion.V1_2)
129-
outputter.output_to_file(filename='/tmp/sbom-v1.2.xml')
130-
```
131-
132-
## Library API Documentation
133-
134-
The Library API Documentation is available online at [https://cyclonedx.github.io/cyclonedx-python-lib/](https://cyclonedx.github.io/cyclonedx-python-lib/).
135-
136-
## Schema Support
137-
138-
This library is a work in progress and complete support for all parts of the CycloneDX schema will come in future releases.
139-
140-
Here is a summary of the parts of the schema supported by this library:
141-
142-
_Note: We refer throughout using XPath, but the same is true for both XML and JSON output formats._
143-
144-
<table width="100%">
145-
<thead>
146-
<tr>
147-
<th>XPath</th>
148-
<th>Support v1.3</th>
149-
<th>Support v1.2</th>
150-
<th>Support v1.1</th>
151-
<th>Support v1.0</th>
152-
<th>Notes</th>
153-
</tr>
154-
</thead>
155-
<tbody>
156-
<tr>
157-
<td><code>/bom</code></td>
158-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
159-
<td>
160-
This is the root element and is supported with all it's defined attributes.
161-
</td>
162-
</tr>
163-
<tr>
164-
<td><code>/bom/metadata</code></td>
165-
<td>Y</td><td>Y</td><td>N/A</td><td>N/A</td>
166-
<td>
167-
<code>timestamp</code> and <code>tools</code> are currently supported
168-
</td>
169-
</tr>
170-
<tr>
171-
<td><code>/bom/components</code></td>
172-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
173-
<td>&nbsp;</td>
174-
</tr>
175-
<tr>
176-
<th colspan="6"><strong><code>/bom/components/component</code></strong></th>
177-
</tr>
178-
<tr>
179-
<td><code>./author</code></td>
180-
<td>Y</td><td>Y</td><td>N/A</td><td>N/A</td>
181-
<td>&nbsp;</td>
182-
</tr>
183-
<tr>
184-
<td><code>./name</code></td>
185-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
186-
<td>&nbsp;</td>
187-
</tr>
188-
<tr>
189-
<td><code>./version</code></td>
190-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
191-
<td>&nbsp;</td>
192-
</tr>
193-
<tr>
194-
<td><code>./purl</code></td>
195-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
196-
<td>&nbsp;</td>
197-
</tr>
198-
<tr>
199-
<td><code>./externalReferences</code></td>
200-
<td>Y</td><td>Y</td><td>Y</td><td>N/A</td>
201-
<td>Not all Parsers have this information. It will be populated where there is information available.</td>
202-
</tr>
203-
<tr>
204-
<td><code>./hashes</code></td>
205-
<td>Y</td><td>Y</td><td>Y</td><td>Y</td>
206-
<td>
207-
These are supported when programmatically creating a <code>Bom</code> - these will not currently be
208-
automatically populated when using a <code>Parser</code>.
209-
</td>
210-
</tr>
211-
</tbody>
212-
</table>
213-
214-
### Notes on Schema Support
215-
216-
* N/A is where the CycloneDX standard does not include this
217-
* If the table above does not refer to an element, it is not currently supported
26+
View our documentation [here](https://cyclonedx-python-library.readthedocs.io/).
21827

21928
## Python Support
22029

@@ -244,14 +53,16 @@ See the [LICENSE][license_file] file for the full license.
24453
[contributing_file]: https://github.com/CycloneDX/cyclonedx-python-lib/blob/master/CONTRIBUTING.md
24554

24655
[shield_gh-workflow-test]: https://img.shields.io/github/workflow/status/CycloneDX/cyclonedx-python-lib/Python%20CI/main?logo=GitHub&logoColor=white "build"
247-
[shield_pypi-version]: https://img.shields.io/pypi/v/cyclonedx-python-lib?logo=Python&logoColor=white&label=PyPI "PyPI"
56+
[shield_pypi-version]: https://img.shields.io/pypi/v/cyclonedx-python-lib?logo=pypi&logoColor=white&label=PyPI "PyPI"
57+
[shield_conda-forge-version]: https://img.shields.io/conda/vn/conda-forge/cyclonedx-python-lib?logo=anaconda&logoColor=white&label=conda-forge "conda-forge"
24858
[shield_license]: https://img.shields.io/github/license/CycloneDX/cyclonedx-python-lib "license"
24959
[shield_website]: https://img.shields.io/badge/https://-cyclonedx.org-blue.svg "homepage"
25060
[shield_slack]: https://img.shields.io/badge/slack-join-blue?logo=Slack&logoColor=white "slack join"
25161
[shield_groups]: https://img.shields.io/badge/discussion-groups.io-blue.svg "groups discussion"
25262
[shield_twitter-follow]: https://img.shields.io/badge/Twitter-follow-blue?logo=Twitter&logoColor=white "twitter follow"
25363
[link_gh-workflow-test]: https://github.com/CycloneDX/cyclonedx-python-lib/actions/workflows/poetry.yml?query=branch%3Amain
25464
[link_pypi]: https://pypi.org/project/cyclonedx-python-lib/
65+
[link_conda-forge]: https://anaconda.org/conda-forge/cyclonedx-python-lib
25566
[link_website]: https://cyclonedx.org/
25667
[link_slack]: https://cyclonedx.org/slack/invite
25768
[link_discussion]: https://groups.io/g/CycloneDX

0 commit comments

Comments
 (0)