From da1d527aca971fe96e935a4ad7423951381db321 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Tue, 7 May 2024 18:51:12 -0500 Subject: [PATCH 01/25] Update README to provide Diff command recommendations Signed-off-by: Matt Rutkowski --- README.md | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index e272323..fdfc966 100644 --- a/README.md +++ b/README.md @@ -58,21 +58,6 @@ Feedback and helpful commits appreciated on the following commands which will be - [Commands](#commands) - [Exit codes](#exit-codes): (e.g., `0`: none, `1`: application, `2`: validation) - [Persistent flags](#persistent-flags) (e.g., `--format`, `--quiet`, `--where`, etc.) - - [component](#component) - - [list](#component-list-subcommand) subcommand: lists all component information found in the BOM - - [license](#license) - - [list](#license-list-subcommand) subcommand: lists all license information found in the BOM - - [policy](#license-policy-subcommand) subcommand: lists configurable license usage policies - - [patch](#patch): patches BOMs using IETF RFC 6902 records. - - [query](#query): extract JSON objects and fields from a BOM using SQL-like queries - - [resource](#resource): list resource information by type (e.g., components, services) - - [schema](#schema): list supported BOM formats, versions, variants - - [trim](#trim): remove unnecessary fields and data from a BOM - - [validate](#validate): BOM against declared or required schema - - [vulnerability](#vulnerability): lists vulnerability summary information included in the BOM or VEX - - [completion](#completion): generates command-line completion scripts for the utility -- [Experimental commands](#experimental-commands) - - [diff](#diff): compares differences between two similar BOMs - [Design considerations](#design-considerations) - [Development](#development) - [Prerequisites](#prerequisites) @@ -129,17 +114,26 @@ This section provides detailed descriptions of all commands, their flags and exa For convenience, links to each command's section are here: +- [component](#component): list all, top-level component information. - [license](#license) - - [list](#license-list-subcommand) subcommand - - [policy](#license-policy-subcommand) subcommand -- [query](#query) -- [resource](#resource) -- [schema](#schema) -- [vulnerability](#vulnerability) -- [validate](#validate) + - [list](#license-list-subcommand) subcommand: lists all license information found in the BOM + - [policy](#license-policy-subcommand) subcommand: lists configurable license usage policies +- [patch](#patch): patches BOMs using IETF RFC 6902 records. +- [query](#query): extract JSON objects and fields from a BOM using SQL-like queries +- [resource](#resource): list resource information by type (e.g., components, services) +- [schema](#schema): list supported BOM formats, versions, variants +- [trim](#trim): remove unnecessary fields and data from a BOM +- [validate](#validate): BOM against declared or required schema +- [vulnerability](#vulnerability): lists vulnerability summary information included in the BOM or VEX - [completion](#completion) - [help](#help) +### Experimental commands + +These commands need more community testing and feedback. + +- [diff](#diff): compares differences between two similar BOMs. + #### Exit codes All commands return a numeric exit code (i.e., a POSIX exit code) for use in automated processing where `0` indicates success and a non-zero value indicates failure of some kind designated by the number. @@ -2246,7 +2240,12 @@ This section contains *experimental* commands that will be promoted once vetted ### Diff -This *experimental* command will compare two *similar* BOMs and return the delta (or "diff") in JSON (diff-patch format) or text. This functionality is based upon code ancestral to that used to report file diffs between `git commit`s. +This *experimental* command will compare two *similar* BOMs and return the delta (or "diff") in JSON (diff-patch format) or text. This functionality is "JSON aware" and based upon code ancestral to that used to report file diffs between `git commit`s. + +##### Recommendations + +- *Even with BOMs that **SHOULD** be similar, it is recommended to use the **[trim](#trim)** to remove data that changes within a BOM from one generation to another *or* is often proprietary such as: **bom-ref**, **hashes**, **timestamp**(s), **properties**, etc.*. +- *In addition, it is recommended that you also `--normalize` trimmed output data to better guarantee ordering of fields and array data.* ##### Notes From 21e326778a91af7597ab13a66462a47322b7d209 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Tue, 7 May 2024 18:59:02 -0500 Subject: [PATCH 02/25] Update README to provide Diff command recommendations Signed-off-by: Matt Rutkowski --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fdfc966..f65ee1b 100644 --- a/README.md +++ b/README.md @@ -2244,7 +2244,7 @@ This *experimental* command will compare two *similar* BOMs and return the delta ##### Recommendations -- *Even with BOMs that **SHOULD** be similar, it is recommended to use the **[trim](#trim)** to remove data that changes within a BOM from one generation to another *or* is often proprietary such as: **bom-ref**, **hashes**, **timestamp**(s), **properties**, etc.*. +- *Even with BOMs that **SHOULD** be similar, it is recommended to use the **[trim](#trim)** command to remove data that changes within a BOM from one generation to another *or* is often proprietary such as: **bom-ref**, **hashes**, **timestamp**(s), **properties**, etc.*. - *In addition, it is recommended that you also `--normalize` trimmed output data to better guarantee ordering of fields and array data.* ##### Notes From 7730ad798453fdfd87b1acd3daecc98bdcd90926 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:09:43 -0500 Subject: [PATCH 03/25] Provide summarized list of commands in table format Signed-off-by: Matt Rutkowski --- README.md | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index f65ee1b..d0747f6 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This utility was designed to be an API platform to validate, analyze and edit ** In addition, the utility features "report" commands that can easily extract, filter, list and summarize **component**, **service**, **license**, **resource**, **vulnerability** and other BOM information using the utility's powerful, SQL-like query command. The **query** command allows **select**-ion of specific data **from** anywhere in the BOM document **where** data values match specified (regex) patterns. -- *Report output can be produced in several formats (e.g., text, CSV, MD (markdown) and JSON) to accommodate further processing.* +- *Report output can be produced in several formats (e.g., `txt`, `csv`, `md` (markdown) and `json`) to accommodate further processing.* The utility also offers commands that support analysis and editing of BOM document data including **trim**, **patch** (IETF RFC 6902) and **diff**. @@ -18,36 +18,28 @@ The utility also offers commands that support analysis and editing of BOM docume ## Command Overview -The following commands, which operate against input BOMs and named resources within them, are offered by the utility: - -- **[component](#component) list** produces filterable listings of hardware or software components declared in the BOM. - -- **[license](#license)** - - **[`list`](#license-list-subcommand)** produces filtered listings of license data contained in a BOM along with license "usage policy" determinations using the policies declared in the `license.json` file. - - **[policy](#license-policy-subcommand)** - lists software and data license information and associated license usage policies as defined in the configurable `license.json` file. - -- **[patch](#patch)** : Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. - -- **[query](#query)** retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select --from --where `). The JSON data can be used to create custom listings or reports. - -- **[resource](#resource) list** produces filterable listings of resources (i.e., components and services) declared in the BOM. - -- **[schema](#schema)** lists the "built-in" set of schema formats, versions and variants supported by the `validation` command. - - Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). - -- **[trim](#trim)** provide the ability to remove specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information. A SQL-like set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths. - -- **[validate](#validate)** enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas. - - Derivative, **"customized" schemas** can be used for verification using the `--variant` flag (e.g., industry or company-specific schemas). - - You can override an BOM's declared BOM version using the `--force` flag (e.g., verify a BOM against a newer specification version). - -- **[vulnerability](#vulnerability) list** produces filterable listings of vulnerabilities declared in the BOM (i.e., CycloneDX Vulnerability Exploitability eXchange (**VEX**)) data or independently stored CycloneDX Vulnerability Disclosure Report (**VDR**) data. +The following commands, which operate against input BOMs and named resources within them, are offered by the utility. They are presented by category + +| Command *[subcommand]* | Description | +| :-- | :-- | +| **[validate](#validate)** |enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.| +| **[patch](#patch)** | Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. | +| **[trim](#trim)** | provides the ability to remove specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information.

*A "SQL-like" set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths.* | +| **[query](#query)** | retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select --from --where `). The JSON data can be used to create custom listings or reports. | +| **[component](#component)** **[`list`](#component-list-command)** | produces filterable listings of hardware or software components declared in the BOM. | +| **[license](#license)** **[`list`](#license-list-subcommand)** | produces filterable listings of license data declared in the BOM along with the associated component or service. Includes *"usage policy"* determinations as declared in the `license.json` configuration file. | +| **[license](#license)** **[`policy`](#license-policy-subcommand)** | lists software and data license information and associated license usage policies as defined in the configurable `license.json` file. | +| **[resource `list`](#resource)** | produces filterable listings of resources (i.e., components and services) declared in the BOM. | +| **[schema `list`](#schema)** | produces filterable listings of schema formats, versions and variants supported by the `validation` command.

**Note**: Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). | +| **[vulnerability `list`](#vulnerability)** | produces filterable listings of vulnerabilities declared in the BOM (i.e., CycloneDX Vulnerability Exploitability eXchange (**VEX**)) data or independently stored CycloneDX Vulnerability Disclosure Report (**VDR**) data stored in the BOM format. | **Experimental commands**: Feedback and helpful commits appreciated on the following commands which will be promoted after at least two point releases: -- **[diff](#diff)** : Shows the delta between two similar BOM versions in JSON (diff) patch format as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/). +| Command | Description | +| :-- | :-- | +| **[diff](#diff)** | Shows the delta between two similar BOM versions in JSON (diff) patch format as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/). | --- @@ -1847,12 +1839,17 @@ Trimmed, normalized output: This command will parse standardized SBOMs and validate it against its declared format and version (e.g., SPDX 2.2, CycloneDX 1.4). Custom variants of standard JSON schemas can be used for validation by supplying the `--variant` name as a flag. Explicit JSON schemas can be specified using the `--force` flag. -#### Validate supported schemas +#### Validating using supported schemas Use the [schema](#schema) command to list supported schemas formats, versions and variants. +#### Validating using "custom" schemas + Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file. See [adding schemas](#adding-schemas). +- **"Customized" schema** variants, perhaps derived from standard BOM schemas, can be used for validation using the `--variant` flag (e.g., industry or company-specific schemas). +- **Overriding default schema** - You can override an BOM's declared BOM version using the `--force` flag (e.g., verify a BOM against a newer specification version). + #### Validate flags The following flags can be used to improve performance when formatting error output results: From 1e7496beeae3ef1587d8b0b658ab76c0b95c8be7 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:21:11 -0500 Subject: [PATCH 04/25] Update locations of released config. files Signed-off-by: Matt Rutkowski --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d0747f6..532592c 100644 --- a/README.md +++ b/README.md @@ -75,14 +75,17 @@ Download and decompress the correct archive file (i.e., `.tar` for Unix/Linux sy - [https://github.com/CycloneDX/sbom-utility/releases](https://github.com/CycloneDX/sbom-utility/releases) -The archive will contain the following files: +The source archive will contain the following files under the root directory: - `sbom-utility` - binary executable. This is all most need for non-customized configurations. -- `config.json` *(optional)* - copy of the default schema configuration file for optional customization (to be passed on the command line) -- `license.json` *(optional)* - copy of the default license policy configuration file for optional customization (to be passed on the command line) -- `custom.json` *(experimental)* - custom validation configuration file - `LICENSE` - the software license for the utility (i.e. Apache 2) - `sbom-utility-.sbom.json` - a simple Software Bill-of-Materials (SBOM) for the utility +- `custom.json` *(experimental)* - custom validation configuration file + +The archive will contain the following files under the `resources/config` directory: + +- `config.json` *(optional)* - copy of the default schema configuration file for optional customization (to be passed on the command line) +- `license.json` *(optional)* - copy of the default license policy configuration file for optional customization (to be passed on the command line) --- From ef28463fe30df471cd5a202c56aa5ec818b41612 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:26:15 -0500 Subject: [PATCH 05/25] Clarify config file override Signed-off-by: Matt Rutkowski --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 532592c..e4afc33 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ The source archive will contain the following files under the root directory: - `sbom-utility-.sbom.json` - a simple Software Bill-of-Materials (SBOM) for the utility - `custom.json` *(experimental)* - custom validation configuration file -The archive will contain the following files under the `resources/config` directory: +and under the `resources/config` directory: - `config.json` *(optional)* - copy of the default schema configuration file for optional customization (to be passed on the command line) - `license.json` *(optional)* - copy of the default license policy configuration file for optional customization (to be passed on the command line) @@ -91,7 +91,7 @@ The archive will contain the following files under the `resources/config` direct ## Running -For convenience, the default `config.json` and optional `license.json` configuration files have been embedded in the executable and used if none are provided on the command line using the `--config-schema` or `--config-license` flags respectively. +For convenience, the default `config.json` and optional `license.json` configuration files have been embedded in the executable and used. *You can provide your own versions of these files on the command line using the `--config-schema` or `--config-license` flags respectively.* When providing configuration files using command line flags, the executable attempts to load them from the same path where the executable is run from. If you choose to keep them in a different directory, you will have to supply their location relative to the executable along with the filename. From 43b932ced946922dc11625567377145984d024a2 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:28:34 -0500 Subject: [PATCH 06/25] Clarify config file override Signed-off-by: Matt Rutkowski --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e4afc33..4a8b9dc 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ and under the `resources/config` directory: For convenience, the default `config.json` and optional `license.json` configuration files have been embedded in the executable and used. *You can provide your own versions of these files on the command line using the `--config-schema` or `--config-license` flags respectively.* -When providing configuration files using command line flags, the executable attempts to load them from the same path where the executable is run from. If you choose to keep them in a different directory, you will have to supply their location relative to the executable along with the filename. +- **Note**: *When providing configuration files using command line flags, the executable attempts to load them from the same path where the executable is run from. If you choose to keep them in a different directory, you will have to supply their location relative to the executable along with the filename.* ##### MacOS - Granting executable permission From 0eede7f3f22baaa313065b3c7092ca842fc7c1c2 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:29:35 -0500 Subject: [PATCH 07/25] Clarify config file override Signed-off-by: Matt Rutkowski --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a8b9dc..410ddc8 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ All `list` subcommands support the `--format` flag with the following values: - `txt`: text (tabbed tables) - `csv`: Comma Separated Value (CSV), e.g., for spreadsheets -- `md`: Markdown, e.g., for GitHub +- `md`: Markdown (GitHub-compliant tables) Some commands, which can output lists of JSON objects, also support JSON format using the `json` value. From ea32ded874910390d75f2b9286734e6f78585d12 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:44:47 -0500 Subject: [PATCH 08/25] Uniformly use the -q flag for examples Signed-off-by: Matt Rutkowski --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 410ddc8..24199e7 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ This flag supplies an integer to any command that encodes JSON output to determi #### Example: indent flag on the query command ```bash -./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 2 --quiet +./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 2 -q ``` output with `indent 2`: @@ -223,7 +223,7 @@ output with `indent 2`: ``` ```bash -./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 6 --quiet +./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 6 -q ``` output with `indent 6`: @@ -307,11 +307,11 @@ CycloneDX v1.4 CycloneDX 1.4 (latest) schema/cyclonedx CycloneDX v1.3 CycloneDX 1.3 (latest) schema/cyclonedx/1.3/bom-1.3.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json CycloneDX v1.2 CycloneDX 1.2 (latest) schema/cyclonedx/1.2/bom-1.2.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json SPDX v2.3.1 (development) SPDX SPDX-2.3 development schema/spdx/2.3.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json -SPDX v2.3 SPDX SPDX-2.3 (latest) schema/spdx/2.3/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json -SPDX v2.2.2 SPDX SPDX-2.2 (latest) schema/spdx/2.2.2/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json -SPDX v2.2.1 SPDX SPDX-2.2 2.2.1 schema/spdx/2.2.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json +... ``` +- **Note**: *The short-form `-q` (quiet) flag is equivalent to `--quiet`.* + #### Where flag (output filtering) All `list` subcommands support the `--where` flag. It can be used to filter output results based upon matches to regular expressions (regex) by using the output list's column titles as keys. @@ -362,20 +362,20 @@ pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org required 0 0 true false false false false false false false ``` -##### Example: `component list` summary in markdown format +##### Example: `component list` summary only -The same BOM component information as in the previous example; however, with output produced in markdown table format and using the summary flag to reduce the number of columns. +The same BOM component information as in the previous example; however, using the summary flag to reduce the number of columns data. ```bash -./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json --summary --format=md -q +./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json --summary -q ``` -```markdown -|bom-ref|group|type|name|version|description|copyright|supplier-name|supplier-url|manufacturer-name|manufacturer-url|publisher|purl|swid-tag-id|cpe|number-hashes|number-licenses| -|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--| -|||application|Acme Application|9.1.1|||||||||swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1||0|0| -|pkg:npm/acme/component@1.0.0|com.acme|library|tomcat-catalina|9.0.14||||||||pkg:npm/acme/component@1.0.0|||4|1| -||org.example|library|mylibrary|1.0.0|||Example, Inc.|https://example.com|Example-2, Inc.|https://example.org|||||0|0| +```text +bom-ref group type name version description copyright supplier-name supplier-url manufacturer-name manufacturer-url publisher purl swid-tag-id cpe number-hashes number-licenses +------- ----- ---- ---- ------- ----------- --------- ------------- ------------ ----------------- ---------------- --------- ---- ----------- --- ------------- --------------- + application Acme Application 9.1.1 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1 0 0 +pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 pkg:npm/acme/component@1.0.0 4 1 + org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org 0 0 ``` --- From 286604c3f9d33b4c2cde2857d8b4795f9209deb2 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 11:56:00 -0500 Subject: [PATCH 09/25] Uniformly use the -q flag for examples Signed-off-by: Matt Rutkowski --- README.md | 66 +++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 24199e7..17cf09b 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,7 @@ All commands support the `--quiet` flag. By default, the utility outputs informa This example shows the `--quiet` flag being used on the `schema` command to turn off or "quiet" any informational output so that only the result table is displayed. ```bash -./sbom-utility schema --quiet +./sbom-utility schema list --quiet ``` ```bash @@ -310,8 +310,6 @@ SPDX v2.3.1 (development) SPDX SPDX-2.3 development schema/spdx/2.3. ... ``` -- **Note**: *The short-form `-q` (quiet) flag is equivalent to `--quiet`.* - #### Where flag (output filtering) All `list` subcommands support the `--where` flag. It can be used to filter output results based upon matches to regular expressions (regex) by using the output list's column titles as keys. @@ -421,7 +419,7 @@ Use the `--summary` flag on the `license list` command to produce a summary repo This example shows a few entries of the JSON output that exhibit the three types of license data described above: ```bash -./sbom-utility license list -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --format json --quiet +./sbom-utility license list -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --format json -q ``` ```json @@ -465,7 +463,7 @@ This example shows a few entries of the JSON output that exhibit the three types This example shows the default text output from using the summary flag: ```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --quiet +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary -q ``` ```bash @@ -503,7 +501,7 @@ The list command results can be filtered using the `--where` flag using the colu The following example shows filtering of component licenses using the `license-type` column where the license was described as a `name` value: ```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where license-type=name --quiet +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where license-type=name -q ``` ```bash @@ -520,7 +518,7 @@ needs-review name UFL ACME Application pkg:app/sample@1.0.0 In another example, the list is filtered by the `usage-policy` where the value is `needs-review`: ```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where usage-policy=needs-review --quiet +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where usage-policy=needs-review -q ``` ```bash @@ -565,7 +563,7 @@ Use the `--wrap` flag to toggle the wrapping of text within columns of the licen ##### Example: license policy ```bash -./sbom-utility license policy --quiet +./sbom-utility license policy -q ``` ```bash @@ -586,7 +584,7 @@ allow Artistic Artistic-1.0 Artistic License 1.0 true We can also apply the `--summary` flag to get a reduced set of columns that includes only the `usage-policy` along with the essential SPDX license information (e.g., no annotations or notes). ```bash -./sbom-utility license policy --summary --quiet +./sbom-utility license policy --summary -q ``` ```bash @@ -622,7 +620,7 @@ allow Apache Apache-2.0 Apache License 2.0 true true false ###### Example: policy with `--wrap` flag ```bash -./sbom-utility license policy --quiet --wrap=true +./sbom-utility license policy --wrap=true -q ``` ```bash @@ -716,7 +714,7 @@ IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.js Invoke the patch command as follows: ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-serial-number.json -q +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-serial-number.json -q ``` Patched JSON BOM output file: @@ -761,7 +759,7 @@ IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.js Invoke the patch command as follows: ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-update-version.json -q +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-update-version.json -q ``` The patched, output JSON BOM file which has the changed `version` value of `2`: @@ -1156,7 +1154,7 @@ In this example, only the `--from` clause is needed to select an object. The `- is equivalent to using the wildcard character (which may need to be enclosed in single or double quotes depending on your shell): ```bash -./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select '*' --from metadata.component --quiet +./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select '*' --from metadata.component -q ``` ```json @@ -1191,7 +1189,7 @@ is equivalent to using the wildcard character (which may need to be enclosed in In this example, the `--from` clause references the top-level `metadata.supplier` object. ```bash -./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.supplier --quiet +./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.supplier -q ``` ```json @@ -1213,7 +1211,7 @@ In this example, the `--from` clause references the top-level `metadata.supplier In this example, the `--from` clause references the singleton JSON object `component` found under the top-level `metadata` object. It then reduces the resultant JSON object to only return the `name` and `value` fields and their values as requested on the `--select` clause. ```bash -./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --quiet +./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json -q ``` ```json @@ -1228,7 +1226,7 @@ In this example, the `--from` clause references the singleton JSON object `compo In this example, the `--from` filter will return the entire JSON components array. ```bash -./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from components --quiet +./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from components -q ``` ```json @@ -1278,7 +1276,7 @@ In this example, the `--from` filter will return the entire JSON components arra In this example, the `--where` filter will be applied to a set of `properties` results to only include entries that match the specified regex. ```bash -./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.properties --where name=urn:example.com:classification --quiet +./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --from metadata.properties --where name=urn:example.com:classification -q ``` ```json @@ -1293,7 +1291,7 @@ In this example, the `--where` filter will be applied to a set of `properties` r additionally, you can apply a `--select` clause to simply obtain the matching entry's `value`: ```bash -./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select value --from metadata.properties --where name=urn:example.com:classification --quiet +./sbom-utility query -i test/cyclonedx/cdx-1-4-mature-example-1.json --select value --from metadata.properties --where name=urn:example.com:classification -q ``` ```json @@ -1327,7 +1325,7 @@ Currently, all `resource list` command results are sorted by resource `type` the #### Example: resource list ```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --quiet +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json -q ``` ```bash @@ -1354,7 +1352,7 @@ service Foo Foo service This example uses the `type` flag to specific `service`. The other valid type is `component`. Future versions of CycloneDX schema will include more resource types such as "ml" (machine learning) or "tool". ```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --type service --quiet +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --type service -q ``` ```bash @@ -1367,7 +1365,7 @@ service Foo Foo service service:example.com/myservi **Note** The results would be equivalent to using the `--where` filter: ```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "resource-type=service" --quiet +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "resource-type=service" -q ``` ##### Example: list with `name` regex match @@ -1375,7 +1373,7 @@ service Foo Foo service service:example.com/myservi This example uses the `where` filter on the `name` field. In this case we supply an exact "startswith" regex. for the `name` filter. ```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "name=Library A" --quiet +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "name=Library A" -q ``` ```bash @@ -1571,7 +1569,7 @@ Output BOM results without `properties`: ##### Example: Trim `name` and `description` from entire JSON BOM ```bash -./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=name,description --quiet +./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=name,description -q ``` Output BOM results without `name` or `description`: @@ -1618,7 +1616,7 @@ Output BOM results without `name` or `description`: ##### Example: Trim `properties` from only `components` path ```bash -./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties --from components --quiet +./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties --from components -q ``` Output BOM results with `properties` removed from all `components`: @@ -2023,7 +2021,7 @@ The details include the full context of the failing `metadata.properties` object The JSON format will provide an `array` of schema error results that can be post-processed as part of validation toolchain. ```bash -./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --quiet +./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json -q ``` ```json @@ -2100,7 +2098,7 @@ In many cases, BOMs may have many errors and having the `value` information deta Rerunning the same command with this flag set to false yields a reduced set of information. ```bash -./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --error-value=false --quiet +./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --error-value=false -q ``` ```json @@ -2144,7 +2142,7 @@ Use the `--format` flag on the to choose one of the supported output formats: The `list` subcommand provides a complete view of most top-level, vulnerability fields. ```bash -./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --quiet +./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json -q ``` ```bash @@ -2160,7 +2158,7 @@ CVE-2020-25649 611 CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSS This example shows the default text output from using the `--summary` flag: ```bash -./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --quiet --summary +./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --summary -q ``` ```bash @@ -2174,7 +2172,7 @@ CVE-2020-25649 CVSSv31: 7.5 (high) NVD 2020-12-03 com.fasterxml.jack ##### Example: Vulnerability list with `--where` filter with `description` key ```bash -./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --quiet --where description=XXE +./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --where description=XXE -q ``` ```bash @@ -2186,7 +2184,7 @@ CVE-2020-25649 611 CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSS ##### Example: Vulnerability list with `--where` filter with `analysis-state` key ```bash -./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --quiet --where analysis-state=not_affected +./sbom-utility vulnerability list -i test/vex/cdx-1-3-example1-bom-vex.json --where analysis-state=not_affected -q ``` ```bash @@ -2264,7 +2262,7 @@ Use the `--format` flag on the to choose one of the supported output formats: ##### Example: Add, delete and modify ```bash -./sbom-utility diff -i test/diff/json-array-order-change-with-add-and-delete-base.json -r test/diff/json-array-order-change-with-add-and-delete-delta.json --quiet --format txt --colorize=true +./sbom-utility diff -i test/diff/json-array-order-change-with-add-and-delete-base.json -r test/diff/json-array-order-change-with-add-and-delete-delta.json --format txt --colorize=true -q ``` ```bash @@ -2576,16 +2574,16 @@ Simply append the flags `--args --trace` or `--args --debug` to your `go test` c go test github.com/CycloneDX/sbom-utility/cmd -v --args --trace ``` +**Note**: You should always use the `--args` flag of `go test` as this will assure non-conflict with `go test` built-in flags which is the case with the `--trace` flag. + #### Eliminating extraneous test output Several tests will still output error and warning messages as designed. If these messages are distracting, you can turn them off using the `--quiet` flag. ```bash -go test github.com/CycloneDX/sbom-utility/cmd -v --args --quiet +go test github.com/CycloneDX/sbom-utility/cmd -v --quiet ``` -**Note**: Always use the `--args` flag of `go test` as this will assure non-conflict with built-in flags. - --- #### Releasing From 515393559e6aadd2b92a73794445b2ea054bdcd6 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 12:04:12 -0500 Subject: [PATCH 10/25] Uniformly use the -q flag for examples Signed-off-by: Matt Rutkowski --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 17cf09b..c616b44 100644 --- a/README.md +++ b/README.md @@ -109,19 +109,19 @@ This section provides detailed descriptions of all commands, their flags and exa For convenience, links to each command's section are here: -- [component](#component): list all, top-level component information. -- [license](#license) - - [list](#license-list-subcommand) subcommand: lists all license information found in the BOM - - [policy](#license-policy-subcommand) subcommand: lists configurable license usage policies +- [validate](#validate): validates BOM data against declared or required JSON schema. +- [trim](#trim): removes uninteresting or necessary fields and data from a BOM. - [patch](#patch): patches BOMs using IETF RFC 6902 records. -- [query](#query): extract JSON objects and fields from a BOM using SQL-like queries -- [resource](#resource): list resource information by type (e.g., components, services) -- [schema](#schema): list supported BOM formats, versions, variants -- [trim](#trim): remove unnecessary fields and data from a BOM -- [validate](#validate): BOM against declared or required schema -- [vulnerability](#vulnerability): lists vulnerability summary information included in the BOM or VEX -- [completion](#completion) -- [help](#help) +- [query](#query): extracts JSON objects and fields from a BOM using SQL-like queries. +- [component list](#component): lists all, top-level component information. +- [license](#license) + - [list](#license-list-subcommand) subcommand: lists all license information found in the BOM. + - [policy](#license-policy-subcommand) subcommand: lists configurable license usage policies. +- [resource list](#resource): lists resource information by type (e.g., components, services). +- [schema list](#schema): lists supported JSON schemas by BOM formats, versions and variants. +- [vulnerability list](#vulnerability): lists vulnerability summary information included in a BOM or standalone VDR BOM. +- [completion](#completion): generates command-line completion scripts for the this utility. +- [help](#help): displays help and usage information for the utility or current command/subcommand. ### Experimental commands From 0055c074de1b7ced13660305510dc8978695991f Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 15:32:24 -0500 Subject: [PATCH 11/25] Fix clerical errors in JSON schema for v1.6 Signed-off-by: Matt Rutkowski --- schema/cyclonedx.go | 50 +++++++++++++++++++++----------------- schema/cyclonedx_common.go | 2 ++ schema/cyclonedx_crypto.go | 2 +- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/schema/cyclonedx.go b/schema/cyclonedx.go index b4cb238..064b293 100644 --- a/schema/cyclonedx.go +++ b/schema/cyclonedx.go @@ -60,16 +60,18 @@ type CDXBom struct { // v1.2: existed // v1.3: added "licenses", "properties" // v1.5: added "lifecycles" +// v1.6: added "manufacturer"; deprecated "manufacture" type CDXMetadata struct { Timestamp string `json:"timestamp,omitempty" scvs:"bom:core:timestamp"` // urn:owasp:scvs:bom:core:timestamp Tools interface{} `json:"tools,omitempty"` // v1.2: added; v1.5: "tools" is now an interface{} Authors *[]CDXOrganizationalContact `json:"authors,omitempty"` Component *CDXComponent `json:"component,omitempty"` - Manufacturer *CDXOrganizationalEntity `json:"manufacture,omitempty"` // NOTE: Typo is in spec. Supplier *CDXOrganizationalEntity `json:"supplier,omitempty"` - Licenses *[]CDXLicenseChoice `json:"licenses,omitempty"` // v1.3 added - Properties *[]CDXProperty `json:"properties,omitempty"` // v1.3 added - Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty"` // v1.5 added + Licenses *[]CDXLicenseChoice `json:"licenses,omitempty" cdx:"+1.3"` // v1.3 added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"+1.3"` // v1.3 added + Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty" cdx:"+1.5"` // v1.5 added + Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"deprecated:1.6"` // v1.6: added + Manufacture *CDXOrganizationalEntity `json:"manufacture,omitempty" cdx:"+1.6"` // v1.6: deprecated (typo. error) } // TODO: figure out how to support both current (object)/legacy(array) tools in Metadata.Tools field @@ -115,20 +117,23 @@ type CDXComponent struct { Cpe string `json:"cpe,omitempty"` // See: https://nvd.nist.gov/products/cpe Purl string `json:"purl,omitempty" scvs:"bom:resource:identifiers:purl"` // See: https://github.com/package-url/purl-spec Swid *CDXSwid `json:"swid,omitempty"` // See: https://www.iso.org/standard/65666.html - Pedigree *CDXPedigree `json:"pedigree,omitempty"` // anon. type + Pedigree *CDXPedigree `json:"pedigree,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Components *[]CDXComponent `json:"components,omitempty"` - Evidence *CDXComponentEvidence `json:"evidence,omitempty" cdx:"added:1.3"` // v1.3: added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` // v1.3: added - ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty" cdx:"added:1.4"` // v1.4: added - Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` // v1.4: added - Modified bool `json:"modified,omitempty" cdx:"deprecated:1.4"` // v1.4: deprecated - ModelCard *CDXModelCard `json:"modelCard,omitempty" cdx:"added:1.5"` // v1.5: added - Data *[]CDXComponentData `json:"data,omitempty" cdx:"added:1.5"` // v1.5: added - Authors *[]CDXOrganizationalContact `json:"authors,omitempty" cdx:"added:1.6"` // v1.6: added - Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` // v1.6: added - Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"added:1.6"` // v1.6: added - Author string `json:"author,omitempty" cdx:"deprecated:1.6"` // v1.6: deprecated + Evidence *CDXComponentEvidence `json:"evidence,omitempty" cdx:"added:1.3"` // v1.3: added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` // v1.3: added + ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty" cdx:"added:1.4"` // v1.4: added + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` // v1.4: added + Modified bool `json:"modified,omitempty" cdx:"deprecated:1.4"` // v1.4: deprecated + ModelCard *CDXModelCard `json:"modelCard,omitempty" cdx:"added:1.5"` // v1.5: added + Data *[]CDXComponentData `json:"data,omitempty" cdx:"added:1.5"` // v1.5: added + Authors *[]CDXOrganizationalContact `json:"authors,omitempty" cdx:"added:1.6"` // v1.6: added + OmniborId *[]string `json:"omniborId,omitempty" cdx:"added:1.6"` // v1.6: added + Swhid *[]string `json:"swhid,omitempty" cdx:"added:1.6"` // v1.6: added + CryptoProperties *CDXCryptoProperties `json:"cryptoProperties,omitempty" cdx:"added:1.6"` // v1.6: added + Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` // v1.6: added + Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"added:1.6"` // v1.6: added + Author string `json:"author,omitempty" cdx:"deprecated:1.6"` // v1.6: deprecated } // v1.5 added object @@ -195,10 +200,10 @@ type CDXService struct { Licenses *[]CDXLicenseChoice `json:"licenses,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Services *[]CDXService `json:"services,omitempty"` - Properties *[]CDXProperty `json:"properties,omitempty"` // v1.3: added - ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty"` // v1.4: added - Signature *JSFSignature `json:"signature,omitempty"` // v1.4: added - Tags *[]string `json:"tags,omitempty" cdx:"+1.6"` // v1.6: added + Properties *[]CDXProperty `json:"properties,omitempty"` // v1.3: added + ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty"` // v1.4: added + Signature *JSFSignature `json:"signature,omitempty"` // v1.4: added + Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` // v1.6: added } // v1.5: added. aggregated related date from v1.2-v1.4 and added additional fields @@ -256,7 +261,7 @@ type CDXSwid struct { Version string `json:"version,omitempty"` TagVersion int `json:"tagVersion,omitempty"` Patch bool `json:"patch,omitempty"` - Text *CDXAttachment `json:"attachment,omitempty"` + Text *CDXAttachment `json:"text,omitempty"` Url string `json:"url,omitempty"` } @@ -284,7 +289,8 @@ type CDXLicenseExpression struct { // v1.6: added Acknowledgment // Note: "id" SHOULD be an SPDX license ID // Note: "oneOf": ["id", "name"] is required -// NOTE: CDXRefType is a named `string` type as of v1.5 +// Note: CDXRefType is a named `string` type as of v1.5 +// Note: Acknowledgement is actually a named `string` (licenseAcknowledgementEnumeration) type CDXLicense struct { Id string `json:"id,omitempty"` Name string `json:"name,omitempty"` diff --git a/schema/cyclonedx_common.go b/schema/cyclonedx_common.go index bcd78ea..9a4d794 100644 --- a/schema/cyclonedx_common.go +++ b/schema/cyclonedx_common.go @@ -103,12 +103,14 @@ type CDXNote struct { // v1.2: existed // v1.5: added "bom-ref" +// v1.6: added "address" // NOTE: CDXRefType is a named `string` type as of v1.5 type CDXOrganizationalEntity struct { Name string `json:"name,omitempty"` Url []string `json:"url,omitempty"` Contact *[]CDXOrganizationalContact `json:"contact,omitempty"` BOMRef *CDXRefType `json:"bom-ref,omitempty"` // v1.5 added + Address *CDXPostalAddress `json:"address,omitempty"` // v1.6 added } // v1.2: existed diff --git a/schema/cyclonedx_crypto.go b/schema/cyclonedx_crypto.go index e1126d8..1978346 100644 --- a/schema/cyclonedx_crypto.go +++ b/schema/cyclonedx_crypto.go @@ -19,7 +19,7 @@ package schema // v1.6: added // NOTE: This is an enum. (e.g., "algorithm", "certificate", "protocol", etc.) -type CDXAssetType struct { +type CDXCryptoProperties struct { AssetType string `json:"assetType,omitempty" cdx:"+1.6"` // v1.6 added AlgorithmProperties *CDXAlgorithmProperties `json:"algorithmProperties,omitempty" cdx:"+1.6"` // v1.6 added CertificateProperties *CDXCertificateProperties `json:"certificateProperties,omitempty" cdx:"+1.6"` // v1.6 added From bcda3eddf5e5ebb33431d0d0fdcb489a7ec2171e Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Wed, 8 May 2024 16:44:10 -0500 Subject: [PATCH 12/25] Fix missing structures from v1.5 for ComponentEvidence Signed-off-by: Matt Rutkowski --- schema/cyclonedx.go | 102 ++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 28 deletions(-) diff --git a/schema/cyclonedx.go b/schema/cyclonedx.go index 064b293..6e1b960 100644 --- a/schema/cyclonedx.go +++ b/schema/cyclonedx.go @@ -47,14 +47,14 @@ type CDXBom struct { Services *[]CDXService `json:"services,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Dependencies *[]CDXDependency `json:"dependencies,omitempty"` - Compositions *[]CDXCompositions `json:"compositions,omitempty" cdx:"+1.3"` // v1.3 added - Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty" cdx:"+1.4"` // v1.4 added - Signature *JSFSignature `json:"signature,omitempty" cdx:"+1.4"` // v1.4 added - Annotations *[]CDXAnnotation `json:"annotations,omitempty" cdx:"+1.5"` // v1.5 added - Formulation *[]CDXFormula `json:"formulation,omitempty" cdx:"+1.5"` // v1.5 added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"+1.5"` // v1.5 added - Declarations *[]CDXDeclaration `json:"declarations,omitempty" cdx:"+1.6"` // v1.6 added - Definitions *[]CDXDefinition `json:"definitions,omitempty" cdx:"+1.6"` // v1.6 added + Compositions *[]CDXCompositions `json:"compositions,omitempty" cdx:"added:1.3"` // v1.3 added + Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty" cdx:"added:1.4"` // v1.4 added + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` // v1.4 added + Annotations *[]CDXAnnotation `json:"annotations,omitempty" cdx:"added:1.5"` // v1.5 added + Formulation *[]CDXFormula `json:"formulation,omitempty" cdx:"added:1.5"` // v1.5 added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` // v1.5 added + Declarations *[]CDXDeclaration `json:"declarations,omitempty" cdx:"added:1.6"` // v1.6 added + Definitions *[]CDXDefinition `json:"definitions,omitempty" cdx:"added:1.6"` // v1.6 added } // v1.2: existed @@ -67,11 +67,11 @@ type CDXMetadata struct { Authors *[]CDXOrganizationalContact `json:"authors,omitempty"` Component *CDXComponent `json:"component,omitempty"` Supplier *CDXOrganizationalEntity `json:"supplier,omitempty"` - Licenses *[]CDXLicenseChoice `json:"licenses,omitempty" cdx:"+1.3"` // v1.3 added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"+1.3"` // v1.3 added - Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty" cdx:"+1.5"` // v1.5 added + Licenses *[]CDXLicenseChoice `json:"licenses,omitempty" cdx:"added:1.3"` // v1.3 added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` // v1.3 added + Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty" cdx:"added:1.5"` // v1.5 added Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"deprecated:1.6"` // v1.6: added - Manufacture *CDXOrganizationalEntity `json:"manufacture,omitempty" cdx:"+1.6"` // v1.6: deprecated (typo. error) + Manufacture *CDXOrganizationalEntity `json:"manufacture,omitempty" cdx:"added:1.6"` // v1.6: deprecated (typo. error) } // TODO: figure out how to support both current (object)/legacy(array) tools in Metadata.Tools field @@ -281,11 +281,11 @@ type CDXLicenseChoice struct { type CDXLicenseExpression struct { Expression string `json:"expression,omitempty"` BOMRef *CDXRefType `json:"bom-ref,omitempty"` - Acknowledgement string `json:"acknowledgement,omitempty"` // v1.6: added + Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` // v1.6: added } // v1.2: was an anon. type -// v1.3: created +// v1.3: created as a named type // v1.6: added Acknowledgment // Note: "id" SHOULD be an SPDX license ID // Note: "oneOf": ["id", "name"] is required @@ -296,22 +296,22 @@ type CDXLicense struct { Name string `json:"name,omitempty"` Text *CDXAttachment `json:"text,omitempty"` Url string `json:"url,omitempty"` - BOMRef *CDXRefType `json:"bom-ref,omitempty"` // v1.5: added - Licensing *CDXLicensing `json:"licensing,omitempty"` // v1.5: added - Properties *[]CDXProperty `json:"properties,omitempty"` // v1.5: added - Acknowledgement string `json:"acknowledgement,omitempty"` // v1.6: added + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` // v1.5: added + Licensing *CDXLicensing `json:"licensing,omitempty" cdx:"added:1.5"` // v1.5: added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` // v1.5: added + Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` // v1.6: added } // v1.5: added object type CDXLicensing struct { - AltIds *[]string `json:"altIds,omitempty"` - Licensor *CDXLicenseLegalParty `json:"licensor,omitempty"` - Licensee *CDXLicenseLegalParty `json:"licensee,omitempty"` - Purchaser *CDXLicenseLegalParty `json:"purchaser,omitempty"` - PurchaseOrder string `json:"purchaseOrder,omitempty"` - LicenseTypes *[]string `json:"licenseTypes,omitempty"` // Constraint: enum[see schema] - LastRenewal string `json:"lastRenewal,omitempty"` - Expiration string `json:"expiration,omitempty"` + AltIds *[]string `json:"altIds,omitempty" cdx:"added:1.5"` // v1.5: added + Licensor *CDXLicenseLegalParty `json:"licensor,omitempty" cdx:"added:1.5"` // v1.5: added + Licensee *CDXLicenseLegalParty `json:"licensee,omitempty" cdx:"added:1.5"` // v1.5: added + Purchaser *CDXLicenseLegalParty `json:"purchaser,omitempty" cdx:"added:1.5"` // v1.5: added + PurchaseOrder string `json:"purchaseOrder,omitempty" cdx:"added:1.5"` // v1.5: added + LicenseTypes *[]string `json:"licenseTypes,omitempty" cdx:"added:1.5"` // v1.5: added + LastRenewal string `json:"lastRenewal,omitempty" cdx:"added:1.5"` // v1.5: added + Expiration string `json:"expiration,omitempty" cdx:"added:1.5"` // v1.5: added } // v1.2: existed @@ -407,11 +407,57 @@ type CDXCopyright struct { } // v1.3: created "componentEvidence" defn. +// Note: "Identity" was changed from a singleton in v1.5, to an array of in v1.6 type CDXComponentEvidence struct { - Licenses *[]CDXLicense `json:"licenses,omitempty"` - Copyright *[]CDXCopyright `json:"copyright,omitempty"` + Licenses *[]CDXLicense `json:"licenses,omitempty" cdx:"added:1.3"` + Copyright *[]CDXCopyright `json:"copyright,omitempty" cdx:"added:1.3"` + Identity interface{} `json:"identity,omitempty" cdx:"added:1.5,changed:1.6"` + Occurrences *[]CDXOccurrence `json:"occurrences,omitempty" cdx:"added:1.5"` + Callstack *CDXCallstack `json:"callstack,omitempty" cdx:"added:1.5"` } +// v1.5: added +type CDXOccurrence struct { + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` + Location string `json:"location,omitempty" cdx:"added:1.5"` +} + +// v1.5: added +type CDXCallstack struct { + Frames *[]CDXFrames `json:"frames,omitempty" cdx:"added:1.5"` +} + +// v1.5: added +// Note: "parameters" SHOULD use "formulation" definitions that better define a parameter +type CDXFrames struct { + Package string `json:"package,omitempty" cdx:"added:1.5"` + Module string `json:"module,omitempty" cdx:"added:1.5"` + Function string `json:"function,omitempty" cdx:"added:1.5"` + Parameters *[]string `json:"parameters,omitempty" cdx:"added:1.5"` + Line int `json:"line,omitempty" cdx:"added:1.5"` + Column int `json:"column,omitempty" cdx:"added:1.5"` + FullFilename string `json:"fullFilename,omitempty" cdx:"added:1.5"` +} + +// v1.5: added +// TODO: figure out how to support both the v1.5 "Identity" type (a singleton +// of an anonymous type) vs. the v1.6 "identity" which is an array of named type +// (i.e., componentIdentityEvidence). +// Note: Tools is either (OneOf) CDXRefType CDXBomLinkElementType, which are both strings for now... +// type CDXComponentIdentityEvidence struct { +// Field string `json:"field,omitempty" cdx:"added:1.5"` +// Confidence float64 `json:"confidence,omitempty" cdx:"added:1.5"` +// Methods *[]CDXMethod `json:"methods,omitempty" cdx:"added:1.5"` +// Tools *[]string `json:"tools,omitempty" cdx:"added:1.5"` +// } + +// // v1.5: added +// type CDXMethod struct { +// Technique string `json:"technique,omitempty" cdx:"added:1.5"` +// Confidence float64 `json:"confidence,omitempty" cdx:"added:1.5"` +// Value string `json:"value,omitempty" cdx:"added:1.5"` +// } + // v1.3: created "compositions" defn. // v1.4: added "signature" // v1.5: added "bom-ref", "vulnerabilities" From 534e139be6226067ff0af5b60f7e66853f4dc957 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 11:08:52 -0500 Subject: [PATCH 13/25] Add JSON schema tags to all core CycloneDX types Signed-off-by: Matt Rutkowski --- schema/cyclonedx.go | 224 ++++++++++++++++------------------ schema/cyclonedx_common.go | 43 ++++--- schema/cyclonedx_modelcard.go | 3 + 3 files changed, 132 insertions(+), 138 deletions(-) diff --git a/schema/cyclonedx.go b/schema/cyclonedx.go index 6e1b960..a33ae2d 100644 --- a/schema/cyclonedx.go +++ b/schema/cyclonedx.go @@ -47,47 +47,34 @@ type CDXBom struct { Services *[]CDXService `json:"services,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Dependencies *[]CDXDependency `json:"dependencies,omitempty"` - Compositions *[]CDXCompositions `json:"compositions,omitempty" cdx:"added:1.3"` // v1.3 added - Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty" cdx:"added:1.4"` // v1.4 added - Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` // v1.4 added - Annotations *[]CDXAnnotation `json:"annotations,omitempty" cdx:"added:1.5"` // v1.5 added - Formulation *[]CDXFormula `json:"formulation,omitempty" cdx:"added:1.5"` // v1.5 added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` // v1.5 added - Declarations *[]CDXDeclaration `json:"declarations,omitempty" cdx:"added:1.6"` // v1.6 added - Definitions *[]CDXDefinition `json:"definitions,omitempty" cdx:"added:1.6"` // v1.6 added + Compositions *[]CDXCompositions `json:"compositions,omitempty" cdx:"added:1.3"` + Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty" cdx:"added:1.4"` + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` + Annotations *[]CDXAnnotation `json:"annotations,omitempty" cdx:"added:1.5"` + Formulation *[]CDXFormula `json:"formulation,omitempty" cdx:"added:1.5"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` + Declarations *[]CDXDeclaration `json:"declarations,omitempty" cdx:"added:1.6"` + Definitions *[]CDXDefinition `json:"definitions,omitempty" cdx:"added:1.6"` } // v1.2: existed // v1.3: added "licenses", "properties" // v1.5: added "lifecycles" +// v1.5: "tools" is changed to an interface{} as it represents 2 possible types (object , slice ) // v1.6: added "manufacturer"; deprecated "manufacture" +// Note: "timestamp" in OWASP SCVS is: urn:owasp:scvs:bom:core:timestamp type CDXMetadata struct { - Timestamp string `json:"timestamp,omitempty" scvs:"bom:core:timestamp"` // urn:owasp:scvs:bom:core:timestamp - Tools interface{} `json:"tools,omitempty"` // v1.2: added; v1.5: "tools" is now an interface{} + Timestamp string `json:"timestamp,omitempty" scvs:"bom:core:timestamp"` + Tools interface{} `json:"tools,omitempty"` Authors *[]CDXOrganizationalContact `json:"authors,omitempty"` Component *CDXComponent `json:"component,omitempty"` Supplier *CDXOrganizationalEntity `json:"supplier,omitempty"` - Licenses *[]CDXLicenseChoice `json:"licenses,omitempty" cdx:"added:1.3"` // v1.3 added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` // v1.3 added - Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty" cdx:"added:1.5"` // v1.5 added - Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"deprecated:1.6"` // v1.6: added - Manufacture *CDXOrganizationalEntity `json:"manufacture,omitempty" cdx:"added:1.6"` // v1.6: deprecated (typo. error) -} - -// TODO: figure out how to support both current (object)/legacy(array) tools in Metadata.Tools field -// See: https://stackoverflow.com/questions/47057240/parsing-multiple-json-types-into-the-same-struct -// type CDXToolLegacy struct { -// Name string `json:"name,omitempty"` -// Version string `json:"version,omitempty"` -// Vendor string `json:"vendor,omitempty"` -// Hashes *[]CDXHash `json:"hashes,omitempty"` -// ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` -// } - -// type CDXTools struct { -// Components *[]CDXComponent `json:"components,omitempty"` -// Services *[]CDXService `json:"services,omitempty"` -// } + Licenses *[]CDXLicenseChoice `json:"licenses,omitempty" cdx:"added:1.3"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` + Lifecycles *[]CDXLifecycle `json:"lifecycles,omitempty" cdx:"added:1.5"` + Manufacture *CDXOrganizationalEntity `json:"manufacture,omitempty" cdx:"deprecated:1.6"` + Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"added:1.6"` +} // v1.2: existed // v1.3: added: "evidence", "properties" @@ -120,56 +107,56 @@ type CDXComponent struct { Pedigree *CDXPedigree `json:"pedigree,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Components *[]CDXComponent `json:"components,omitempty"` - Evidence *CDXComponentEvidence `json:"evidence,omitempty" cdx:"added:1.3"` // v1.3: added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` // v1.3: added - ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty" cdx:"added:1.4"` // v1.4: added - Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` // v1.4: added - Modified bool `json:"modified,omitempty" cdx:"deprecated:1.4"` // v1.4: deprecated - ModelCard *CDXModelCard `json:"modelCard,omitempty" cdx:"added:1.5"` // v1.5: added - Data *[]CDXComponentData `json:"data,omitempty" cdx:"added:1.5"` // v1.5: added - Authors *[]CDXOrganizationalContact `json:"authors,omitempty" cdx:"added:1.6"` // v1.6: added - OmniborId *[]string `json:"omniborId,omitempty" cdx:"added:1.6"` // v1.6: added - Swhid *[]string `json:"swhid,omitempty" cdx:"added:1.6"` // v1.6: added - CryptoProperties *CDXCryptoProperties `json:"cryptoProperties,omitempty" cdx:"added:1.6"` // v1.6: added - Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` // v1.6: added - Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"added:1.6"` // v1.6: added - Author string `json:"author,omitempty" cdx:"deprecated:1.6"` // v1.6: deprecated + Evidence *CDXComponentEvidence `json:"evidence,omitempty" cdx:"added:1.3"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` + ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty" cdx:"added:1.4"` + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` + Modified bool `json:"modified,omitempty" cdx:"deprecated:1.4"` + ModelCard *CDXModelCard `json:"modelCard,omitempty" cdx:"added:1.5"` + Data *[]CDXComponentData `json:"data,omitempty" cdx:"added:1.5"` + Authors *[]CDXOrganizationalContact `json:"authors,omitempty" cdx:"added:1.6"` + OmniborId *[]string `json:"omniborId,omitempty" cdx:"added:1.6"` + Swhid *[]string `json:"swhid,omitempty" cdx:"added:1.6"` + CryptoProperties *CDXCryptoProperties `json:"cryptoProperties,omitempty" cdx:"added:1.6"` + Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` + Manufacturer *CDXOrganizationalEntity `json:"manufacturer,omitempty" cdx:"added:1.6"` + Author string `json:"author,omitempty" cdx:"deprecated:1.6"` } // v1.5 added object // The general theme or subject matter of the data being specified. // TODO: "contents" is plural, but it is not an array type CDXComponentData struct { - Type string `json:"type,omitempty"` // Constraint: "enum": ["source-code","configuration","dataset","definition","other"] - Name string `json:"name,omitempty"` - BOMRef *CDXRefType `json:"bom-ref,omitempty"` - Contents *CDXContent `json:"contents,omitempty"` - Classification *CDXDataClassification `json:"classification,omitempty"` - SensitiveData []string `json:"sensitiveData,omitempty"` - Graphics *CDXGraphicsCollection `json:"graphics,omitempty"` - Description string `json:"description,omitempty"` - Governance *CDXDataGovernance `json:"governance,omitempty"` + Type string `json:"type,omitempty" cdx:"added:1.5"` // Constraint: "enum": ["source-code","configuration","dataset","definition","other"] + Name string `json:"name,omitempty" cdx:"added:1.5"` + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` + Contents *CDXContent `json:"contents,omitempty" cdx:"added:1.5"` + Classification *CDXDataClassification `json:"classification,omitempty" cdx:"added:1.5"` + SensitiveData []string `json:"sensitiveData,omitempty" cdx:"added:1.5"` + Graphics *CDXGraphicsCollection `json:"graphics,omitempty" cdx:"added:1.5"` + Description string `json:"description,omitempty" cdx:"added:1.5"` + Governance *CDXDataGovernance `json:"governance,omitempty" cdx:"added:1.5"` } // v1.5 added object type CDXContent struct { - Url string `json:"url,omitempty"` - Attachment *CDXAttachment `json:"attachment,omitempty"` - Properties *[]CDXProperty `json:"properties,omitempty"` + Url string `json:"url,omitempty" cdx:"added:1.5"` + Attachment *CDXAttachment `json:"attachment,omitempty" cdx:"added:1.5"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` } // v1.5 added type CDXDataGovernance struct { - Custodians *[]CDXDataGovernanceResponsibleParty `json:"custodians,omitempty"` - Stewards *[]CDXDataGovernanceResponsibleParty `json:"stewards,omitempty"` - Owners *[]CDXDataGovernanceResponsibleParty `json:"owners,omitempty"` + Custodians *[]CDXDataGovernanceResponsibleParty `json:"custodians,omitempty" cdx:"added:1.5"` + Stewards *[]CDXDataGovernanceResponsibleParty `json:"stewards,omitempty" cdx:"added:1.5"` + Owners *[]CDXDataGovernanceResponsibleParty `json:"owners,omitempty" cdx:"added:1.5"` } // v1.5 added structure // Constraints: "oneOf": ["organization", "contact"] type CDXDataGovernanceResponsibleParty struct { - Organization *CDXOrganizationalEntity `json:"organization,omitempty"` - Contact *CDXOrganizationalContact `json:"contact,omitempty"` + Organization *CDXOrganizationalEntity `json:"organization,omitempty" cdx:"added:1.5"` + Contact *CDXOrganizationalContact `json:"contact,omitempty" cdx:"added:1.5"` } // v1.2: existed @@ -194,16 +181,16 @@ type CDXService struct { Endpoints *[]string `json:"endpoints,omitempty"` Authenticated bool `json:"authenticated,omitempty"` XTrustBoundary bool `json:"x-trust-boundary,omitempty"` - TrustZone string `json:"trustZone,omitempty"` Provider *CDXOrganizationalEntity `json:"provider,omitempty"` Data *[]CDXServiceData `json:"data,omitempty"` Licenses *[]CDXLicenseChoice `json:"licenses,omitempty"` ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"` Services *[]CDXService `json:"services,omitempty"` - Properties *[]CDXProperty `json:"properties,omitempty"` // v1.3: added - ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty"` // v1.4: added - Signature *JSFSignature `json:"signature,omitempty"` // v1.4: added - Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` // v1.6: added + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.3"` + ReleaseNotes *[]CDXReleaseNotes `json:"releaseNotes,omitempty" cdx:"added:1.4"` + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` + TrustZone string `json:"trustZone,omitempty" cdx:"added:1.5"` + Tags *[]string `json:"tags,omitempty" cdx:"added:1.6"` } // v1.5: added. aggregated related date from v1.2-v1.4 and added additional fields @@ -213,11 +200,11 @@ type CDXService struct { type CDXServiceData struct { Flow string `json:"flow,omitempty"` Classification *CDXDataClassification `json:"classification,omitempty"` - Name string `json:"name,omitempty"` // v1.5: added - Description string `json:"description,omitempty"` // v1.5: added - Governance *CDXDataGovernance `json:"governance,omitempty"` // v1.5: added - Source string `json:"source,omitempty"` // v1.5: added - Destination string `json:"destination,omitempty"` // v1.5: added + Name string `json:"name,omitempty" cdx:"added:1.5"` + Description string `json:"description,omitempty" cdx:"added:1.5"` + Governance *CDXDataGovernance `json:"governance,omitempty" cdx:"added:1.5"` + Source string `json:"source,omitempty" cdx:"added:1.5"` + Destination string `json:"destination,omitempty" cdx:"added:1.5"` } // v1.2: existed as an anon. type in the "component" type defn. @@ -253,8 +240,8 @@ func (pedigree *CDXPedigree) isEmpty() bool { } // v1.2: existed -// v1.4: deprecated // See: https://www.iso.org/standard/65666.html +// NOTE: Swid v1 tag values are deprecated; new v2 tags are avail. type CDXSwid struct { TagId string `json:"tagId,omitempty"` Name string `json:"name,omitempty"` @@ -275,13 +262,13 @@ type CDXLicenseChoice struct { CDXLicenseExpression } -// v1.5: added structure +// v1.5: added "expression" type structure // v1.6: added Acknowledgment // NOTE: CDXRefType is a named `string` type as of v1.5 type CDXLicenseExpression struct { Expression string `json:"expression,omitempty"` - BOMRef *CDXRefType `json:"bom-ref,omitempty"` - Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` // v1.6: added + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` + Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` } // v1.2: was an anon. type @@ -296,22 +283,22 @@ type CDXLicense struct { Name string `json:"name,omitempty"` Text *CDXAttachment `json:"text,omitempty"` Url string `json:"url,omitempty"` - BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` // v1.5: added - Licensing *CDXLicensing `json:"licensing,omitempty" cdx:"added:1.5"` // v1.5: added - Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` // v1.5: added - Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` // v1.6: added + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` + Licensing *CDXLicensing `json:"licensing,omitempty" cdx:"added:1.5"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.5"` + Acknowledgement string `json:"acknowledgement,omitempty" cdx:"added:1.6"` } // v1.5: added object type CDXLicensing struct { - AltIds *[]string `json:"altIds,omitempty" cdx:"added:1.5"` // v1.5: added - Licensor *CDXLicenseLegalParty `json:"licensor,omitempty" cdx:"added:1.5"` // v1.5: added - Licensee *CDXLicenseLegalParty `json:"licensee,omitempty" cdx:"added:1.5"` // v1.5: added - Purchaser *CDXLicenseLegalParty `json:"purchaser,omitempty" cdx:"added:1.5"` // v1.5: added - PurchaseOrder string `json:"purchaseOrder,omitempty" cdx:"added:1.5"` // v1.5: added - LicenseTypes *[]string `json:"licenseTypes,omitempty" cdx:"added:1.5"` // v1.5: added - LastRenewal string `json:"lastRenewal,omitempty" cdx:"added:1.5"` // v1.5: added - Expiration string `json:"expiration,omitempty" cdx:"added:1.5"` // v1.5: added + AltIds *[]string `json:"altIds,omitempty" cdx:"added:1.5"` + Licensor *CDXLicenseLegalParty `json:"licensor,omitempty" cdx:"added:1.5"` + Licensee *CDXLicenseLegalParty `json:"licensee,omitempty" cdx:"added:1.5"` + Purchaser *CDXLicenseLegalParty `json:"purchaser,omitempty" cdx:"added:1.5"` + PurchaseOrder string `json:"purchaseOrder,omitempty" cdx:"added:1.5"` + LicenseTypes *[]string `json:"licenseTypes,omitempty" cdx:"added:1.5"` + LastRenewal string `json:"lastRenewal,omitempty" cdx:"added:1.5"` + Expiration string `json:"expiration,omitempty" cdx:"added:1.5"` } // v1.2: existed @@ -335,21 +322,21 @@ type CDXPatch struct { // v1.3 "url" type changed from `string` (with constraints) to an "iri-reference" type CDXDiff struct { Text *CDXAttachment `json:"text,omitempty"` - Url string `json:"url,omitempty"` // v1.3: type changed to "iri-reference" + Url string `json:"url,omitempty" cdx:"changed:1.3"` } // v1.2: existed // Note: v1.2 Bug: there appears to be a bug in the 1.2 spec. where the type for // "references" is declared an array of "no type" (it likely should be `string`) // Not sure how a parser will treat this... perhaps as an `interface{}`? -// v1.3: fixed to be []string +// v1.3: fixed missing item type to "string" ([]string) and constrained as an "iri-reference" type CDXIssue struct { Type string `json:"type,omitempty"` Id string `json:"id,omitempty"` Name string `json:"name,omitempty"` Description string `json:"description,omitempty"` Source *CDXSource `json:"source,omitempty"` - References *[]string `json:"references,omitempty"` // v1.3: added missing `string` type + References *[]string `json:"references,omitempty" cdx:"changed:1.3"` } // v1.2: existed as anon. type @@ -369,20 +356,11 @@ type CDXIdentifiableAction struct { Email string `json:"email,omitempty"` } -// v1.2: existed -// v1.3: added "hashes" -// v1.4: `Type` field: added value "release-notes" to enum. -type CDXExternalReference struct { - Type string `json:"type,omitempty"` - Url string `json:"url,omitempty"` - Comment string `json:"comment,omitempty"` - Hashes *[]CDXHash `json:"hashes,omitempty"` // v1.3: added -} - // v1.2: existed // v1.4: "ref" and "dependsOn" became type "refType" which is a constrained `string` // v1.5: "ref": is now a constrained "string" of type "#/definitions/refLinkType" // v1.5: "dependsOn": is now a constrained "string" of type "#/definitions/refLinkType" +// Note: Changes to RefType and RefLinkType are ONLY constraint changes; we need only track type changes... type CDXDependency struct { Ref *CDXRefLinkType `json:"ref,omitempty"` DependsOn *[]CDXRefLinkType `json:"dependsOn,omitempty"` @@ -468,32 +446,40 @@ type CDXFrames struct { // TODO: Should NOT be plural; open issue against v2.0 schema // NOTE: CDXRefType is a named `string` type as of v1.5 type CDXCompositions struct { - Aggregate string `json:"aggregate,omitempty"` - Assemblies *[]string `json:"assemblies,omitempty"` - Dependencies *[]string `json:"dependencies,omitempty"` - Signature *JSFSignature `json:"signature,omitempty"` // v1.4: added - Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty"` // v1.5: added - BOMRef *CDXRefType `json:"bom-ref,omitempty"` // v1.5: added + Aggregate string `json:"aggregate,omitempty" cdx:"added:1.3"` + Assemblies *[]string `json:"assemblies,omitempty" cdx:"added:1.3"` + Dependencies *[]string `json:"dependencies,omitempty" cdx:"added:1.3"` + Signature *JSFSignature `json:"signature,omitempty" cdx:"added:1.4"` + Vulnerabilities *[]CDXVulnerability `json:"vulnerabilities,omitempty" cdx:"added:1.5"` + BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"added:1.5"` } // v1.4: created "releaseNotes" defn. // TODO: should be singular "releaseNote" +// TODO: v1.7: Add []ExternalReferences +// TODO: v1.7: "Tags" is an overloaded concept... currently doesn't represent GitHub tags type CDXReleaseNotes struct { - Type string `json:"type,omitempty"` - Title string `json:"title,omitempty"` - FeaturedImage string `json:"featuredImage,omitempty"` - SocialImage string `json:"socialImage,omitempty"` - Description string `json:"description,omitempty"` - Timestamp string `json:"timestamp,omitempty"` - Aliases *[]string `json:"aliases,omitempty"` - Tags *[]string `json:"tags,omitempty"` - Resolves *[]CDXIssue `json:"resolves,omitempty"` - Notes *[]CDXNote `json:"notes,omitempty"` - Properties *[]CDXProperty `json:"properties,omitempty"` + Type string `json:"type,omitempty" cdx:"added:1.4"` + Title string `json:"title,omitempty" cdx:"added:1.4"` + FeaturedImage string `json:"featuredImage,omitempty" cdx:"added:1.4"` + SocialImage string `json:"socialImage,omitempty" cdx:"added:1.4"` + Description string `json:"description,omitempty" cdx:"added:1.4"` + Timestamp string `json:"timestamp,omitempty" cdx:"added:1.4"` + Aliases *[]string `json:"aliases,omitempty" cdx:"added:1.4"` + Tags *[]string `json:"tags,omitempty" cdx:"added:1.4"` + Resolves *[]CDXIssue `json:"resolves,omitempty" cdx:"added:1.4"` + Notes *[]CDXNote `json:"notes,omitempty" cdx:"added:1.4"` + Properties *[]CDXProperty `json:"properties,omitempty" cdx:"added:1.4"` } type CDXLifecycle struct { // v1.5: "enum": [ "design", "pre-build", "build", "post-build", "operations", "discovery", "decommission"] - Phase string `json:"phase,omitempty"` + Phase string `json:"phase,omitempty" cdx:"added:1.5"` CDXNameDescription // name, description } + +// v1.5 new type for "metadata" +type CDXNameDescription struct { + Name string `json:"name,omitempty" cdx:"added:1.5"` + Description string `json:"description,omitempty" cdx:"added:1.5"` +} diff --git a/schema/cyclonedx_common.go b/schema/cyclonedx_common.go index 9a4d794..5fa5bce 100644 --- a/schema/cyclonedx_common.go +++ b/schema/cyclonedx_common.go @@ -62,6 +62,16 @@ func (link CDXBomLink) String() string { return string(link) } +// v1.2: existed +// v1.3: added "hashes" +// v1.4: `Type` field: added value "release-notes" to enum. +type CDXExternalReference struct { + Type string `json:"type,omitempty"` + Url string `json:"url,omitempty"` + Comment string `json:"comment,omitempty"` + Hashes *[]CDXHash `json:"hashes,omitempty"` // v1.3: added +} + // v1.2: existed type CDXAttachment struct { ContentType string `json:"contentType,omitempty"` @@ -70,7 +80,6 @@ type CDXAttachment struct { } func (attachment *CDXAttachment) GetContentTruncated(maxLength int, addTruncatedMessage bool) string { - if length := len(attachment.Content); length > maxLength { if addTruncatedMessage { return fmt.Sprintf("%s (truncated from %v) ...", attachment.Content[0:maxLength], length) @@ -88,19 +97,6 @@ type CDXHash struct { Content string `json:"content,omitempty"` } -// v1.5 new type for "metadata" -type CDXNameDescription struct { - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` -} - -// v1.4: created "note" defn. -// Note: "locale" is of type "localeType" which is a constrained `string` -type CDXNote struct { - Locale string `json:"locale,omitempty"` - Text *CDXAttachment `json:"attachment,omitempty"` -} - // v1.2: existed // v1.5: added "bom-ref" // v1.6: added "address" @@ -129,11 +125,11 @@ type CDXProperty struct { Value string `json:"value,omitempty"` } -// v1.5: created for reuse in "licensing" schema for "licensee" and "licensor" -// TODO: reuse on "annotator" as well? -type CDXLicenseLegalParty struct { - Organization *CDXOrganizationalEntity `json:"organization,omitempty"` - Individual *CDXOrganizationalContact `json:"individual,omitempty"` +// v1.4: created "note" defn. +// Note: "locale" is of type "localeType" which is a constrained `string` +type CDXNote struct { + Locale string `json:"locale,omitempty"` + Text *CDXAttachment `json:"attachment,omitempty"` } // v1.2: existed @@ -142,6 +138,8 @@ type CDXLicenseLegalParty struct { // - v1.5 Note: The v1.4 structure/fields is now called the "Creation Tools (legacy)" structure // - v1.5: In order to support the new object "Creation Tools", we need to combine these fields // into with the legacy structure fields +// TODO: figure out how to support both current (object)/legacy(array) tools in Metadata.Tools field +// See: https://stackoverflow.com/questions/47057240/parsing-multiple-json-types-into-the-same-struct type CDXLegacyCreationTool struct { Vendor string `json:"vendor,omitempty" cdx:"deprecated"` // v1.5: deprecated Name string `json:"name,omitempty" cdx:"deprecated"` // v1.5: deprecated @@ -155,3 +153,10 @@ type CDXCreationTools struct { Components *[]CDXComponent `json:"components,omitempty" cdx:"+1.5"` // v1.5: added (new type) Services *[]CDXService `json:"services,omitempty" cdx:"+1.5"` // v1.5: added (new type) } + +// v1.5: created for reuse in "licensing" schema for "licensee" and "licensor" +// TODO: reuse on "annotator" as well? +type CDXLicenseLegalParty struct { + Organization *CDXOrganizationalEntity `json:"organization,omitempty"` + Individual *CDXOrganizationalContact `json:"individual,omitempty"` +} diff --git a/schema/cyclonedx_modelcard.go b/schema/cyclonedx_modelcard.go index 8f0a341..e390aad 100644 --- a/schema/cyclonedx_modelcard.go +++ b/schema/cyclonedx_modelcard.go @@ -24,6 +24,9 @@ package schema // v1.5: added // NOTE: CDXRefType is a named `string` type as of v1.5 +// TODO: v1.7: How to represent an AI App. (e.g., a Chatbot) using a model +// with components like embeddings (vector DB), re-rankers, etc. +// also consider distinguishing model capabilities: e.g., generative/classification; types (multi-model, LLM, LM, etc.) type CDXModelCard struct { BOMRef *CDXRefType `json:"bom-ref,omitempty" cdx:"+1.5"` // v1.5 ModelParameters *CDXModelParameters `json:"modelParameters,omitempty" cdx:"+1.5"` // v1.5 From be85aaa48d94f166fa29e8a3956d35af33251e54 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 13:46:54 -0500 Subject: [PATCH 14/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c616b44..8974395 100644 --- a/README.md +++ b/README.md @@ -14,23 +14,23 @@ In addition, the utility features "report" commands that can easily extract, fil The utility also offers commands that support analysis and editing of BOM document data including **trim**, **patch** (IETF RFC 6902) and **diff**. -> **Note**: *The utility supports all CycloneDX BOM variants, such as **Software** (SBOM), **Hardware** (HBOM), **Manufacturing** (MBOM), **AI/ML** (MLBOM), **Cryptographic** (CBOM), etc., that adhere to their respective schemas.* +> **Note**: *The utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc., that adhere to their respective schemas.* ## Command Overview -The following commands, which operate against input BOMs and named resources within them, are offered by the utility. They are presented by category +The following commands, which operate against input BOMs and their data, are offered by the utility: | Command *[subcommand]* | Description | | :-- | :-- | -| **[validate](#validate)** |enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.| +| **[validate](#validate)** | Enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.| | **[patch](#patch)** | Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. | -| **[trim](#trim)** | provides the ability to remove specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information.

*A "SQL-like" set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths.* | -| **[query](#query)** | retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select --from --where `). The JSON data can be used to create custom listings or reports. | -| **[component](#component)** **[`list`](#component-list-command)** | produces filterable listings of hardware or software components declared in the BOM. | -| **[license](#license)** **[`list`](#license-list-subcommand)** | produces filterable listings of license data declared in the BOM along with the associated component or service. Includes *"usage policy"* determinations as declared in the `license.json` configuration file. | -| **[license](#license)** **[`policy`](#license-policy-subcommand)** | lists software and data license information and associated license usage policies as defined in the configurable `license.json` file. | -| **[resource `list`](#resource)** | produces filterable listings of resources (i.e., components and services) declared in the BOM. | -| **[schema `list`](#schema)** | produces filterable listings of schema formats, versions and variants supported by the `validation` command.

**Note**: Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). | +| **[trim](#trim)** | Removes specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information.

*A "SQL-like" set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths.* | +| **[query](#query)** | Retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select --from --where `). The JSON data can be used to create custom listings or reports. | +| **[component](#component)** **[`list`](#component-list-command)** | Produces filterable listings of hardware or software components declared in the BOM. | +| **[license](#license)** **[`list`](#license-list-subcommand)** | Produces filterable listings of license data declared in the BOM along with the associated component or service. Includes *"usage policy"* determinations as declared in the `license.json` configuration file. | +| **[license](#license)** **[`policy`](#license-policy-subcommand)** | Produces filterable listings of software and data license information and associated license usage policies as defined a `license.json` configuration file. | +| **[resource `list`](#resource)** | Produces filterable listings of resources (i.e., components and services) declared in the BOM. | +| **[schema `list`](#schema)** | Produces filterable listings of schema formats, versions and variants supported by the `validation` command.

**Note**: Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). | | **[vulnerability `list`](#vulnerability)** | produces filterable listings of vulnerabilities declared in the BOM (i.e., CycloneDX Vulnerability Exploitability eXchange (**VEX**)) data or independently stored CycloneDX Vulnerability Disclosure Report (**VDR**) data stored in the BOM format. | **Experimental commands**: @@ -51,16 +51,8 @@ Feedback and helpful commits appreciated on the following commands which will be - [Exit codes](#exit-codes): (e.g., `0`: none, `1`: application, `2`: validation) - [Persistent flags](#persistent-flags) (e.g., `--format`, `--quiet`, `--where`, etc.) - [Design considerations](#design-considerations) -- [Development](#development) - - [Prerequisites](#prerequisites) - - [Building](#building) - - [Running from source](#running-from-source) - - [Debugging](#debugging) - - [VSCode](#vscode) - - [Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants) - [Contributing](#contributing) - - [TODO list](#todo-list) - - [Priority features](#priority-features) +- [Development](#development) - [Testing](#testing) - [Go test files](#go-test-files) - [Running tests](#running-tests) @@ -2325,6 +2317,15 @@ In the future, we envision support for additional kinds of BOMs (e.g., Hardware ### Development +The following development-oriented topics are included in this section: + +- [Prerequisites](#prerequisites) +- [Building](#building) +- [Running from source](#running-from-source) +- [Debugging](#debugging) + - [Using VSCode](#vscode) +- [Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants) + #### Prerequisites - Go v1.20.1 or higher: see [https://go.dev/doc/install](https://go.dev/doc/install) @@ -2442,7 +2443,10 @@ The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `prop ### Contributing -Contributions are welcome under the Apache 2.0 license. +Contributions are welcome under the Apache 2.0 license. Help is wanted in the following areas: + +- [TODO list](#todo-list) +- [Priority features](#priority-features) #### TODO list From 029f9ba8a3be9a7d3e3d7b076853e52af5db37cc Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:08:54 -0500 Subject: [PATCH 15/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8974395..3d497a4 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The utility also offers commands that support analysis and editing of BOM docume The following commands, which operate against input BOMs and their data, are offered by the utility: -| Command *[subcommand]* | Description | +| Command *[`subcommand`]* | Description | | :-- | :-- | | **[validate](#validate)** | Enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.| | **[patch](#patch)** | Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. | @@ -54,10 +54,10 @@ Feedback and helpful commits appreciated on the following commands which will be - [Contributing](#contributing) - [Development](#development) - [Testing](#testing) - - [Go test files](#go-test-files) - - [Running tests](#running-tests) - [Releasing](#releasing) -- [References](#references): [CycloneDX](#cyclonedx), [SPDX](#spdx) +- [BOM References](#bom-references) + - [CycloneDX](#cyclonedx) + - [SPDX](#spdx) --- @@ -2516,9 +2516,18 @@ An example `schema` object for the canonical SPDX v2.3 (default, no variant) sch ## Testing -### Go test files +Testing implementation and invocation, with examples, is described in this section including: -The built-in `go test` command is used to execute all functional tests that appear in `*._test.go` files. By default, `go test` executes tests within the same directory where its respective `*._test.go` file is located and sets that as the working directory. For example, tests in the `validate_test.go` file are executed from the `cmd` subdirectory. This is a problem as the actual test SBOM JSON test files are located relative the project root, one level higher, and would not be found. In order to correct for that, the test working directory is automatically changed for all tests within the `TestMain` routine found in `root_test.go`. +- [Authoring Go test files](#authoring-go-test-files) +- [Running tests](#running-tests) + +### Authoring Go test files + +The built-in `go test` command will execute all functional tests that appear in files named with the pattern: `_test.go`. These files are executed from within the same directory (package) where its respective `.go` source code file is located and sets that same as the "working directory". + +*For example,* tests in the `validate_test.go` file are executed from the `cmd` subdirectory. + +This is normally a problem as the actual test SBOM JSON test files are located relative the project root, one level higher, and would not be found by the "working directory". In order to correct for that, the test working directory is automatically changed for all tests within the `TestMain` routine found in `root_test.go`. ### Running tests @@ -2642,7 +2651,18 @@ $ go build ${LDFLAGS} -o ${BINARY} --- -## References +## BOM References + +### Software-Bill-of-Materials (SBOM) + +- [NTIA - SBOM Minimum Requirements](https://www.ntia.doc.gov/blog/2021/ntia-releases-minimum-elements-software-bill-materials) +- [CISA - Software Bill of Materials (SBOM)](https://www.cisa.gov/sbom) +- [FOSSA - Software Bill Of Materials: Formats, Use Cases, and Tools](https://fossa.com/blog/software-bill-of-materials-formats-use-cases-tools/) + +#### Guides + +- [FOSSA](https://fossa.com/) + - *["A Practical Guide to CycloneDX"](https://fossa.com/cyclonedx)* ### CycloneDX @@ -2676,14 +2696,3 @@ $ go build ${LDFLAGS} -o ${BINARY} - Tools - [SPDX Online Tool](https://tools.spdx.org/app/) - **Note** Used the [convert](https://tools.spdx.org/app/convert/) tool to convert SPDX examples from `.tv` format to `.json`; however, conversion of [`example6-bin.spdx`](https://github.com/spdx/spdx-examples/blob/master/example6/spdx/example6-bin.spdx) resulted in an error. - -### Software-Bill-of-Materials (SBOM) - -- [NTIA - SBOM Minimum Requirements](https://www.ntia.doc.gov/blog/2021/ntia-releases-minimum-elements-software-bill-materials) -- [CISA - Software Bill of Materials (SBOM)](https://www.cisa.gov/sbom) -- [FOSSA - Software Bill Of Materials: Formats, Use Cases, and Tools](https://fossa.com/blog/software-bill-of-materials-formats-use-cases-tools/) - -#### Guides - -- [FOSSA](https://fossa.com/) - - *["A Practical Guide to CycloneDX"](https://fossa.com/cyclonedx)* From 16f20464ef61ec1654bd603d5cd8618ac0339ed9 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:12:21 -0500 Subject: [PATCH 16/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3d497a4..c1a9d5d 100644 --- a/README.md +++ b/README.md @@ -43,21 +43,18 @@ Feedback and helpful commits appreciated on the following commands which will be --- -## Index +### Project Index - [Installation](#installation) - [Running](#running) - [Commands](#commands) - - [Exit codes](#exit-codes): (e.g., `0`: none, `1`: application, `2`: validation) - - [Persistent flags](#persistent-flags) (e.g., `--format`, `--quiet`, `--where`, etc.) - [Design considerations](#design-considerations) - [Contributing](#contributing) - [Development](#development) - [Testing](#testing) - [Releasing](#releasing) - [BOM References](#bom-references) - - [CycloneDX](#cyclonedx) - - [SPDX](#spdx) + - [CycloneDX](#cyclonedx), [SPDX](#spdx) --- @@ -101,6 +98,8 @@ This section provides detailed descriptions of all commands, their flags and exa For convenience, links to each command's section are here: +- [Exit codes](#exit-codes): *e.g., `0`: none, `1`: application, `2`: validation* +- [Persistent flags](#persistent-flags) *e.g., `--format`, `--quiet`, `--where`, etc.* - [validate](#validate): validates BOM data against declared or required JSON schema. - [trim](#trim): removes uninteresting or necessary fields and data from a BOM. - [patch](#patch): patches BOMs using IETF RFC 6902 records. From 007c1217cc67f70991b4da1532573c4755196bb9 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:20:38 -0500 Subject: [PATCH 17/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c1a9d5d..e7ddb74 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ The following commands, which operate against input BOMs and their data, are off | **[validate](#validate)** | Enables validation of SBOMs against their declared format (e.g., SPDX, CycloneDX) and version (e.g., "2.3", "1.6", etc.) using their JSON schemas.| | **[patch](#patch)** | Applies a JSON patch file, as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/), to an input JSON BOM file. | | **[trim](#trim)** | Removes specified JSON information from the input JSON BOM document and produce output BOMs with reduced or targeted sets of information.

*A "SQL-like" set of parameters allows for fine-grained specification of which fields should be trimmed from which document paths.* | +| **[diff](#diff)** | **Experimental**[1](#experimental-commands): Displays the delta between two similar BOM versions in JSON (diff) patch format as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/). *Please read "recommendations" before running.* | | **[query](#query)** | Retrieves JSON data from BOMs using SQL-style query statements (i.e., `--select --from --where `). The JSON data can be used to create custom listings or reports. | | **[component](#component)** **[`list`](#component-list-command)** | Produces filterable listings of hardware or software components declared in the BOM. | | **[license](#license)** **[`list`](#license-list-subcommand)** | Produces filterable listings of license data declared in the BOM along with the associated component or service. Includes *"usage policy"* determinations as declared in the `license.json` configuration file. | @@ -33,13 +34,8 @@ The following commands, which operate against input BOMs and their data, are off | **[schema `list`](#schema)** | Produces filterable listings of schema formats, versions and variants supported by the `validation` command.

**Note**: Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file (see the `schema` command's [adding schemas](#adding-schemas) section). | | **[vulnerability `list`](#vulnerability)** | produces filterable listings of vulnerabilities declared in the BOM (i.e., CycloneDX Vulnerability Exploitability eXchange (**VEX**)) data or independently stored CycloneDX Vulnerability Disclosure Report (**VDR**) data stored in the BOM format. | -**Experimental commands**: - -Feedback and helpful commits appreciated on the following commands which will be promoted after at least two point releases: - -| Command | Description | -| :-- | :-- | -| **[diff](#diff)** | Shows the delta between two similar BOM versions in JSON (diff) patch format as defined by [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/). | +> **Experimental commands**: +*Testing, feedback and helpful suggestions and code commits are appreciated on experimental commands.* --- From bb096ef26034a30e00a0ea46823b6f4bdc160ce3 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:53:39 -0500 Subject: [PATCH 18/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 2218 ++++++++++++++++++++++++++--------------------------- 1 file changed, 1109 insertions(+), 1109 deletions(-) diff --git a/README.md b/README.md index e7ddb74..7822b98 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This utility was designed to be an API platform to validate, analyze and edit ** - *Organizations may also design and supply **"custom JSON schema"** variants to the validate command which are perhaps designed to assure additional data-compliance requirements are met.* -In addition, the utility features "report" commands that can easily extract, filter, list and summarize **component**, **service**, **license**, **resource**, **vulnerability** and other BOM information using the utility's powerful, SQL-like query command. The **query** command allows **select**-ion of specific data **from** anywhere in the BOM document **where** data values match specified (regex) patterns. +In addition, the utility features "report" commands that can easily *extract*, *filter*, *list* and *summarize* **component**, **service**, **license**, **resource**, **vulnerability** and other BOM information using the utility's powerful, SQL-like query command. The **query** command allows **select**-ion of specific data **from** anywhere in the BOM document **where** data values match specified (regex) patterns. - *Report output can be produced in several formats (e.g., `txt`, `csv`, `md` (markdown) and `json`) to accommodate further processing.* @@ -90,31 +90,31 @@ On MacOS, the utility is not a registered Apple application and may warn you tha ## Commands -This section provides detailed descriptions of all commands, their flags and examples. First we will cover how all commands generate consistent [exit codes](#exit-codes) and describe some of the [persistent flags](#persistent-flags) supported by most commands. +This section provides detailed descriptions of all commands, supported flags and output formats along with usage examples. -For convenience, links to each command's section are here: +All commands generate consistent [exit codes](#exit-codes) as well as share some [persistent flags](#persistent-flags) which are described here: -- [Exit codes](#exit-codes): *e.g., `0`: none, `1`: application, `2`: validation* -- [Persistent flags](#persistent-flags) *e.g., `--format`, `--quiet`, `--where`, etc.* -- [validate](#validate): validates BOM data against declared or required JSON schema. -- [trim](#trim): removes uninteresting or necessary fields and data from a BOM. -- [patch](#patch): patches BOMs using IETF RFC 6902 records. -- [query](#query): extracts JSON objects and fields from a BOM using SQL-like queries. -- [component list](#component): lists all, top-level component information. -- [license](#license) - - [list](#license-list-subcommand) subcommand: lists all license information found in the BOM. - - [policy](#license-policy-subcommand) subcommand: lists configurable license usage policies. -- [resource list](#resource): lists resource information by type (e.g., components, services). -- [schema list](#schema): lists supported JSON schemas by BOM formats, versions and variants. -- [vulnerability list](#vulnerability): lists vulnerability summary information included in a BOM or standalone VDR BOM. -- [completion](#completion): generates command-line completion scripts for the this utility. -- [help](#help): displays help and usage information for the utility or current command/subcommand. +- [Exit codes](#exit-codes): Including: *`0`: no error, `1`: application error, `2`: validation error, etc.* +- [Persistent flags](#persistent-flags) Including: *`--input`, `--output`, `--format`, `--quiet`, `--where`, etc.* -### Experimental commands +Convenient links to each command: -These commands need more community testing and feedback. +- [validate](#validate): Validates BOM data against declared or required JSON schema. +- [trim](#trim): Removes uninteresting or necessary fields and data from a BOM. +- [patch](#patch): Patches BOMs using IETF RFC 6902 records. +- [diff](#diff): *(Experimental)*: Displays the differences between two similar BOMs. *Please read recommendations before executing.* +- [query](#query): Extracts JSON objects and fields from a BOM using SQL-like queries. +- [component list](#component): Lists all component information found in a BOM. +- [license](#license) + - [list](#license-list-subcommand): Lists all license information found in a BOM. + - [policy](#license-policy-subcommand): Lists configurable license usage policies found in the `license.json` file. +- [resource list](#resource): Lists all resource information by type (e.g., components, services). +- [schema list](#schema): Lists supported JSON schemas by BOM format, version and variant. +- [vulnerability list](#vulnerability): Lists vulnerability (i.e., `VEX`) information included in a BOM or standalone `VDR` BOM. +- [completion](#completion): Generates command-line completion scripts for the this utility. +- [help](#help): Displays help and usage information for the utility or currently specified command. -- [diff](#diff): compares differences between two similar BOMs. +--- #### Exit codes @@ -146,6 +146,8 @@ which returns `0` (zero) or "no error": 0 ``` +--- + ### Persistent flags This section describes some of the important command line flags that apply to most of the utility's commands. @@ -190,11 +192,11 @@ This example uses the `--format` flag on the `schema` command to output in markd |SPDX v2.2.1|SPDX|SPDX-2.2|2.2.1|schema/spdx/2.2.1/spdx-schema.json|https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json| ``` -### Indent flag +#### Indent flag This flag supplies an integer to any command that encodes JSON output to determine how many spaces to indent nested JSON elements. If not specified, the default indent is `4` (spaces). -#### Example: indent flag on the query command +##### Example: indent flag on the query command ```bash ./sbom-utility query --select name,version --from metadata.component -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --indent 2 -q @@ -309,402 +311,423 @@ See each command's section for contextual examples of the `--where` flag filter --- -## Component +### Validate -Primarily, this command is used to generate lists of components that are included in a CycloneDX SBOM. +This command will parse standardized SBOMs and validate it against its declared format and version (e.g., SPDX 2.2, CycloneDX 1.4). Custom variants of standard JSON schemas can be used for validation by supplying the `--variant` name as a flag. Explicit JSON schemas can be specified using the `--force` flag. -### Component `list` command +#### Validating using supported schemas -This command is used to extract, filter and list CycloneDX BOM `Component` data. +Use the [schema](#schema) command to list supported schemas formats, versions and variants. -#### Component list supported formats +#### Validating using "custom" schemas -This command supports the `--format` flag with any of the following values: +Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file. See [adding schemas](#adding-schemas). -- `txt` (default), `csv`, `md` +- **"Customized" schema** variants, perhaps derived from standard BOM schemas, can be used for validation using the `--variant` flag (e.g., industry or company-specific schemas). +- **Overriding default schema** - You can override an BOM's declared BOM version using the `--force` flag (e.g., verify a BOM against a newer specification version). -#### Component list flags +#### Validate flags -##### Component list `--summary` flag +The following flags can be used to improve performance when formatting error output results: -Use the `--summary` flag on the `component list` command to produce a summary report with reduced column information. +##### `--error-limit` flag -#### Component list examples +Use the `--error-limit x` (default: `10`) flag to reduce the formatted error result output to the first `x` errors. By default, only the first 10 errors are output with an informational messaging indicating `x/y` errors were shown. -##### Example: `component list` +##### `--error-value` flag -This example shows the component list with all column information display. Since CycloneDX component data can be very extensive, many columns simply indicate the component `has` more data available which can be extracted using the `query` command if needed. +Use the `--error-value=true|false` (default: `true`) flag to reduce the formatted error result output by not showing the `value` field which shows detailed information about the failing data in the BOM. + +##### `--colorize` flag + +Use the `--colorize=true|false` (default: `false`) flag to add/remove color formatting to error result `txt` formatted output. By default, `txt` formatted error output is colorized to help with human readability; for automated use, it can be turned off. + +#### Validate Examples + +##### Example: Validate using inferred format and schema + +Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository. ```bash -./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json -q +./sbom-utility validate -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json ``` -```text -bom-ref group type name version description copyright supplier-name supplier-url manufacturer-name manufacturer-url publisher purl swid-tag-id cpe mime-type scope number-hashes number-licenses has-pedigree has-evidence has-components has-release-notes has-model-card has-data has-tags has-signature -------- ----- ---- ---- ------- ----------- --------- ------------- ------------ ----------------- ---------------- --------- ---- ----------- --- --------- ----- ------------- --------------- ------------ ------------ -------------- ----------------- -------------- -------- -------- ------------- - application Acme Application 9.1.1 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1 0 0 false false false false false false false false -pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 pkg:npm/acme/component@1.0.0 4 1 true false false false false false false false - org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org required 0 0 true false false false false false false false +```bash +[INFO] Loading (embedded) default schema config file: `config.json`... +[INFO] Loading (embedded) default license policy file: `license.json`... +[INFO] Attempting to load and unmarshal data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`... +[INFO] Successfully unmarshalled data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json` +[INFO] Determining file's BOM format and version... +[INFO] Determined BOM format, version (variant): `CycloneDX`, `1.2` (latest) +[INFO] Matching BOM schema (for validation): schema/cyclonedx/1.2/bom-1.2.schema.json +[INFO] Loading schema `schema/cyclonedx/1.2/bom-1.2.schema.json`... +[INFO] Schema `schema/cyclonedx/1.2/bom-1.2.schema.json` loaded. +[INFO] Validating `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`... +[INFO] BOM valid against JSON schema: `true` ``` -##### Example: `component list` summary only - -The same BOM component information as in the previous example; however, using the summary flag to reduce the number of columns data. +You can also verify the [exit code](#exit-codes) from the validate command: ```bash -./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json --summary -q +echo $? ``` -```text -bom-ref group type name version description copyright supplier-name supplier-url manufacturer-name manufacturer-url publisher purl swid-tag-id cpe number-hashes number-licenses -------- ----- ---- ---- ------- ----------- --------- ------------- ------------ ----------------- ---------------- --------- ---- ----------- --- ------------- --------------- - application Acme Application 9.1.1 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1 0 0 -pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 pkg:npm/acme/component@1.0.0 4 1 - org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org 0 0 +```bash +0 // no error (valid) ``` ---- - -### License +#### Example: Validate using "custom" schema variants -This command is used to aggregate and summarize software, hardware and data license information included in the SBOM. It also displays license usage policies for resources based upon concluded by SPDX license identifier, license family or logical license expressions as defined in he current policy file (i.e., `license.json`). +The validation command will use the declared format and version found within the SBOM JSON file itself to lookup the default (latest) matching schema version (as declared in`config.json`; however, if variants of that same schema (same format and version) are declared, they can be requested via the `--variant` command line flag: -The `license` command supports the following subcommands: +```bash +./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom +``` -- [list](#license-list-subcommand) - list or create a summarized report of licenses found in input SBOM. - - [list with --summary flag](#license-list---summary-flag) - As full license information can be very large, a summary view is often most useful. -- [policy](#license-policy-subcommand) - list user configured license policies by SPDX license ID, family name and other filters. +If you run the sample command above, you would see several "custom" schema errors resulting in an invalid SBOM determination (i.e., `exit status 2`): ---- +```text +[INFO] Loading (embedded) default schema config file: `config.json`... +[INFO] Loading (embedded) default license policy file: `license.json`... +[INFO] Attempting to load and unmarshal data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`... +[INFO] Successfully unmarshalled data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json` +[INFO] Determining file's BOM format and version... +[INFO] Determined BOM format, version (variant): `CycloneDX`, `1.4` custom +[INFO] Matching BOM schema (for validation): schema/test/bom-1.4-custom.schema.json +[INFO] Loading schema `schema/test/bom-1.4-custom.schema.json`... +[INFO] Schema `schema/test/bom-1.4-custom.schema.json` loaded. +[INFO] Validating `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`... +[INFO] BOM valid against JSON schema: `false` +[INFO] (3) schema errors detected. +[INFO] Formatting error results (`txt` format)... +1. { + "type": "contains", + "field": "metadata.properties", + "context": "(root).metadata.properties", + "description": "At least one of the items must match", + "value": [ + { + "name": "urn:example.com:disclaimer", + "value": "This SBOM is current as of the date it was generated." + }, + { + "name": "urn:example.com:classification", + "value": "This SBOM is Confidential Information. Do not distribute." + } + ] + } +2. { + "type": "const", + "field": "metadata.properties.0.value", + "context": "(root).metadata.properties.0.value", + "description": "metadata.properties.0.value does not match: \"This SBOM is current as of the date it was generated and is subject to change.\"", + "value": "This SBOM is current as of the date it was generated." + } +3. { + "type": "number_all_of", + "field": "metadata.properties", + "context": "(root).metadata.properties", + "description": "Must validate all the schemas (allOf)", + "value": [ + { + "name": "urn:example.com:disclaimer", + "value": "This SBOM is current as of the date it was generated." + }, + { + "name": "urn:example.com:classification", + "value": "This SBOM is Confidential Information. Do not distribute." + } + ] + } +[ERROR] invalid SBOM: schema errors found (test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json) +[INFO] document `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`: valid=[false] +``` -### License `list` subcommand +confirming the exit code: -The `list` subcommand produces JSON output which contains an array of CycloneDX `LicenseChoice` data objects found in the BOM input file without component association. `LicenseChoice` data, in general, may provide license information using registered SPDX IDs, license expressions (of SPDX IDs) or license names (not necessarily registered by SPDX). License data may also include base64-encoded license or legal text that was used to determine a license's SPDX ID or name. +```bash +echo $? +``` -#### License list supported formats +```bash +2 // SBOM error +``` -This command supports the `--format` flag with any of the following values: +##### Why validation failed -- `json` (default), `csv`, `md` - - using the `--summary` flag: `txt` (default), `csv`, `md` +The output shows a first schema error indicating the failing JSON object; in this case, -#### License list result sorting +- the CycloneDX `metadata.properties` field, which is a list of `property` objects. +- Found that a property with a `name` field with the value `"urn:example.com:disclaimer"` had an incorrect `value`. + - the `value` field SHOULD have had a constant value of `"This SBOM is current as of the date it was generated and is subject to change."` (as was required by the custom schema's regex). + - However, it was found to have only a partial match of `"This SBOM is current as of the date it was generated."`. -- Results are not sorted for base `license list` subcommand. - - using the `--summary` flag: results are sorted (ascending) by license key which can be one of license `id` (SPDX ID), `name` or `expression`. +##### Details of the schema error -#### License list flags +Use the `--debug` or `-d` flag to see all schema error details: -##### License list `--summary` flag +```bash +./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom -d +``` -Use the `--summary` flag on the `license list` command to produce a summary report in `txt` (default) format as well as policy determination based upon the `license.json` declarations. +The details include the full context of the failing `metadata.properties` object which also includes a `"urn:example.com:classification"` property: -#### License list examples +```bash +3. { + "type": "number_all_of", + "field": "metadata.properties", + "context": "(root).metadata.properties", + "description": "Must validate all the schemas (allOf)", + "value": [ + { + "name": "urn:example.com:disclaimer", + "value": "This SBOM is current as of the date it was generated." + }, + { + "name": "urn:example.com:classification", + "value": "This SBOM is Confidential Information. Do not distribute." + } + ] + } +``` -##### Example: license list JSON +#### Example: Validate using "JSON" format -This example shows a few entries of the JSON output that exhibit the three types of license data described above: +The JSON format will provide an `array` of schema error results that can be post-processed as part of validation toolchain. ```bash -./sbom-utility license list -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --format json -q +./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json -q ``` ```json [ { - "license": { - "$comment": "by license `id", - "id": "MIT", - "name": "", - "url": "" + "type": "unique", + "field": "components", + "context": "(root).components", + "description": "array items[1,2] must be unique", + "value": { + "type": "array", + "index": 1, + "item": { + "bom-ref": "pkg:npm/body-parser@1.19.0", + "description": "Node.js body parsing middleware", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "name": "body-parser", + "purl": "pkg:npm/body-parser@1.19.0", + "type": "library", + "version": "1.19.0" + } } }, { - "license": { - "$comment": "by license `expression", - "id": "", - "name": "", - "url": "" - }, - "expression": "Apache-2.0 AND (MIT OR GPL-2.0-only)" - }, - { - "license": { - "$comment": "by license `name` with full license encoding", - "id": "", - "name": "Apache 2", - "text": { - "contentType": "text/plain", - "encoding": "base64", - "content": "CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFwYWNoZSBMaWNlbnNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlcnNpb24 ..." - }, - "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" - } - }, - ... -] -``` - -###### Example: license list `--summary` - -This example shows the default text output from using the summary flag: - -```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary -q -``` - -```bash -usage-policy license-type license resource-name bom-ref bom-location ------------- ------------ ------- ------------- ------- ------------ -needs-review id ADSL Foo service:example.com/myservices/foo services -needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components -allow name Apache Library B pkg:lib/libraryB@1.0.0 components -allow id Apache-1.0 Library E pkg:lib/libraryE@1.0.0 components -allow id Apache-2.0 N/A N/A metadata.licenses -allow id Apache-2.0 Library A pkg:lib/libraryA@1.0.0 components -allow id Apache-2.0 Library F pkg:lib/libraryF@1.0.0 components -allow expression Apache-2.0 AND (MIT OR BSD-2-Clause) Library B pkg:lib/libraryB@1.0.0 components -allow name BSD Library J pkg:lib/libraryJ@1.0.0 components -deny name CC-BY-NC Library G pkg:lib/libraryG@1.0.0 components -needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components -needs-review id GPL-2.0-only Library C pkg:lib/libraryC@1.0.0 components -needs-review id GPL-3.0-only Library D pkg:lib/libraryD@1.0.0 components -allow id MIT ACME Application pkg:app/sample@1.0.0 metadata.component -allow id MIT Library A pkg:lib/libraryA@1.0.0 components -UNDEFINED invalid NOASSERTION Library NoLicense pkg:lib/libraryNoLicense@1.0.0 components -UNDEFINED invalid NOASSERTION Bar service:example.com/myservices/bar services -needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component + "type": "unique", + "field": "components", + "context": "(root).components", + "description": "array items[2,4] must be unique", + "value": { + "type": "array", + "index": 2, + "item": { + "bom-ref": "pkg:npm/body-parser@1.19.0", + "description": "Node.js body parsing middleware", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "licenses": [ + { + "license": { + "id": "MIT" + } + } + ], + "name": "body-parser", + "purl": "pkg:npm/body-parser@1.19.0", + "type": "library", + "version": "1.19.0" + } + } + } +] ``` -- **Notes** - - **Usage policy** column values are derived from the `license.json` policy configuration file. - - A `usage policy` value of `UNDEFINED` indicates that `license.json` provided no entry that matched the declared license (`id` or `name`) in the SBOM. - - **License expressions** (e.g., `(MIT or GPL-2.0)`) with one term resolving to `UNDEFINED` and the the other term having a concrete policy will resolve to the "optimistic" policy for `OR` expressions and the "pessimistic" policy for `AND` expressions. In addition, a warning of this resolution is emitted. - -###### Example: license list summary with `--where` filter - -The list command results can be filtered using the `--where` flag using the column names in the report. These include `usage-policy`, `license-type`, `license`, `resource-name`, `bom-ref` and `bom-location`. - -The following example shows filtering of component licenses using the `license-type` column where the license was described as a `name` value: - -```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where license-type=name -q -``` +##### Reducing output size using `error-value=false` flag -```bash -usage-policy license-type license resource-name bom-ref bom-location ------------- ------------ ------- ------------- ------- ------------ -needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components -allow name Apache Library B pkg:lib/libraryB@1.0.0 components -allow name BSD Library J pkg:lib/libraryJ@1.0.0 components -deny name CC-BY-NC Library G pkg:lib/libraryG@1.0.0 components -needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components -needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component -``` +In many cases, BOMs may have many errors and having the `value` information details included can be too verbose and lead to large output files to inspect. In those cases, simply set the `error-value` flag to `false`. -In another example, the list is filtered by the `usage-policy` where the value is `needs-review`: +Rerunning the same command with this flag set to false yields a reduced set of information. ```bash -./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where usage-policy=needs-review -q +./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --error-value=false -q ``` -```bash -usage-policy license-type license resource-name bom-ref bom-location ------------- ------------ ------- ------------- ------- ------------ -needs-review id ADSL Foo service:example.com/myservices/foo services -needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components -needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components -needs-review id GPL-2.0-only Library C pkg:lib/libraryC@1.0.0 components -needs-review id GPL-3.0-only Library D pkg:lib/libraryD@1.0.0 components -needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component +```json +[ + { + "type": "unique", + "field": "components", + "context": "(root).components", + "description": "array items[1,2] must be unique" + }, + { + "type": "unique", + "field": "components", + "context": "(root).components", + "description": "array items[2,4] must be unique" + } +] ``` --- -### License `policy` subcommand - -To view a report listing the contents of the current policy file (i.e., [`license.json`](https://github.com/CycloneDX/sbom-utility/blob/main/license.json)) which contains an encoding of known software and data licenses by SPDX ID and license family along with a configurable usage policy (i.e., `"allow"`, `"deny"` or `"needs-review"`). - -#### License policy supported formats +### Trim -This command supports the `--format` flag with any of the following values: +This command is able to "trim" one or more JSON keys (fields) from specified JSON BOM documents effectively "pruning" the JSON document. This functionality helps consumers of large-sized BOMs that need to analyze specific types of data in large BOMs in reducing the BOM data to just what is needed for their use cases or needs. -- `txt` (default), `csv`, `md` +#### Trim supported output formats -#### License policy result sorting +This command is used to output, using the [`--output-file` flag](#output-flag), a "trimmed" BOM in JSON format. -- Results are sorted by license policy `family`. +- `json` (default) -#### License policy flags +#### Trim flags -##### list `--summary` flag +Trim operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) and produces a trimmed JSON BOM output file using the following flags: -Use the `--summary` flag on the `license policy list` command to produce a summary report with a reduced set of column data (i.e., it includes only the following columns: `usage-policy`, `family`, `id`, `name`, `oci` (approved) `fsf` (approved), `deprecated`, and SPDX `reference` URL). +##### Trim `--keys` flag -##### list `--wrap` flag +A comma-separated list of JSON map keys. Similar to the [query command's `--select` flag](#query---select-flag) syntax. -Use the `--wrap` flag to toggle the wrapping of text within columns of the license policy report (`txt` format only) output using the values `true` or `false`. The default value is `false`. +##### Trim `--from` flag -#### License policy examples +A comma-separated list of JSON document paths using the same syntax as the [query command's `--from` flag](#query---from-flag). -##### Example: license policy +##### Trim `--normalize` flag -```bash -./sbom-utility license policy -q -``` +A flag that normalizes the BOM data after trimming and prior to output. -```bash -usage-policy family id name osi fsf deprecated reference aliases annotations notes ------------- ------ -- ---- --- --- ---------- --------- ------- ----------- ----- -allow 0BSD 0BSD BSD Zero Clause License true false false https://spdx.org/licenses/0BSD.html Free Public License 1.0.0 APPROVED none -needs-review ADSL ADSL Amazon Digital Services License false false false https://spdx.org/licenses/ADSL.html none NEEDS-APPROVAL none -allow AFL AFL-3.0 Academic Free License v3.0 true true false https://spdx.org/licenses/AFL-3.0.html none APPROVED none -needs-review AGPL AGPL-1.0 Affero General Public License v1.0 false false true https://spdx.org/licenses/AGPL-1.0.html none NEEDS-APPROVAL,AGPL-WARNING none -allow Adobe Adobe-2006 Adobe Systems Incorporated CLA false false false https://spdx.org/licenses/Adobe-2006.html none APPROVED none -allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html Apache License, Version 2.0 APPROVED none -allow Artistic Artistic-1.0 Artistic License 1.0 true false false https://spdx.org/licenses/Artistic-1.0.html none APPROVED none -... -``` +This flag has custom code that sorts all components, services, licenses, vulnerabilities, properties, external references, hashes and *most* other BOM data using custom comparators. -###### Example: policy with `--summary` flag +Each comparator uses `required` fields and other identifying fields to create *"composite keys"* for each unique data structure. -We can also apply the `--summary` flag to get a reduced set of columns that includes only the `usage-policy` along with the essential SPDX license information (e.g., no annotations or notes). +#### Trim examples -```bash -./sbom-utility license policy --summary -q -``` +The original BOM used for these examples can be found here: -```bash -usage-policy family id name osi fsf deprecated reference ------------- ------ -- ---- --- --- ---------- --------- -allow 0BSD 0BSD BSD Zero Clause License true false false https://spdx.org/licenses/0BSD.html -needs-review ADSL ADSL Amazon Digital Services License false false false https://spdx.org/licenses/ADSL.html -allow AFL AFL-3.0 Academic Free License v3.0 true true false https://spdx.org/licenses/AFL-3.0.html -needs-review AGPL AGPL-1.0 Affero General Public License v1.0 false false true https://spdx.org/licenses/AGPL-1.0.html -allow Adobe Adobe-2006 Adobe Systems Incorporated CLA false false false https://spdx.org/licenses/Adobe-2006.html -allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html -allow Artistic Artistic-1.0 Artistic License 1.0 true true false https://spdx.org/licenses/Artistic-2.0.html -... -``` +- [test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json](test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json) -###### Example: policy with `--where` filter +##### Example: Trim `properties` from entire JSON BOM -The following example shows filtering of license policies using the `id` column: +Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository. ```bash -./sbom-utility license policy --where id=Apache +./sbom-utility trim -i ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties ``` -```bash -usage-policy family id name osi fsf deprecated reference aliases annotations notes ------------- ------ -- ---- --- --- ---------- --------- ------- ----------- ----- -allow Apache Apache-1.0 Apache v1.0 false true false https://spdx.org/licenses/Apache-1.0.html none APPROVED none -allow Apache Apache-1.1 Apache v1.1 true true false https://spdx.org/licenses/Apache-1.1.html none APPROVED Superseded by Apache-2.0 -allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html Apache License APPROVED none +Original BOM with `properties`: +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/sample@2.0.0", + "purl": "pkg:npm/sample@2.0.0", + "name": "sample", + "version": "2.0.0", + "description": "Node.js Sampler package", + "properties": [ + { + "name": "foo", + "value": "bar" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/body-parser@1.19.0", + "purl": "pkg:npm/body-parser@1.19.0", + "name": "body-parser", + "version": "1.19.0", + "description": "Node.js body parsing middleware", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ] + } + ], + "properties": [ + { + "name": "abc", + "value": "123" + } + ] +} ``` -###### Example: policy with `--wrap` flag - -```bash -./sbom-utility license policy --wrap=true -q -``` - -```bash -usage-policy family id name osi fsf deprecated reference aliases annotations notes ------------- ------ -- ---- --- --- ---------- --------- ------- ----------- ----- -allow 0BSD 0BSD BSD Zero Clause Lice (20/23) true false false https://spdx.org/licenses/0BSD.html Free Public License 1.0. (24/25) APPROVED none -needs-review ADSL ADSL Amazon Digital Servi (20/31) false false false https://spdx.org/licenses/ADSL.html NEEDS-APPROVAL none -allow AFL AFL-3.0 Academic Free Licens (20/26) true true false https://spdx.org/licenses/AFL-3.0.ht (36/38) APPROVED none -needs-review AGPL AGPL-1.0 Affero General Publi (20/34) false false true https://spdx.org/licenses/AGPL-1.0.h (36/39) NEEDS-APPROVAL none - AGPL-WARNING -needs-review APSL APSL-2.0 Apple Public Source (20/31) true true false https://spdx.org/licenses/APSL-2.0.h (36/39) NEEDS-APPROVAL none -allow Adobe Adobe-2006 Adobe Systems Incorp (20/56) false false false https://spdx.org/licenses/Adobe-2006 (36/41) APPROVED none -allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0 (36/41) Apache License, Version (24/27) APPROVED none -allow Artistic Artistic-2.0 Artistic License 2.0 true true false https://spdx.org/licenses/Artistic-2 (36/43) APPROVED none -... -``` - -#### License policy notes - -- Currently, the default `license.json` file, used to derive the `usage-policy` data, does not contain entries for the entire set of SPDX 3.2 license templates. - - An issue [12](https://github.com/CycloneDX/sbom-utility/issues/12) is open to add parity. -- Annotations (tags) and notes can be defined within the `license.json` file and one or more assigned each license entry. - -- For backwards compatibility, the `--where` filter supports the key `spdx-id` as an alias for `id`. - ---- - -### Patch - -This *experimental* command is able to "patch" an existing JSON BOM document using an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1) *"JavaScript Object Notation (JSON) Patch"* file. - -The current implementation supports the following "patch" operations: - -- "add", "update", "remove" and "test" - -At this time the "move" or "copy" operations are not supported. - -Patches work for both simple (i.e., integer, float, boolean and string) values as well as complex values such as JSON objects, maps and arrays. - -#### Patch supported output formats - -This command is used to output, using the [`--output-file` flag](#output-flag), a "patched" BOM in JSON format. - -- `json` (default) - -#### Patch flags - -The patch command operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) as well as an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1)-formatted "patch' file and produces a "patched" version of the input JSON BOM as output using the following flags: - -##### Patch `--patch-filename` flag - -The `--patch-file ` flag is used to provide the relative path to the IETF RFC6902 patch file to applied to the BOM input file. - -#### Patch examples - -This section contains examples of all supported patch operations (i.e., add, replace, test) including values that are primitives (i.e., `numbers`, `strings`) as well as JSON `objects` and may be indexed JSON `array` elements. - -- ["add" BOM `serialNumber`](#patch-example-1-add-bom-serialnumber) -- ["add" (update) BOM `version`](#patch-example-2-add-update-bom-version) -- ["add" `supplier` object to `metadata`](#patch-example-3-add-supplier-object-to-metadata-object) -- ["add" `property` objects to `metadata.properties` array](#patch-example-4-add-property-objects-to-metadataproperties-array) -- ["replace" `version` and `timestamp` values](#patch-example-5-replace-bom-version-and-timestamp) -- ["remove" `property` from the `metadata.properties` array](#patch-example-6-remove-property-from-the-metadataproperties-array) -- ["test" if a `property` exists in the `metadata.properties` array](#patch-example-7-test-property-exists-in-the-metadataproperties-array) - -##### Patch example 1: "add" BOM `serialNumber` - -This example adds a new top-level key `"serialNumber"` and corresponding value to a CycloneDX JSON BOM file. - -The original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) has no serial number: +Output BOM results without `properties`: ```json { - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "metadata": { - ... - } + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", + "version": 1, + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/sample@2.0.0", + "name": "sample", + "version": "2.0.0", + "description": "Node.js Sampler package", + "purl": "pkg:npm/sample@2.0.0" + }, + { + "type": "library", + "bom-ref": "pkg:npm/body-parser@1.19.0", + "name": "body-parser", + "version": "1.19.0", + "description": "Node.js body parsing middleware", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "purl": "pkg:npm/body-parser@1.19.0" + } + ] } ``` -IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json): - -```json -[ - { "op": "add", "path": "/serialNumber", "value": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9" } -] -``` - -Invoke the patch command as follows: +##### Example: Trim `name` and `description` from entire JSON BOM ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-serial-number.json -q +./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=name,description -q ``` -Patched JSON BOM output file: +Output BOM results without `name` or `description`: ```json { @@ -712,123 +735,307 @@ Patched JSON BOM output file: "specVersion": "1.5", "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", "version": 1, - "metadata": { - ... - } -} -``` - -##### Patch example 2: "add" (update) BOM `version` - -This example shows how the patch's "add" operation can be used to update existing values which is the specified behavior of RFC6902. - -Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) with `version` equal to `1`: - -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "metadata": { - ... - } + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/sample@2.0.0", + "version": "2.0.0", + "purl": "pkg:npm/sample@2.0.0", + "properties": [ + { + "value": "bar" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/body-parser@1.19.0", + "version": "1.19.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "purl": "pkg:npm/body-parser@1.19.0" + } + ], + "properties": [ + { + "value": "123" + } + ] } ``` -IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json): - -```json -[ - { "op": "add", "path": "/version", "value": 2 } -] -``` - -Invoke the patch command as follows: +##### Example: Trim `properties` from only `components` path ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-update-version.json -q +./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties --from components -q ``` -The patched, output JSON BOM file which has the changed `version` value of `2`: +Output BOM results with `properties` removed from all `components`: ```json { "bomFormat": "CycloneDX", "specVersion": "1.5", - "version": 2, - "metadata": { - ... - } -} -``` - -##### Patch example 3: "add" `supplier` object to `metadata` object - -This example shows how the patch's "add" operation can be used to add a JSON object to an existing object. - -Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): - -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "metadata": { - "timestamp": "2023-10-12T19:07:00Z", + "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", + "version": 1, + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/sample@2.0.0", + "name": "sample", + "version": "2.0.0", + "description": "Node.js Sampler package", + "purl": "pkg:npm/sample@2.0.0" + }, + { + "type": "library", + "bom-ref": "pkg:npm/body-parser@1.19.0", + "name": "body-parser", + "version": "1.19.0", + "description": "Node.js body parsing middleware", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "purl": "pkg:npm/body-parser@1.19.0" + } + ], "properties": [ - ... + { + "name": "abc", + "value": "123" + } ] - } } ``` -Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-supplier.json](test/patch/cdx-patch-example-add-metadata-supplier.json): - -```json -[ - { "op": "add", "path": "/metadata/supplier", "value": { - "name": "Example Co. Distribution Dept.", - "url": [ - "https://example.com/software/" - ] - } - } -] -``` +--- -Invoke the patch command as follows: +##### Example: Trim `bom-ref` and normalize output ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-supplier.json -q +./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-components-normalize.sbom.json --keys="bom-ref" --normalize -q ``` -The patched BOM has the `supplier` object added to the `metadata`: +**Note** If you do not want to remove any keys and simply normalize output, set keys to an empty string: `--keys=""`. + +Use the trim command to remove all `bom-ref` fields and normalize output: ```json { - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "metadata": { - "timestamp": "2023-10-12T19:07:00Z", - "supplier": { - "name": "Example Co. Distribution Dept.", - "url": [ - "https://example.com/software/" - ] - }, - "properties": [ - ... - ] + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "components": [ + { + "type": "library", + "bom-ref": "pkg:npm/sample@2.0.0", + "purl": "pkg:npm/sample@2.0.0", + "name": "sample", + "version": "2.0.0", + "licenses": [ + { + "license": { + "id": "GPL-2.0-or-later" + } + }, + { + "license": { + "id": "LGPL-2.0-or-later" + } + }, + { + "license": { + "id": "GPL-2.0-only" + } + } + ], + "properties": [ + { + "name": "moo", + "value": "cow" + }, + { + "name": "foo", + "value": "bar" + } + ] + }, + { + "type": "library", + "bom-ref": "pkg:npm/body-parser@1.19.0", + "purl": "pkg:npm/body-parser@1.19.0", + "name": "body-parser", + "version": "1.19.0", + "hashes": [ + { + "alg": "SHA-256", + "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" + }, + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + } + ], + "licenses": [ + { + "license": { + "id": "MIT" + } + }, + { + "license": { + "id": "Apache-2.0" + } + } + ], + "externalReferences": [ + { + "type": "website", + "url": "https://example.com/website" + }, + { + "type": "support", + "url": "https://example.com/support" + } + ] } + ] } ``` -##### Patch example 4: "add" `property` objects to `metadata.properties` array +Trimmed, normalized output: -This example shows how the patch's "add" operation can be used to add `property` objects to an existing `properties` array. +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "components": [ + { + "type": "library", + "name": "body-parser", + "version": "1.19.0", + "hashes": [ + { + "alg": "SHA-1", + "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + }, + { + "alg": "SHA-256", + "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" + } + ], + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + }, + { + "license": { + "id": "MIT" + } + } + ], + "purl": "pkg:npm/body-parser@1.19.0", + "externalReferences": [ + { + "type": "support", + "url": "https://example.com/support" + }, + { + "type": "website", + "url": "https://example.com/website" + } + ] + }, + { + "type": "library", + "name": "sample", + "version": "2.0.0", + "licenses": [ + { + "license": { + "id": "GPL-2.0-only" + } + }, + { + "license": { + "id": "GPL-2.0-or-later" + } + }, + { + "license": { + "id": "LGPL-2.0-or-later" + } + } + ], + "purl": "pkg:npm/sample@2.0.0", + "properties": [ + { + "name": "foo", + "value": "bar" + }, + { + "name": "moo", + "value": "cow" + } + ] + } + ] +} +``` -Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): +--- + +### Patch + +This *experimental* command is able to "patch" an existing JSON BOM document using an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1) *"JavaScript Object Notation (JSON) Patch"* file. + +The current implementation supports the following "patch" operations: + +- "add", "update", "remove" and "test" + +At this time the "move" or "copy" operations are not supported. + +Patches work for both simple (i.e., integer, float, boolean and string) values as well as complex values such as JSON objects, maps and arrays. + +#### Patch supported output formats + +This command is used to output, using the [`--output-file` flag](#output-flag), a "patched" BOM in JSON format. + +- `json` (default) + +#### Patch flags + +The patch command operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) as well as an [IETF RFC6902](https://datatracker.ietf.org/doc/html/rfc6902/#section-4.1)-formatted "patch' file and produces a "patched" version of the input JSON BOM as output using the following flags: + +##### Patch `--patch-filename` flag + +The `--patch-file ` flag is used to provide the relative path to the IETF RFC6902 patch file to applied to the BOM input file. + +#### Patch examples + +This section contains examples of all supported patch operations (i.e., add, replace, test) including values that are primitives (i.e., `numbers`, `strings`) as well as JSON `objects` and may be indexed JSON `array` elements. + +- ["add" BOM `serialNumber`](#patch-example-1-add-bom-serialnumber) +- ["add" (update) BOM `version`](#patch-example-2-add-update-bom-version) +- ["add" `supplier` object to `metadata`](#patch-example-3-add-supplier-object-to-metadata-object) +- ["add" `property` objects to `metadata.properties` array](#patch-example-4-add-property-objects-to-metadataproperties-array) +- ["replace" `version` and `timestamp` values](#patch-example-5-replace-bom-version-and-timestamp) +- ["remove" `property` from the `metadata.properties` array](#patch-example-6-remove-property-from-the-metadataproperties-array) +- ["test" if a `property` exists in the `metadata.properties` array](#patch-example-7-test-property-exists-in-the-metadataproperties-array) + +##### Patch example 1: "add" BOM `serialNumber` + +This example adds a new top-level key `"serialNumber"` and corresponding value to a CycloneDX JSON BOM file. + +The original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) has no serial number: ```json { @@ -836,74 +1043,44 @@ Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/p "specVersion": "1.5", "version": 1, "metadata": { - "timestamp": "2023-10-12T19:07:00Z", - "properties": [ - { - "name": "Property 1", - "value": "Value 1" - }, - { - "name": "Property 2", - "value": "Value 2" - } - ] + ... } } ``` -Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-properties.json](test/patch/cdx-patch-example-add-metadata-properties.json): +IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json): ```json [ - { "op": "add", "path": "/metadata/properties/-", "value": { "name": "foo", "value": "bar" } }, - { "op": "add", "path": "/metadata/properties/1", "value": { "name": "rush", "value": "yyz" } } + { "op": "add", "path": "/serialNumber", "value": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9" } ] ``` -Note that the first patch record uses the `-` (dash) to indicate "insert at end" whereas the second patch record has the zero-based array index `1`. - Invoke the patch command as follows: ```bash -./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-properties.json -q +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-serial-number.json -q ``` -The patched, output BOM has the two new properties at the specified indices: +Patched JSON BOM output file: ```json { "bomFormat": "CycloneDX", "specVersion": "1.5", + "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", "version": 1, "metadata": { - "timestamp": "2023-10-12T19:07:00Z", - "properties": [ - { - "name": "Property 1", - "value": "Value 1" - }, - { - "name": "rush", - "value": "yyz" - }, - { - "name": "Property 2", - "value": "Value 2" - }, - { - "name": "foo", - "value": "bar" - } - ] + ... } } ``` -##### Patch example 5: "replace" BOM `version` and `timestamp` +##### Patch example 2: "add" (update) BOM `version` -This example shows how the patch's "replace" operation can be used to update the BOM document's `version` and `timestamp` values. +This example shows how the patch's "add" operation can be used to update existing values which is the specified behavior of RFC6902. -Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): +Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json) with `version` equal to `1`: ```json { @@ -911,8 +1088,189 @@ Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/p "specVersion": "1.5", "version": 1, "metadata": { - "timestamp": "2023-10-12T19:07:00Z", - "properties": [ + ... + } +} +``` + +IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-serial-number.json](test/patch/cdx-patch-example-add-serial-number.json): + +```json +[ + { "op": "add", "path": "/version", "value": 2 } +] +``` + +Invoke the patch command as follows: + +```bash +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-update-version.json -q +``` + +The patched, output JSON BOM file which has the changed `version` value of `2`: + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 2, + "metadata": { + ... + } +} +``` + +##### Patch example 3: "add" `supplier` object to `metadata` object + +This example shows how the patch's "add" operation can be used to add a JSON object to an existing object. + +Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "timestamp": "2023-10-12T19:07:00Z", + "properties": [ + ... + ] + } +} +``` + +Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-supplier.json](test/patch/cdx-patch-example-add-metadata-supplier.json): + +```json +[ + { "op": "add", "path": "/metadata/supplier", "value": { + "name": "Example Co. Distribution Dept.", + "url": [ + "https://example.com/software/" + ] + } + } +] +``` + +Invoke the patch command as follows: + +```bash +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-supplier.json -q +``` + +The patched BOM has the `supplier` object added to the `metadata`: + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "timestamp": "2023-10-12T19:07:00Z", + "supplier": { + "name": "Example Co. Distribution Dept.", + "url": [ + "https://example.com/software/" + ] + }, + "properties": [ + ... + ] + } +} +``` + +##### Patch example 4: "add" `property` objects to `metadata.properties` array + +This example shows how the patch's "add" operation can be used to add `property` objects to an existing `properties` array. + +Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "timestamp": "2023-10-12T19:07:00Z", + "properties": [ + { + "name": "Property 1", + "value": "Value 1" + }, + { + "name": "Property 2", + "value": "Value 2" + } + ] + } +} +``` + +Apply the following IETF RFC6902 JSON Patch file: [test/patch/cdx-patch-example-add-metadata-properties.json](test/patch/cdx-patch-example-add-metadata-properties.json): + +```json +[ + { "op": "add", "path": "/metadata/properties/-", "value": { "name": "foo", "value": "bar" } }, + { "op": "add", "path": "/metadata/properties/1", "value": { "name": "rush", "value": "yyz" } } +] +``` + +Note that the first patch record uses the `-` (dash) to indicate "insert at end" whereas the second patch record has the zero-based array index `1`. + +Invoke the patch command as follows: + +```bash +./sbom-utility patch --input-file test/patch/cdx-1-5-simplest-base.json --patch-file test/patch/cdx-patch-example-add-metadata-properties.json -q +``` + +The patched, output BOM has the two new properties at the specified indices: + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "timestamp": "2023-10-12T19:07:00Z", + "properties": [ + { + "name": "Property 1", + "value": "Value 1" + }, + { + "name": "rush", + "value": "yyz" + }, + { + "name": "Property 2", + "value": "Value 2" + }, + { + "name": "foo", + "value": "bar" + } + ] + } +} +``` + +##### Patch example 5: "replace" BOM `version` and `timestamp` + +This example shows how the patch's "replace" operation can be used to update the BOM document's `version` and `timestamp` values. + +Original CycloneDX JSON BOM file: [test/patch/cdx-1-5-simplest-base.json](test/patch/cdx-1-5-simplest-base.json): + +```json +{ + "bomFormat": "CycloneDX", + "specVersion": "1.5", + "version": 1, + "metadata": { + "timestamp": "2023-10-12T19:07:00Z", + "properties": [ ... ] } @@ -1291,819 +1649,461 @@ additionally, you can apply a `--select` clause to simply obtain the matching en --- -### Resource - -The `resource` command is geared toward inspecting various resources types and their information from SBOMs against future maturity models being developed as part of the [OWASP Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/). In the SCVS model, a "resource" is the parent classification for software (components), services, Machine Learning (ML) models, data, hardware, tools and more. +### Component -Primarily, the command is used to generate lists of resources, by type, that are included in a CycloneDX SBOM by invoking `resource list`. +Primarily, this command is used to extract, filter and list CycloneDX BOM component data using `component list`. -#### Resource supported output formats +#### Component list supported formats This command supports the `--format` flag with any of the following values: - `txt` (default), `csv`, `md` -#### Resource result sorting +#### Component list flags -Currently, all `resource list` command results are sorted by resource `type` then by resource `name` (required field). +##### Component list `--summary` flag -#### Resource Examples +Use the `--summary` flag on the `component list` command to produce a summary report with reduced column information. -#### Example: resource list +#### Component list examples -```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json -q -``` +##### Example: `component list` + +This example shows the component list with all column information display. Since CycloneDX component data can be very extensive, many columns simply indicate the component `has` more data available which can be extracted using the `query` command if needed. ```bash -resource-type group name version description bom-ref -------------- ----- ---- ------- ----------- ------- -component ACME Application 2.0.0 ACME sample application pkg:app/sample@1.0.0 -component Library A 1.0.0 Library A description pkg:lib/libraryA@1.0.0 -component Library C 1.0.0 Library C description. pkg:lib/libraryC@1.0.0 -component Library F 1.0.0 Library F description. pkg:lib/libraryF@1.0.0 -component Library G 1.0.0 Library G description. pkg:lib/libraryG@1.0.0 -component Library H 1.0.0 Library H description. pkg:lib/libraryH@1.0.0 -component Library NoLicense 1.0.0 Library "NoLicense" description. pkg:lib/libraryNoLicense@1.0.0 -component blue Library B 1.0.0 Library B description. pkg:lib/libraryB@1.0.0 -component blue Library E 1.0.0 Library E description. pkg:lib/libraryE@1.0.0 -component green Library D 1.0.0 Library D description. pkg:lib/libraryD@1.0.0 -component green Library J 1.0.0 Library J description. pkg:lib/libraryJ@1.0.0 -service Bar Bar service service:example.com/myservices/bar -service Foo Foo service service:example.com/myservices/foo +./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json -q +``` +```text +bom-ref group type name version description copyright supplier-name supplier-url manufacturer-name manufacturer-url publisher purl swid-tag-id cpe mime-type scope number-hashes number-licenses has-pedigree has-evidence has-components has-release-notes has-model-card has-data has-tags has-signature +------- ----- ---- ---- ------- ----------- --------- ------------- ------------ ----------------- ---------------- --------- ---- ----------- --- --------- ----- ------------- --------------- ------------ ------------ -------------- ----------------- -------------- -------- -------- ------------- + application Acme Application 9.1.1 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1 0 0 false false false false false false false false +pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 pkg:npm/acme/component@1.0.0 4 1 true false false false false false false false + org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org required 0 0 true false false false false false false false ``` -##### Example: resource list using `--type service` +##### Example: `component list` summary only -This example uses the `type` flag to specific `service`. The other valid type is `component`. Future versions of CycloneDX schema will include more resource types such as "ml" (machine learning) or "tool". +The same BOM component information as in the previous example; however, using the summary flag to reduce the number of columns data. ```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --type service -q +./sbom-utility component list -i test/cyclonedx/1.6/specification/valid-bom-1.6.json --summary -q ``` -```bash -resource-type group name version description bom-ref -------------- ----- ---- ------- ----------- ------- -service Bar Bar service service:example.com/myservices/bar -service Foo Foo service service:example.com/myservices/foo +```text +bom-ref group type name version description copyright supplier-name supplier-url manufacturer-name manufacturer-url publisher purl swid-tag-id cpe number-hashes number-licenses +------- ----- ---- ---- ------- ----------- --------- ------------- ------------ ----------------- ---------------- --------- ---- ----------- --- ------------- --------------- + application Acme Application 9.1.1 swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1 0 0 +pkg:npm/acme/component@1.0.0 com.acme library tomcat-catalina 9.0.14 pkg:npm/acme/component@1.0.0 4 1 + org.example library mylibrary 1.0.0 Example, Inc. https://example.com Example-2, Inc. https://example.org 0 0 ``` -**Note** The results would be equivalent to using the `--where` filter: - -```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "resource-type=service" -q -``` +--- -##### Example: list with `name` regex match +### License -This example uses the `where` filter on the `name` field. In this case we supply an exact "startswith" regex. for the `name` filter. +This command is used to aggregate and summarize software, hardware and data license information included in the SBOM. It also displays license usage policies for resources based upon concluded by SPDX license identifier, license family or logical license expressions as defined in he current policy file (i.e., `license.json`). -```bash -./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "name=Library A" -q -``` +The `license` command supports the following subcommands: -```bash -resource-type group name version description bom-ref -------------- ----- ---- ------- ----------- ------- -component Library A 1.0.0 Library A description pkg:lib/libraryA@1.0.0 -``` +- [list](#license-list-subcommand) - list or create a summarized report of licenses found in input SBOM. + - [list with --summary flag](#license-list---summary-flag) - As full license information can be very large, a summary view is often most useful. +- [policy](#license-policy-subcommand) - list user configured license policies by SPDX license ID, family name and other filters. --- -### Schema - -You can verify which formats, schemas, versions and variants are available for validation by using the `schema` command. +### License `list` subcommand -- **Note**: The `schema` command will default to the `list` subcommand if omitted. +The `list` subcommand produces JSON output which contains an array of CycloneDX `LicenseChoice` data objects found in the BOM input file without component association. `LicenseChoice` data, in general, may provide license information using registered SPDX IDs, license expressions (of SPDX IDs) or license names (not necessarily registered by SPDX). License data may also include base64-encoded license or legal text that was used to determine a license's SPDX ID or name. -#### Schema supported output formats +#### License list supported formats This command supports the `--format` flag with any of the following values: -- `txt` (default), `csv`, `md` +- `json` (default), `csv`, `md` + - using the `--summary` flag: `txt` (default), `csv`, `md` -#### Schema result sorting +#### License list result sorting -- Formatted results are sorted by `format` (ascending), `version` (descending) and `schema` (descending) +- Results are not sorted for base `license list` subcommand. + - using the `--summary` flag: results are sorted (ascending) by license key which can be one of license `id` (SPDX ID), `name` or `expression`. -#### Schema examples +#### License list flags -##### Example: schema list +##### License list `--summary` flag + +Use the `--summary` flag on the `license list` command to produce a summary report in `txt` (default) format as well as policy determination based upon the `license.json` declarations. + +#### License list examples + +##### Example: license list JSON + +This example shows a few entries of the JSON output that exhibit the three types of license data described above: ```bash -./sbom-utility schema list -q +./sbom-utility license list -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json --format json -q ``` -```bash -name variant format version file url ----- ------- ------ ------- ---- --- -CycloneDX v1.6 development CycloneDX 1.6 schema/cyclonedx/1.6/bom-1.6.schema.json https://raw.githubusercontent.com/CycloneDX/specification/1.6-dev/schema/bom-1.6.schema.json -CycloneDX v1.5 (latest) CycloneDX 1.5 schema/cyclonedx/1.5/bom-1.5.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.5.schema.json -CycloneDX v1.4 (latest) CycloneDX 1.4 schema/cyclonedx/1.4/bom-1.4.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json -CycloneDX v1.4 custom CycloneDX 1.4 schema/test/bom-1.4-custom.schema.json -CycloneDX v1.3 (latest) CycloneDX 1.3 schema/cyclonedx/1.3/bom-1.3.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json -CycloneDX v1.3 custom CycloneDX 1.3 schema/test/bom-1.3-custom.schema.json -CycloneDX v1.3 strict CycloneDX 1.3 schema/cyclonedx/1.3/bom-1.3-strict.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3-strict.schema.json -CycloneDX v1.2 (latest) CycloneDX 1.2 schema/cyclonedx/1.2/bom-1.2.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json -CycloneDX v1.2 strict CycloneDX 1.2 schema/cyclonedx/1.2/bom-1.2-strict.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2-strict.schema.json -SPDX v2.3 (latest) SPDX SPDX-2.3 schema/spdx/2.3/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json -SPDX v2.3.1 development SPDX SPDX-2.3 schema/spdx/2.3.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json -SPDX v2.2.2 (latest) SPDX SPDX-2.2 schema/spdx/2.2.2/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json -SPDX v2.2.1 2.2.1 SPDX SPDX-2.2 schema/spdx/2.2.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json +```json +[ + { + "license": { + "$comment": "by license `id", + "id": "MIT", + "name": "", + "url": "" + } + }, + { + "license": { + "$comment": "by license `expression", + "id": "", + "name": "", + "url": "" + }, + "expression": "Apache-2.0 AND (MIT OR GPL-2.0-only)" + }, + { + "license": { + "$comment": "by license `name` with full license encoding", + "id": "", + "name": "Apache 2", + "text": { + "contentType": "text/plain", + "encoding": "base64", + "content": "CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFwYWNoZSBMaWNlbnNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFZlcnNpb24 ..." + }, + "url": "https://www.apache.org/licenses/LICENSE-2.0.txt" + } + }, + ... +] ``` -#### Adding schemas +###### Example: license list `--summary` -Entries for new or "custom" schemas can be added to the `config.json` file by adding a new schema entry and then will need to pass that file on the command line using the `--config-schema` flag. +This example shows the default text output from using the summary flag: -These new schema entries will tell the schema loader where to find the JSON schema file locally, relative to the utility's executable. +```bash +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary -q +``` -For details see the "[Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants)" section. +```bash +usage-policy license-type license resource-name bom-ref bom-location +------------ ------------ ------- ------------- ------- ------------ +needs-review id ADSL Foo service:example.com/myservices/foo services +needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components +allow name Apache Library B pkg:lib/libraryB@1.0.0 components +allow id Apache-1.0 Library E pkg:lib/libraryE@1.0.0 components +allow id Apache-2.0 N/A N/A metadata.licenses +allow id Apache-2.0 Library A pkg:lib/libraryA@1.0.0 components +allow id Apache-2.0 Library F pkg:lib/libraryF@1.0.0 components +allow expression Apache-2.0 AND (MIT OR BSD-2-Clause) Library B pkg:lib/libraryB@1.0.0 components +allow name BSD Library J pkg:lib/libraryJ@1.0.0 components +deny name CC-BY-NC Library G pkg:lib/libraryG@1.0.0 components +needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components +needs-review id GPL-2.0-only Library C pkg:lib/libraryC@1.0.0 components +needs-review id GPL-3.0-only Library D pkg:lib/libraryD@1.0.0 components +allow id MIT ACME Application pkg:app/sample@1.0.0 metadata.component +allow id MIT Library A pkg:lib/libraryA@1.0.0 components +UNDEFINED invalid NOASSERTION Library NoLicense pkg:lib/libraryNoLicense@1.0.0 components +UNDEFINED invalid NOASSERTION Bar service:example.com/myservices/bar services +needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component +``` -#### Embedding schemas +- **Notes** + - **Usage policy** column values are derived from the `license.json` policy configuration file. + - A `usage policy` value of `UNDEFINED` indicates that `license.json` provided no entry that matched the declared license (`id` or `name`) in the SBOM. + - **License expressions** (e.g., `(MIT or GPL-2.0)`) with one term resolving to `UNDEFINED` and the the other term having a concrete policy will resolve to the "optimistic" policy for `OR` expressions and the "pessimistic" policy for `AND` expressions. In addition, a warning of this resolution is emitted. -If you wish to have the new schema *embedded in the executable*, simply add it to the project's `resources` subdirectory following the format and version-based directory structure. +###### Example: license list summary with `--where` filter ---- +The list command results can be filtered using the `--where` flag using the column names in the report. These include `usage-policy`, `license-type`, `license`, `resource-name`, `bom-ref` and `bom-location`. -### Trim +The following example shows filtering of component licenses using the `license-type` column where the license was described as a `name` value: -This command is able to "trim" one or more JSON keys (fields) from specified JSON BOM documents effectively "pruning" the JSON document. This functionality helps consumers of large-sized BOMs that need to analyze specific types of data in large BOMs in reducing the BOM data to just what is needed for their use cases or needs. +```bash +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where license-type=name -q +``` -#### Trim supported output formats +```bash +usage-policy license-type license resource-name bom-ref bom-location +------------ ------------ ------- ------------- ------- ------------ +needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components +allow name Apache Library B pkg:lib/libraryB@1.0.0 components +allow name BSD Library J pkg:lib/libraryJ@1.0.0 components +deny name CC-BY-NC Library G pkg:lib/libraryG@1.0.0 components +needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components +needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component +``` -This command is used to output, using the [`--output-file` flag](#output-flag), a "trimmed" BOM in JSON format. +In another example, the list is filtered by the `usage-policy` where the value is `needs-review`: -- `json` (default) +```bash +./sbom-utility license list -i test/cyclonedx/cdx-1-3-license-list.json --summary --where usage-policy=needs-review -q +``` -#### Trim flags +```bash +usage-policy license-type license resource-name bom-ref bom-location +------------ ------------ ------- ------------- ------- ------------ +needs-review id ADSL Foo service:example.com/myservices/foo services +needs-review name AGPL Library J pkg:lib/libraryJ@1.0.0 components +needs-review name GPL Library H pkg:lib/libraryH@1.0.0 components +needs-review id GPL-2.0-only Library C pkg:lib/libraryC@1.0.0 components +needs-review id GPL-3.0-only Library D pkg:lib/libraryD@1.0.0 components +needs-review name UFL ACME Application pkg:app/sample@1.0.0 metadata.component +``` -Trim operates on a JSON BOM input file (see [`--input-file` flag](#input-flag)) and produces a trimmed JSON BOM output file using the following flags: +--- -##### Trim `--keys` flag +### License `policy` subcommand -A comma-separated list of JSON map keys. Similar to the [query command's `--select` flag](#query---select-flag) syntax. +To view a report listing the contents of the current policy file (i.e., [`license.json`](https://github.com/CycloneDX/sbom-utility/blob/main/license.json)) which contains an encoding of known software and data licenses by SPDX ID and license family along with a configurable usage policy (i.e., `"allow"`, `"deny"` or `"needs-review"`). -##### Trim `--from` flag +#### License policy supported formats -A comma-separated list of JSON document paths using the same syntax as the [query command's `--from` flag](#query---from-flag). +This command supports the `--format` flag with any of the following values: -##### Trim `--normalize` flag +- `txt` (default), `csv`, `md` -A flag that normalizes the BOM data after trimming and prior to output. +#### License policy result sorting -This flag has custom code that sorts all components, services, licenses, vulnerabilities, properties, external references, hashes and *most* other BOM data using custom comparators. +- Results are sorted by license policy `family`. -Each comparator uses `required` fields and other identifying fields to create *"composite keys"* for each unique data structure. +#### License policy flags -#### Trim examples +##### list `--summary` flag -The original BOM used for these examples can be found here: +Use the `--summary` flag on the `license policy list` command to produce a summary report with a reduced set of column data (i.e., it includes only the following columns: `usage-policy`, `family`, `id`, `name`, `oci` (approved) `fsf` (approved), `deprecated`, and SPDX `reference` URL). -- [test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json](test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json) +##### list `--wrap` flag -##### Example: Trim `properties` from entire JSON BOM +Use the `--wrap` flag to toggle the wrapping of text within columns of the license policy report (`txt` format only) output using the values `true` or `false`. The default value is `false`. -Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository. +#### License policy examples + +##### Example: license policy ```bash -./sbom-utility trim -i ./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties +./sbom-utility license policy -q ``` -Original BOM with `properties`: - -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "version": 1, - "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", - "components": [ - { - "type": "library", - "bom-ref": "pkg:npm/sample@2.0.0", - "purl": "pkg:npm/sample@2.0.0", - "name": "sample", - "version": "2.0.0", - "description": "Node.js Sampler package", - "properties": [ - { - "name": "foo", - "value": "bar" - } - ] - }, - { - "type": "library", - "bom-ref": "pkg:npm/body-parser@1.19.0", - "purl": "pkg:npm/body-parser@1.19.0", - "name": "body-parser", - "version": "1.19.0", - "description": "Node.js body parsing middleware", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ] - } - ], - "properties": [ - { - "name": "abc", - "value": "123" - } - ] -} +```bash +usage-policy family id name osi fsf deprecated reference aliases annotations notes +------------ ------ -- ---- --- --- ---------- --------- ------- ----------- ----- +allow 0BSD 0BSD BSD Zero Clause License true false false https://spdx.org/licenses/0BSD.html Free Public License 1.0.0 APPROVED none +needs-review ADSL ADSL Amazon Digital Services License false false false https://spdx.org/licenses/ADSL.html none NEEDS-APPROVAL none +allow AFL AFL-3.0 Academic Free License v3.0 true true false https://spdx.org/licenses/AFL-3.0.html none APPROVED none +needs-review AGPL AGPL-1.0 Affero General Public License v1.0 false false true https://spdx.org/licenses/AGPL-1.0.html none NEEDS-APPROVAL,AGPL-WARNING none +allow Adobe Adobe-2006 Adobe Systems Incorporated CLA false false false https://spdx.org/licenses/Adobe-2006.html none APPROVED none +allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html Apache License, Version 2.0 APPROVED none +allow Artistic Artistic-1.0 Artistic License 1.0 true false false https://spdx.org/licenses/Artistic-1.0.html none APPROVED none +... ``` -Output BOM results without `properties`: +###### Example: policy with `--summary` flag -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", - "version": 1, - "components": [ - { - "type": "library", - "bom-ref": "pkg:npm/sample@2.0.0", - "name": "sample", - "version": "2.0.0", - "description": "Node.js Sampler package", - "purl": "pkg:npm/sample@2.0.0" - }, - { - "type": "library", - "bom-ref": "pkg:npm/body-parser@1.19.0", - "name": "body-parser", - "version": "1.19.0", - "description": "Node.js body parsing middleware", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "purl": "pkg:npm/body-parser@1.19.0" - } - ] -} -``` - -##### Example: Trim `name` and `description` from entire JSON BOM +We can also apply the `--summary` flag to get a reduced set of columns that includes only the `usage-policy` along with the essential SPDX license information (e.g., no annotations or notes). ```bash -./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=name,description -q -``` - -Output BOM results without `name` or `description`: - -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", - "version": 1, - "components": [ - { - "type": "library", - "bom-ref": "pkg:npm/sample@2.0.0", - "version": "2.0.0", - "purl": "pkg:npm/sample@2.0.0", - "properties": [ - { - "value": "bar" - } - ] - }, - { - "type": "library", - "bom-ref": "pkg:npm/body-parser@1.19.0", - "version": "1.19.0", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "purl": "pkg:npm/body-parser@1.19.0" - } - ], - "properties": [ - { - "value": "123" - } - ] -} +./sbom-utility license policy --summary -q ``` -##### Example: Trim `properties` from only `components` path - ```bash -./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-small-components-only.sbom.json --keys=properties --from components -q -``` - -Output BOM results with `properties` removed from all `components`: - -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "serialNumber": "urn:uuid:1a2b3c4d-1234-abcd-9876-a3b4c5d6e7f9", - "version": 1, - "components": [ - { - "type": "library", - "bom-ref": "pkg:npm/sample@2.0.0", - "name": "sample", - "version": "2.0.0", - "description": "Node.js Sampler package", - "purl": "pkg:npm/sample@2.0.0" - }, - { - "type": "library", - "bom-ref": "pkg:npm/body-parser@1.19.0", - "name": "body-parser", - "version": "1.19.0", - "description": "Node.js body parsing middleware", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "purl": "pkg:npm/body-parser@1.19.0" - } - ], - "properties": [ - { - "name": "abc", - "value": "123" - } - ] -} +usage-policy family id name osi fsf deprecated reference +------------ ------ -- ---- --- --- ---------- --------- +allow 0BSD 0BSD BSD Zero Clause License true false false https://spdx.org/licenses/0BSD.html +needs-review ADSL ADSL Amazon Digital Services License false false false https://spdx.org/licenses/ADSL.html +allow AFL AFL-3.0 Academic Free License v3.0 true true false https://spdx.org/licenses/AFL-3.0.html +needs-review AGPL AGPL-1.0 Affero General Public License v1.0 false false true https://spdx.org/licenses/AGPL-1.0.html +allow Adobe Adobe-2006 Adobe Systems Incorporated CLA false false false https://spdx.org/licenses/Adobe-2006.html +allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html +allow Artistic Artistic-1.0 Artistic License 1.0 true true false https://spdx.org/licenses/Artistic-2.0.html +... ``` ---- +###### Example: policy with `--where` filter -##### Example: Trim `bom-ref` and normalize output +The following example shows filtering of license policies using the `id` column: ```bash -./sbom-utility trim -i test/trim/trim-cdx-1-5-sample-components-normalize.sbom.json --keys="bom-ref" --normalize -q +./sbom-utility license policy --where id=Apache ``` -**Note** If you do not want to remove any keys and simply normalize output, set keys to an empty string: `--keys=""`. - -Use the trim command to remove all `bom-ref` fields and normalize output: +```bash +usage-policy family id name osi fsf deprecated reference aliases annotations notes +------------ ------ -- ---- --- --- ---------- --------- ------- ----------- ----- +allow Apache Apache-1.0 Apache v1.0 false true false https://spdx.org/licenses/Apache-1.0.html none APPROVED none +allow Apache Apache-1.1 Apache v1.1 true true false https://spdx.org/licenses/Apache-1.1.html none APPROVED Superseded by Apache-2.0 +allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0.html Apache License APPROVED none -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "components": [ - { - "type": "library", - "bom-ref": "pkg:npm/sample@2.0.0", - "purl": "pkg:npm/sample@2.0.0", - "name": "sample", - "version": "2.0.0", - "licenses": [ - { - "license": { - "id": "GPL-2.0-or-later" - } - }, - { - "license": { - "id": "LGPL-2.0-or-later" - } - }, - { - "license": { - "id": "GPL-2.0-only" - } - } - ], - "properties": [ - { - "name": "moo", - "value": "cow" - }, - { - "name": "foo", - "value": "bar" - } - ] - }, - { - "type": "library", - "bom-ref": "pkg:npm/body-parser@1.19.0", - "purl": "pkg:npm/body-parser@1.19.0", - "name": "body-parser", - "version": "1.19.0", - "hashes": [ - { - "alg": "SHA-256", - "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" - }, - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - }, - { - "license": { - "id": "Apache-2.0" - } - } - ], - "externalReferences": [ - { - "type": "website", - "url": "https://example.com/website" - }, - { - "type": "support", - "url": "https://example.com/support" - } - ] - } - ] -} ``` -Trimmed, normalized output: +###### Example: policy with `--wrap` flag -```json -{ - "bomFormat": "CycloneDX", - "specVersion": "1.5", - "components": [ - { - "type": "library", - "name": "body-parser", - "version": "1.19.0", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - }, - { - "alg": "SHA-256", - "content": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" - } - ], - "licenses": [ - { - "license": { - "id": "Apache-2.0" - } - }, - { - "license": { - "id": "MIT" - } - } - ], - "purl": "pkg:npm/body-parser@1.19.0", - "externalReferences": [ - { - "type": "support", - "url": "https://example.com/support" - }, - { - "type": "website", - "url": "https://example.com/website" - } - ] - }, - { - "type": "library", - "name": "sample", - "version": "2.0.0", - "licenses": [ - { - "license": { - "id": "GPL-2.0-only" - } - }, - { - "license": { - "id": "GPL-2.0-or-later" - } - }, - { - "license": { - "id": "LGPL-2.0-or-later" - } - } - ], - "purl": "pkg:npm/sample@2.0.0", - "properties": [ - { - "name": "foo", - "value": "bar" - }, - { - "name": "moo", - "value": "cow" - } - ] - } - ] -} +```bash +./sbom-utility license policy --wrap=true -q ``` -### Validate - -This command will parse standardized SBOMs and validate it against its declared format and version (e.g., SPDX 2.2, CycloneDX 1.4). Custom variants of standard JSON schemas can be used for validation by supplying the `--variant` name as a flag. Explicit JSON schemas can be specified using the `--force` flag. - -#### Validating using supported schemas +```bash +usage-policy family id name osi fsf deprecated reference aliases annotations notes +------------ ------ -- ---- --- --- ---------- --------- ------- ----------- ----- +allow 0BSD 0BSD BSD Zero Clause Lice (20/23) true false false https://spdx.org/licenses/0BSD.html Free Public License 1.0. (24/25) APPROVED none +needs-review ADSL ADSL Amazon Digital Servi (20/31) false false false https://spdx.org/licenses/ADSL.html NEEDS-APPROVAL none +allow AFL AFL-3.0 Academic Free Licens (20/26) true true false https://spdx.org/licenses/AFL-3.0.ht (36/38) APPROVED none +needs-review AGPL AGPL-1.0 Affero General Publi (20/34) false false true https://spdx.org/licenses/AGPL-1.0.h (36/39) NEEDS-APPROVAL none + AGPL-WARNING +needs-review APSL APSL-2.0 Apple Public Source (20/31) true true false https://spdx.org/licenses/APSL-2.0.h (36/39) NEEDS-APPROVAL none +allow Adobe Adobe-2006 Adobe Systems Incorp (20/56) false false false https://spdx.org/licenses/Adobe-2006 (36/41) APPROVED none +allow Apache Apache-2.0 Apache License 2.0 true true false https://spdx.org/licenses/Apache-2.0 (36/41) Apache License, Version (24/27) APPROVED none +allow Artistic Artistic-2.0 Artistic License 2.0 true true false https://spdx.org/licenses/Artistic-2 (36/43) APPROVED none +... +``` -Use the [schema](#schema) command to list supported schemas formats, versions and variants. +#### License policy notes -#### Validating using "custom" schemas +- Currently, the default `license.json` file, used to derive the `usage-policy` data, does not contain entries for the entire set of SPDX 3.2 license templates. + - An issue [12](https://github.com/CycloneDX/sbom-utility/issues/12) is open to add parity. +- Annotations (tags) and notes can be defined within the `license.json` file and one or more assigned each license entry. + +- For backwards compatibility, the `--where` filter supports the key `spdx-id` as an alias for `id`. -Customized JSON schemas can also be permanently configured as named schema "variants" within the utility's configuration file. See [adding schemas](#adding-schemas). +--- -- **"Customized" schema** variants, perhaps derived from standard BOM schemas, can be used for validation using the `--variant` flag (e.g., industry or company-specific schemas). -- **Overriding default schema** - You can override an BOM's declared BOM version using the `--force` flag (e.g., verify a BOM against a newer specification version). +### Resource -#### Validate flags +The `resource` command is geared toward inspecting various resources types and their information from SBOMs against future maturity models being developed as part of the [OWASP Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/). In the SCVS model, a "resource" is the parent classification for software (components), services, Machine Learning (ML) models, data, hardware, tools and more. -The following flags can be used to improve performance when formatting error output results: +Primarily, the command is used to generate lists of resources, by type, that are included in a CycloneDX SBOM by invoking `resource list`. -##### `--error-limit` flag +#### Resource supported output formats -Use the `--error-limit x` (default: `10`) flag to reduce the formatted error result output to the first `x` errors. By default, only the first 10 errors are output with an informational messaging indicating `x/y` errors were shown. +This command supports the `--format` flag with any of the following values: -##### `--error-value` flag +- `txt` (default), `csv`, `md` -Use the `--error-value=true|false` (default: `true`) flag to reduce the formatted error result output by not showing the `value` field which shows detailed information about the failing data in the BOM. +#### Resource result sorting -##### `--colorize` flag +Currently, all `resource list` command results are sorted by resource `type` then by resource `name` (required field). -Use the `--colorize=true|false` (default: `false`) flag to add/remove color formatting to error result `txt` formatted output. By default, `txt` formatted error output is colorized to help with human readability; for automated use, it can be turned off. +#### Resource Examples -#### Validate Examples +#### Example: resource list -##### Example: Validate using inferred format and schema +```bash +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json -q +``` -Validating the "juice shop" SBOM (CycloneDX 1.2) example provided in this repository. +```bash +resource-type group name version description bom-ref +------------- ----- ---- ------- ----------- ------- +component ACME Application 2.0.0 ACME sample application pkg:app/sample@1.0.0 +component Library A 1.0.0 Library A description pkg:lib/libraryA@1.0.0 +component Library C 1.0.0 Library C description. pkg:lib/libraryC@1.0.0 +component Library F 1.0.0 Library F description. pkg:lib/libraryF@1.0.0 +component Library G 1.0.0 Library G description. pkg:lib/libraryG@1.0.0 +component Library H 1.0.0 Library H description. pkg:lib/libraryH@1.0.0 +component Library NoLicense 1.0.0 Library "NoLicense" description. pkg:lib/libraryNoLicense@1.0.0 +component blue Library B 1.0.0 Library B description. pkg:lib/libraryB@1.0.0 +component blue Library E 1.0.0 Library E description. pkg:lib/libraryE@1.0.0 +component green Library D 1.0.0 Library D description. pkg:lib/libraryD@1.0.0 +component green Library J 1.0.0 Library J description. pkg:lib/libraryJ@1.0.0 +service Bar Bar service service:example.com/myservices/bar +service Foo Foo service service:example.com/myservices/foo -```bash -./sbom-utility validate -i examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json ``` -```bash -[INFO] Loading (embedded) default schema config file: `config.json`... -[INFO] Loading (embedded) default license policy file: `license.json`... -[INFO] Attempting to load and unmarshal data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`... -[INFO] Successfully unmarshalled data from: `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json` -[INFO] Determining file's BOM format and version... -[INFO] Determined BOM format, version (variant): `CycloneDX`, `1.2` (latest) -[INFO] Matching BOM schema (for validation): schema/cyclonedx/1.2/bom-1.2.schema.json -[INFO] Loading schema `schema/cyclonedx/1.2/bom-1.2.schema.json`... -[INFO] Schema `schema/cyclonedx/1.2/bom-1.2.schema.json` loaded. -[INFO] Validating `examples/cyclonedx/SBOM/juice-shop-11.1.2/bom.json`... -[INFO] BOM valid against JSON schema: `true` -``` +##### Example: resource list using `--type service` -You can also verify the [exit code](#exit-codes) from the validate command: +This example uses the `type` flag to specific `service`. The other valid type is `component`. Future versions of CycloneDX schema will include more resource types such as "ml" (machine learning) or "tool". ```bash -echo $? +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --type service -q ``` ```bash -0 // no error (valid) +resource-type group name version description bom-ref +------------- ----- ---- ------- ----------- ------- +service Bar Bar service service:example.com/myservices/bar +service Foo Foo service service:example.com/myservices/foo ``` -#### Example: Validate using "custom" schema variants - -The validation command will use the declared format and version found within the SBOM JSON file itself to lookup the default (latest) matching schema version (as declared in`config.json`; however, if variants of that same schema (same format and version) are declared, they can be requested via the `--variant` command line flag: +**Note** The results would be equivalent to using the `--where` filter: ```bash -./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "resource-type=service" -q ``` -If you run the sample command above, you would see several "custom" schema errors resulting in an invalid SBOM determination (i.e., `exit status 2`): - -```text -[INFO] Loading (embedded) default schema config file: `config.json`... -[INFO] Loading (embedded) default license policy file: `license.json`... -[INFO] Attempting to load and unmarshal data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`... -[INFO] Successfully unmarshalled data from: `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json` -[INFO] Determining file's BOM format and version... -[INFO] Determined BOM format, version (variant): `CycloneDX`, `1.4` custom -[INFO] Matching BOM schema (for validation): schema/test/bom-1.4-custom.schema.json -[INFO] Loading schema `schema/test/bom-1.4-custom.schema.json`... -[INFO] Schema `schema/test/bom-1.4-custom.schema.json` loaded. -[INFO] Validating `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`... -[INFO] BOM valid against JSON schema: `false` -[INFO] (3) schema errors detected. -[INFO] Formatting error results (`txt` format)... -1. { - "type": "contains", - "field": "metadata.properties", - "context": "(root).metadata.properties", - "description": "At least one of the items must match", - "value": [ - { - "name": "urn:example.com:disclaimer", - "value": "This SBOM is current as of the date it was generated." - }, - { - "name": "urn:example.com:classification", - "value": "This SBOM is Confidential Information. Do not distribute." - } - ] - } -2. { - "type": "const", - "field": "metadata.properties.0.value", - "context": "(root).metadata.properties.0.value", - "description": "metadata.properties.0.value does not match: \"This SBOM is current as of the date it was generated and is subject to change.\"", - "value": "This SBOM is current as of the date it was generated." - } -3. { - "type": "number_all_of", - "field": "metadata.properties", - "context": "(root).metadata.properties", - "description": "Must validate all the schemas (allOf)", - "value": [ - { - "name": "urn:example.com:disclaimer", - "value": "This SBOM is current as of the date it was generated." - }, - { - "name": "urn:example.com:classification", - "value": "This SBOM is Confidential Information. Do not distribute." - } - ] - } -[ERROR] invalid SBOM: schema errors found (test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json) -[INFO] document `test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json`: valid=[false] -``` +##### Example: list with `name` regex match -confirming the exit code: +This example uses the `where` filter on the `name` field. In this case we supply an exact "startswith" regex. for the `name` filter. ```bash -echo $? +./sbom-utility resource list -i test/cyclonedx/cdx-1-3-resource-list.json --where "name=Library A" -q ``` ```bash -2 // SBOM error +resource-type group name version description bom-ref +------------- ----- ---- ------- ----------- ------- +component Library A 1.0.0 Library A description pkg:lib/libraryA@1.0.0 ``` -##### Why validation failed +--- -The output shows a first schema error indicating the failing JSON object; in this case, +### Schema -- the CycloneDX `metadata.properties` field, which is a list of `property` objects. -- Found that a property with a `name` field with the value `"urn:example.com:disclaimer"` had an incorrect `value`. - - the `value` field SHOULD have had a constant value of `"This SBOM is current as of the date it was generated and is subject to change."` (as was required by the custom schema's regex). - - However, it was found to have only a partial match of `"This SBOM is current as of the date it was generated."`. +You can verify which formats, schemas, versions and variants are available for validation by using the `schema` command. -##### Details of the schema error +- **Note**: The `schema` command will default to the `list` subcommand if omitted. -Use the `--debug` or `-d` flag to see all schema error details: +#### Schema supported output formats -```bash -./sbom-utility validate -i test/custom/cdx-1-4-test-custom-metadata-property-disclaimer-invalid.json --variant custom -d -``` +This command supports the `--format` flag with any of the following values: -The details include the full context of the failing `metadata.properties` object which also includes a `"urn:example.com:classification"` property: +- `txt` (default), `csv`, `md` -```bash -3. { - "type": "number_all_of", - "field": "metadata.properties", - "context": "(root).metadata.properties", - "description": "Must validate all the schemas (allOf)", - "value": [ - { - "name": "urn:example.com:disclaimer", - "value": "This SBOM is current as of the date it was generated." - }, - { - "name": "urn:example.com:classification", - "value": "This SBOM is Confidential Information. Do not distribute." - } - ] - } -``` +#### Schema result sorting -#### Example: Validate using "JSON" format +- Formatted results are sorted by `format` (ascending), `version` (descending) and `schema` (descending) -The JSON format will provide an `array` of schema error results that can be post-processed as part of validation toolchain. +#### Schema examples + +##### Example: schema list ```bash -./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json -q +./sbom-utility schema list -q ``` -```json -[ - { - "type": "unique", - "field": "components", - "context": "(root).components", - "description": "array items[1,2] must be unique", - "value": { - "type": "array", - "index": 1, - "item": { - "bom-ref": "pkg:npm/body-parser@1.19.0", - "description": "Node.js body parsing middleware", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "body-parser", - "purl": "pkg:npm/body-parser@1.19.0", - "type": "library", - "version": "1.19.0" - } - } - }, - { - "type": "unique", - "field": "components", - "context": "(root).components", - "description": "array items[2,4] must be unique", - "value": { - "type": "array", - "index": 2, - "item": { - "bom-ref": "pkg:npm/body-parser@1.19.0", - "description": "Node.js body parsing middleware", - "hashes": [ - { - "alg": "SHA-1", - "content": "96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - } - ], - "licenses": [ - { - "license": { - "id": "MIT" - } - } - ], - "name": "body-parser", - "purl": "pkg:npm/body-parser@1.19.0", - "type": "library", - "version": "1.19.0" - } - } - } -] +```bash +name variant format version file url +---- ------- ------ ------- ---- --- +CycloneDX v1.6 development CycloneDX 1.6 schema/cyclonedx/1.6/bom-1.6.schema.json https://raw.githubusercontent.com/CycloneDX/specification/1.6-dev/schema/bom-1.6.schema.json +CycloneDX v1.5 (latest) CycloneDX 1.5 schema/cyclonedx/1.5/bom-1.5.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.5.schema.json +CycloneDX v1.4 (latest) CycloneDX 1.4 schema/cyclonedx/1.4/bom-1.4.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.4.schema.json +CycloneDX v1.4 custom CycloneDX 1.4 schema/test/bom-1.4-custom.schema.json +CycloneDX v1.3 (latest) CycloneDX 1.3 schema/cyclonedx/1.3/bom-1.3.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3.schema.json +CycloneDX v1.3 custom CycloneDX 1.3 schema/test/bom-1.3-custom.schema.json +CycloneDX v1.3 strict CycloneDX 1.3 schema/cyclonedx/1.3/bom-1.3-strict.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.3-strict.schema.json +CycloneDX v1.2 (latest) CycloneDX 1.2 schema/cyclonedx/1.2/bom-1.2.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2.schema.json +CycloneDX v1.2 strict CycloneDX 1.2 schema/cyclonedx/1.2/bom-1.2-strict.schema.json https://raw.githubusercontent.com/CycloneDX/specification/master/schema/bom-1.2-strict.schema.json +SPDX v2.3 (latest) SPDX SPDX-2.3 schema/spdx/2.3/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json +SPDX v2.3.1 development SPDX SPDX-2.3 schema/spdx/2.3.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3.1/schemas/spdx-schema.json +SPDX v2.2.2 (latest) SPDX SPDX-2.2 schema/spdx/2.2.2/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.2/schemas/spdx-schema.json +SPDX v2.2.1 2.2.1 SPDX SPDX-2.2 schema/spdx/2.2.1/spdx-schema.json https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json ``` -##### Reducing output size using `error-value=false` flag +#### Adding schemas -In many cases, BOMs may have many errors and having the `value` information details included can be too verbose and lead to large output files to inspect. In those cases, simply set the `error-value` flag to `false`. +Entries for new or "custom" schemas can be added to the `config.json` file by adding a new schema entry and then will need to pass that file on the command line using the `--config-schema` flag. -Rerunning the same command with this flag set to false yields a reduced set of information. +These new schema entries will tell the schema loader where to find the JSON schema file locally, relative to the utility's executable. -```bash -./sbom-utility validate -i test/validation/cdx-1-4-validate-err-components-unique-items-1.json --format json --error-value=false -q -``` +For details see the "[Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants)" section. -```json -[ - { - "type": "unique", - "field": "components", - "context": "(root).components", - "description": "array items[1,2] must be unique" - }, - { - "type": "unique", - "field": "components", - "context": "(root).components", - "description": "array items[2,4] must be unique" - } -] -``` +#### Embedding schemas + +If you wish to have the new schema *embedded in the executable*, simply add it to the project's `resources` subdirectory following the format and version-based directory structure. --- @@ -2182,7 +2182,7 @@ CVE-2020-25649 611 CVSSv31: 7.5 (high), CVSSv31: 8.2 (high), CVSS --- -#### Completion +### Completion This command will generate command-line completion scripts, for the this utility, customized for various supported shells. From d934abd61565f16b913ad8aaebc4040e45af5ad6 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:57:59 -0500 Subject: [PATCH 19/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7822b98..977ec12 100644 --- a/README.md +++ b/README.md @@ -4,18 +4,18 @@ # sbom-utility +> *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.* + This utility was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either **CycloneDX** or **SPDX**-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities. - *Organizations may also design and supply **"custom JSON schema"** variants to the validate command which are perhaps designed to assure additional data-compliance requirements are met.* +The utility also offers commands that support analysis and editing of BOM document data including **trim**, **patch** (IETF RFC 6902) and **diff** *(experimental)*. + In addition, the utility features "report" commands that can easily *extract*, *filter*, *list* and *summarize* **component**, **service**, **license**, **resource**, **vulnerability** and other BOM information using the utility's powerful, SQL-like query command. The **query** command allows **select**-ion of specific data **from** anywhere in the BOM document **where** data values match specified (regex) patterns. - *Report output can be produced in several formats (e.g., `txt`, `csv`, `md` (markdown) and `json`) to accommodate further processing.* -The utility also offers commands that support analysis and editing of BOM document data including **trim**, **patch** (IETF RFC 6902) and **diff**. - -> **Note**: *The utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc., that adhere to their respective schemas.* - ## Command Overview The following commands, which operate against input BOMs and their data, are offered by the utility: From 4c92a27da238662268bcc8c68f524b77e9783f22 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 14:59:40 -0500 Subject: [PATCH 20/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 977ec12..b3e6529 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ > *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.* -This utility was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either **CycloneDX** or **SPDX**-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities. +**`sbom-utility`** was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either CycloneDX *or* SPDX-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities. - *Organizations may also design and supply **"custom JSON schema"** variants to the validate command which are perhaps designed to assure additional data-compliance requirements are met.* From 897f74a3b16056863308f0251b73c2112c16af6e Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 15:01:04 -0500 Subject: [PATCH 21/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b3e6529..e0c5e76 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ # sbom-utility -> *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.* - -**`sbom-utility`** was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either CycloneDX *or* SPDX-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities. +The **`sbom-utility`** was designed to be an API platform to validate, analyze and edit **Bills-of-Materials (BOMs)**. Initially, it was created to **validate** either CycloneDX *or* SPDX-formatted BOMs against official, versioned JSON schemas as published by their respective standards communities. - *Organizations may also design and supply **"custom JSON schema"** variants to the validate command which are perhaps designed to assure additional data-compliance requirements are met.* @@ -16,6 +14,8 @@ In addition, the utility features "report" commands that can easily *extract*, * - *Report output can be produced in several formats (e.g., `txt`, `csv`, `md` (markdown) and `json`) to accommodate further processing.* +> **Note**: *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.* + ## Command Overview The following commands, which operate against input BOMs and their data, are offered by the utility: From 6786e471ea8d2538f3158a6d5a898f9b8af9743d Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 15:20:56 -0500 Subject: [PATCH 22/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 129 +++++++++++++++++++----------------------------------- 1 file changed, 45 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index e0c5e76..23ea521 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,9 @@ In addition, the utility features "report" commands that can easily *extract*, * > **Note**: *This utility supports all CycloneDX BOM variants, such as Software (**SBOM**), Hardware (**HBOM**), Manufacturing (**MBOM**), Machine Learning and AI (**MLBOM**), Cryptographic (**CBOM**), etc.* -## Command Overview +--- + +### Command Overview The following commands, which operate against input BOMs and their data, are offered by the utility: @@ -116,7 +118,7 @@ Convenient links to each command: --- -#### Exit codes +### Exit codes All commands return a numeric exit code (i.e., a POSIX exit code) for use in automated processing where `0` indicates success and a non-zero value indicates failure of some kind designated by the number. @@ -2282,35 +2284,35 @@ Use the `--format` flag on the to choose one of the supported output formats: --- -### Design considerations +## Design considerations -#### Memory safety +### Memory safety The utility itself is written in `Go` to advantage the language's built-in typing enforcement and memory safe features and its ability to be compiled for a wide range of target platforms and architectures. -#### Consistent output +### Consistent output The utility also is designed to produce output formats (e.g., JSON) and handle exit codes consistently to make it immediately useful standalone or as part of automated Continuous Integration (CI) tool chains for downstream use or inspection. -#### Security and integrity focus +### Security and integrity focus Further commands and reports are planned that prioritize use cases that enable greater insight and analysis of the legal, security and compliance data captured in the SBOM such as component **provenance** and **signage** (e.g., verifying resource identities by hashes or fingerprints). In addition, inclusion of **Continuous Integration and Delivery (CI/CD)** or "build integrity" information around the BOM component is anticipated as part of the CycloneDX Formulation work which will require features for workflow insights. -#### Functional priorities +### Functional priorities The utility additionally prioritizes commands that help provide insight into contents of the BOM to search for and report on missing (i.e., completeness) or specific data requirements (e.g., organization or customer-specific requirements). In general, the goal of these prioritized commands is to support data verification for many of the primary BOM use cases as identified by the CycloneDX community (see https://cyclonedx.org/use-cases/). Functional development has focused on those use cases that verify inventory (resource identity), legal compliance (e.g., license), and security analysis (e.g., vulnerability) which are foundational to any SBOM. -#### Support all BOM formats +### Support all BOM formats In the future, we envision support for additional kinds of BOMs (e.g., Hardware (HBOM), Machine Learning (MLBOM), etc.) with each again having different data requirements and levels of maturity which will increase the need for domain-specific validation. Specifically, this utility intends to support the work of the [OWASP Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/) which is defining a BOM Maturity Model (BMM). --- -### Development +## Development The following development-oriented topics are included in this section: @@ -2321,12 +2323,12 @@ The following development-oriented topics are included in this section: - [Using VSCode](#vscode) - [Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants) -#### Prerequisites +### Prerequisites - Go v1.20.1 or higher: see [https://go.dev/doc/install](https://go.dev/doc/install) - `git` client: see [https://git-scm.com/downloads](https://git-scm.com/downloads) -#### Building +### Building To build an executable of the utility compatible with your local computer's architecture use the `build` target in the project's `Makefile`: @@ -2351,7 +2353,7 @@ Welcome to the sbom-utility! Version `latest` (sbom-utility) (darwin/arm64) If you wish to build binaries for all supported combinations of `GOOS` and `GOARCH` values, use the `release` target (i.e., `make release`) which will produce named binaries of the form `sbom-utility-${GOOS}-${GOARCH}` under the `release` directory (e.g., `sbom-utility-darwin-amd64`). -#### Running from source +### Running from source Developers can run using the current source code in their local branch using `go run main.go`. For example: @@ -2359,9 +2361,9 @@ Developers can run using the current source code in their local branch using `go go run main.go validate -i test/cyclonedx/cdx-1-4-mature-example-1.json ``` -#### Debugging +### Debugging -##### VSCode +#### VSCode This project was developed using VSCode and can be seamlessly loaded as a project. @@ -2395,37 +2397,42 @@ or add it globally to the `settings.json` file: **Note**: *The `showGlobalVariables` setting was only recently disabled as the default in VSCode as a stop-gap measure due to performance (loading) problems under Windows.* -#### Adding SBOM formats, schema versions and variants +### Supporting new SBOM formats and schema versions -The utility uses the [`config.json`](./config.json) file (either the default, embedded version or the equivalent provided on the command line using `--config-schema` flag) to lookup supported formats and their associated versioned JSON schema files. To add another SBOM format simply add another entry to the `format` array in the root of the document: +The utility uses the [`config.json`](./config.json) file (either the default, embedded version or the equivalent provided on the command line using `--config-schema` flag) to lookup supported formats and their associated versioned JSON schema files. To add another SBOM format simply add another entry to the `format` array in the document: ```json { - "canonicalName": "SPDX", - "propertyKeyFormat": "SPDXID", - "propertyKeyVersion": "spdxVersion", - "propertyValueFormat": "SPDXRef-DOCUMENT", - "schemas": [ - { - ... - } - ] + "canonicalName": "SPDX", + "propertyKeyFormat": "SPDXID", + "propertyKeyVersion": "spdxVersion", + "propertyValueFormat": "SPDXRef-DOCUMENT", + "schemas": [ + { + ... + } + ] ... } ``` The value for `propertyKeyFormat` should be the exact name of key field that would appear in the JSON SBOM itself which can be used to confirm it is indeed a format match. In addition, the corresponding value to match for that key should be declared in the `propertyValueFormat` value. -The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `propertyValueFormat` are required. The `format` object **MUST** have at least one valid `schema` object. The `schema` object appears as follows: +The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `propertyValueFormat` are required. The `format` object **MUST** have at least one valid `schema` object. + +An example `schema` object for the canonical SPDX v2.3 (default, no variant) schema appears as follows: ```json { - "version": "SPDX-2.2", - "file": "file://schema/spdx/2.2.1/spdx-schema.json", - "url": "https://raw.githubusercontent.com/spdx/spdx-spec/v2.2.1/schemas/spdx-schema.json", - "strict": false, - "latest": true, - "variant": "" + { + "version": "SPDX-2.3", + "variant": "", + "name": "SPDX v2.3", + "file": "schema/spdx/2.3/spdx-schema.json", + "development": "https://github.com/spdx/spdx-spec/blob/development/v2.3/schemas/spdx-schema.json", + "url": "https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json", + "default": true + }, }, ``` @@ -2436,7 +2443,7 @@ The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `prop --- -### Contributing +## Contributing Contributions are welcome under the Apache 2.0 license. Help is wanted in the following areas: @@ -2463,52 +2470,6 @@ An ad-hoc list of featured "TODOs" geared at making the tool more accessible, ex --- -### Supporting new SBOM formats and schema versions - -The utility uses the [`config.json`](./config.json) file to lookup supported BOM formats and their associated versioned schemas. To add another SBOM format simply add another entry to the `format` array in the root of the document: - -```json -{ - "canonicalName": "SPDX", - "propertyKeyFormat": "SPDXID", - "propertyKeyVersion": "spdxVersion", - "propertyValueFormat": "SPDXRef-DOCUMENT", - "schemas": [ - { - ... - } - ] - ... -} -``` - -The value for `propertyKeyFormat` should be the exact name of key field that would appear in the JSON SBOM itself which can be used to confirm it is indeed a format match. In addition, the corresponding value to match for that key should be declared in the `propertyValueFormat` value. - -The fields `canonicalName`, `propertyKeyFormat`, `propertyKeyVersion`, and `propertyValueFormat` are required. The `format` object **MUST** have at least one valid `schema` object. - -An example `schema` object for the canonical SPDX v2.3 (default, no variant) schema appears as follows: - -```json -{ - { - "version": "SPDX-2.3", - "variant": "", - "name": "SPDX v2.3", - "file": "schema/spdx/2.3/spdx-schema.json", - "development": "https://github.com/spdx/spdx-spec/blob/development/v2.3/schemas/spdx-schema.json", - "url": "https://raw.githubusercontent.com/spdx/spdx-spec/development/v2.3/schemas/spdx-schema.json", - "default": true - }, -}, -``` - -- Add a copy of the JSON schema file locally in the project under the structure `resources/schema///`. - - **Note** If the schema exists under the `resources` directory, it will automatically be embedded in in the executable binary when built using `go build` which includes using the project's `Makefile`. -- Assure **only one** `schema` object entry for a given format and version has the value `latest` set to `true`. This latest schema will be used when the SBOM being validated does not have a clear version declared **or** used with the `--force latest` flag. -- If you have a customized or "variant" version of a schema (with the same format and version values) you wish to use for validation (e.g., a `corporate`or `staging` version with added requirements or for testing an unreleased version), you can create an entry that has the same `version` as another entry, but also declare its `variant` name *(non-empty value)*. This value can be supplied on the commend line with the `--variant ` flag to force the validator to use it instead of the default *(empty variant value)*. - ---- - ## Testing Testing implementation and invocation, with examples, is described in this section including: @@ -2574,7 +2535,7 @@ run an individual test within the `cmd` package: go test github.com/CycloneDX/sbom-utility/cmd -v -run TestValidateCdx14MinRequiredBasic ``` -##### Debugging `go test` +#### Debugging `go test` Simply append the flags `--args --trace` or `--args --debug` to your `go test` command to enable trace or debug output for your designated test(s): @@ -2594,9 +2555,9 @@ go test github.com/CycloneDX/sbom-utility/cmd -v --quiet --- -#### Releasing +## Releasing -##### GitHub +### GitHub In order to initiate the release workflow, simply go to the release page of the repository: @@ -2604,7 +2565,7 @@ In order to initiate the release workflow, simply go to the release page of the and click on the `Draft a new release` button. Follow the instructions to create a new version tag, provide an appropriate release title and description and `publish` the release. The GitHub release workflow will be triggered automatically. -##### Local +### Local For local development, you may choose to make a release on your machine using the `Makefile` directive `release`: @@ -2631,7 +2592,7 @@ drwxr-xr-x 27 User1 staff 864 Jan 27 14:43 .. - *Please also note that the common `*.json` configuration files are also copied to the `release` directory.* -##### Versioning +### Versioning to produce a release version you can set the following flags and invoke `go build` directly: From 944976c9e9e86835d174f92611b6b524a5f4e2fe Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 15:24:04 -0500 Subject: [PATCH 23/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23ea521..4c52004 100644 --- a/README.md +++ b/README.md @@ -2321,7 +2321,7 @@ The following development-oriented topics are included in this section: - [Running from source](#running-from-source) - [Debugging](#debugging) - [Using VSCode](#vscode) -- [Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants) +- [Adding new SBOM formats, schema versions and variants](#adding-new-sbom-formats-schema-versions-and-variants) ### Prerequisites @@ -2397,7 +2397,7 @@ or add it globally to the `settings.json` file: **Note**: *The `showGlobalVariables` setting was only recently disabled as the default in VSCode as a stop-gap measure due to performance (loading) problems under Windows.* -### Supporting new SBOM formats and schema versions +### Adding new SBOM formats, schema versions and variants The utility uses the [`config.json`](./config.json) file (either the default, embedded version or the equivalent provided on the command line using `--config-schema` flag) to lookup supported formats and their associated versioned JSON schema files. To add another SBOM format simply add another entry to the `format` array in the document: From ecb0d93463529bf8870c23b3a855357af6ed3c7c Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 15:25:41 -0500 Subject: [PATCH 24/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c52004..13a726e 100644 --- a/README.md +++ b/README.md @@ -2101,7 +2101,7 @@ Entries for new or "custom" schemas can be added to the `config.json` file by ad These new schema entries will tell the schema loader where to find the JSON schema file locally, relative to the utility's executable. -For details see the "[Adding SBOM formats, schema versions and variants](#adding-sbom-formats-schema-versions-and-variants)" section. +For details see the "[Adding new SBOM formats, schema versions and variants](#adding-new-sbom-formats-schema-versions-and-variants)" section. #### Embedding schemas From cfee03440b0b0667dbbb29cda6d94b34f4e92b47 Mon Sep 17 00:00:00 2001 From: Matt Rutkowski Date: Thu, 9 May 2024 15:29:11 -0500 Subject: [PATCH 25/25] Final proof-read changes Signed-off-by: Matt Rutkowski --- README.md | 56 +++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 13a726e..616c202 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ The following commands, which operate against input BOMs and their data, are off - [Installation](#installation) - [Running](#running) - [Commands](#commands) -- [Design considerations](#design-considerations) - [Contributing](#contributing) +- [Design considerations](#design-considerations) - [Development](#development) - [Testing](#testing) - [Releasing](#releasing) @@ -2284,6 +2284,33 @@ Use the `--format` flag on the to choose one of the supported output formats: --- +## Contributing + +Contributions are welcome under the Apache 2.0 license. Help is wanted in the following areas: + +- [TODO list](#todo-list) +- [Priority features](#priority-features) + +#### TODO list + +The entirety of the code contains the tag "**TODO**" with comments of things that are features or improvements conceived while authoring the base functionality. Most of these do not have active issues opened form them. + +Feel free to "grep" for the "TODO" tag, open an issue and/or submit a draft PR. + +#### Priority features + +An ad-hoc list of featured "TODOs" geared at making the tool more accessible, extensible and useful especially around "core" commands such as validation. + +- **Merge command** Support merge of two (both validated) SBOMs with de-duplication and configurable. Please note that some method of normalization prior to merge will be necessary. +- **Remote Schema loading** Support using SBOM schema files that are remotely hosted (network accessible) from known, trusted source locations (e.g., releases of SPDX, CycloneDX specification schemas). Note that the config file has an existing `url` field per entry that can be used for this purpose. +- **--orderby** Support ordering of query result sets by comparison of values from a specified field key. +- **license.json** Document license policy configuration JSON schema structure and how to add entries relative to a CycloneDX `LicenseChoice` object for entries with SPDX IDs and those without. +- **license.json** Add entries for all SPDX licenses listed in v3.21. + - See issue: https://github.com/CycloneDX/sbom-utility/issues/12 +- **Go libraries** Replace `go-prettyjson`, `go-multimap` libraries with alternatives that produce maintained releases. + +--- + ## Design considerations ### Memory safety @@ -2443,33 +2470,6 @@ An example `schema` object for the canonical SPDX v2.3 (default, no variant) sch --- -## Contributing - -Contributions are welcome under the Apache 2.0 license. Help is wanted in the following areas: - -- [TODO list](#todo-list) -- [Priority features](#priority-features) - -#### TODO list - -The entirety of the code contains the tag "**TODO**" with comments of things that are features or improvements conceived while authoring the base functionality. Most of these do not have active issues opened form them. - -Feel free to "grep" for the "TODO" tag, open an issue and/or submit a draft PR. - -#### Priority features - -An ad-hoc list of featured "TODOs" geared at making the tool more accessible, extensible and useful especially around "core" commands such as validation. - -- **Merge command** Support merge of two (both validated) SBOMs with de-duplication and configurable. Please note that some method of normalization prior to merge will be necessary. -- **Remote Schema loading** Support using SBOM schema files that are remotely hosted (network accessible) from known, trusted source locations (e.g., releases of SPDX, CycloneDX specification schemas). Note that the config file has an existing `url` field per entry that can be used for this purpose. -- **--orderby** Support ordering of query result sets by comparison of values from a specified field key. -- **license.json** Document license policy configuration JSON schema structure and how to add entries relative to a CycloneDX `LicenseChoice` object for entries with SPDX IDs and those without. -- **license.json** Add entries for all SPDX licenses listed in v3.21. - - See issue: https://github.com/CycloneDX/sbom-utility/issues/12 -- **Go libraries** Replace `go-prettyjson`, `go-multimap` libraries with alternatives that produce maintained releases. - ---- - ## Testing Testing implementation and invocation, with examples, is described in this section including: