A Gitpod based playground to understand bomctl.
Launch the Playground in gitpod.
Follow one of the installation methods.
bomctl uses several key concepts that are important to understand to effectively use the tool.
bomctl uses a sqlite document storage cache to manage documents. Similar to how docker image storage is managed on a system, users should not directly interact with the cache.
The cache is located in one of these locations:
- Unix:
$HOME/.cache/bomctl - Darwin:
$HOME/Library/Caches/bomctl - Windows:
%LocalAppData%\bomctl
Software Bill of Materials (SBOMs) are imported into the cache, manipulated, and then exported.
Generating SBOMs for complex systems usually involves multiple SBOM files, and sometimes the
format of SBOMs provided for sub-components is outside of a user's control. Internally, bomctl leverages
protobom to parse and store SBOMs in a format-agnostic way. bomctl can
import SBOMs in various formats and easily perform operations on them without having to first be converted,
potentially losing information in the process. In addition, this allows for easy conversion of provided SBOMs
and generation of SBOMs in all supported formats.
For more information on which formats bomctl supports, run:
bomctl export --helpThe supported formats and encodings are available in the help info.
Rarely are systems represented by a single application, and therefore multiple components in a system need are probably going to be individual SBOMs. For example a helm chart deployment has several container images. Each container image is going to have its own SBOM.
bomctl is designed to work with "trees of SBOMs" where linkages exist between components and lower level SBOMs.
bomctl has two commands for adding SBOMs to the cache
bomctl fetchwill download SBOMs from different sourcesbomctl importwill import local SBOM files or SBOM content piped from stdin
Add SBOMs to cache:
bomctl fetch https://raw.githubusercontent.com/bomctl/bomctl-playground/main/examples/bomctl-container-image/bomctl_bomctl_v0.3.0.cdx.jsonNotice two important bomctl objectives in the command above.
bomctlis designed to handle collections or sets of SBOM documents. While only one url is listed in the command a second SBOM document was fetched along with the first. This happens becausebomctlwill recursively fetch any SBOMs that are external references of components. This is a foundational concept for representing modern software systems.bomctlsupports multiple SBOM formats. The first SBOM fetched is a CycloneDX 1.5 SBOM Document, the second externally referenced SBOM is an SPDX 2.3 SBOM Document.
List SBOMs in cache:
bomctl listUsing Trivy, scan a remote image and pipe the output into bomctl
trivy image --format spdx-json chainguard/cosign:latest | bomctl import -bomctl import examples/bomctl_0.3.0_darwin_arm64.tar.gz.spdx.jsonand/or
bomctl import examples/bomctl_0.1.3_darwin_amd64.tar.gz.cdx.jsonList SBOMs in cache:
bomctl listbomctl export --helpNotice there are two flags that control how the document is exported:
- Encoding: Controls what encoding the resulting document will be, either json or xml. Default:
json
Note
The format choice may change the encoding options.
- Format: Controls the format and format version. Default:
cyclonedx
Note
The generic spdx and cyclonedx format options will use the latest version of that format supported by bomctl.
There are more explicit format options for each format version if an older version is desired.
Export the an SBOM to a local directory.
This step assumes the CycloneDX SBOM from exercise was previously fetched.
bomctl export urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db -f spdx -o test.spdx.jsonNote that the document that was initally fetched was a CycloneDX SBOM and the above command is exporting an SPDX SBOM.
Grype is a tool that can scan SBOMs for vulnerabilities and accepts them as input from stdin.bomctlcan facilitate this.
bomctl export urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db | grypebomctl push --helpSimilar to export, there are options to specify the format and encoding of the pushed SBOM(s).
Review flags for encoding and format here
Setup:
Push the original SBOM to a "remote" oci registry. In this exercise, the env variable used BOMCTL_PORT_URL is already set in the environment, so the commands
can be copied/pasted as is. Based on this example from Oras.
For a more interactive view, switch to the ports tab of the open terminal and select the globe icon next to the Zot Registry row.
This will open the deployed Zot Registry we are using for the OCI registry endpoint. There is another preloaded tag in this registry,
simply for illustration and initialization purposes.
Note
- Using this example registry is only necessary to make these exercises standalone, a personal or test oci registry can also be used.
- For authentication to those registries, a
.netrcfile needs to be created and a flag--netrcshould be added to thepushcommand.
bomctl push -f spdx urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db oci://${BOMCTL_PORT_URL}/hello-bomctl:latestFetch the manifest from the local test registry
oras manifest fetch ${BOMCTL_PORT_URL}/hello-bomctl:latest | jqIdentify the appropriate blob digest from the manifest output from previous cmd:
For SPDX, look for a layer with "mediaType": "application/spdx+json"
For CycloneDX, look for a layer with "mediaType": "application/vnd.cyclonedx+json;version=<version#>". Note the <version#> at the end would have the CycloneDX version of the SBOM.
Once the layer has been identified, copy the digest.
In the example below, the digest for the CycloneDX SBOM layer would be "sha256:bd309293a0e79962aa08abf2e5e4e636d254accf9a455bdf17c6ca22bc3ae7a0"
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"data": "e30="
},
"layers": [
{
"mediaType": "application/vnd.cyclonedx+json;version=1.5",
"digest": "sha256:bd309293a0e79962aa08abf2e5e4e636d254accf9a455bdf17c6ca22bc3ae7a0",
"size": 2470,
"data": "super cool data"
}
]
}Fetch the blob contents using the digest located in the previous step:
oras blob fetch --output - ${BOMCTL_PORT_URL}/hello-bomctl@sha256:<digest of SBOM layer in manifest>The merge command will merge two or more documents that exist in local storage. This will leave the original SBOMs unaltered in
the cache and will generate a new SBOM with the combined, deduplicated contents.
More info regarding the merge command and merging strategy can be found in the help menu for the command:
bomctl merge --helpNext merge some simple test boms in the db to illustrate how it works.
bomctl import examples/bomctl_merge_A.cdx.json examples/bomctl_merge_B.cdx.jsonView the imported SBOMs in the database:
bomctl listThese are intentionally small, manageable SBOMs. Use cat to view contents if desired, or simply open them in the editor to view.
To give the merged SBOM a specific name, add a --name or -n flag; otherwise a UUID will be generated and used as the name.
To merge:
bomctl merge urn:uuid:0cd5c64f-318a-40cd-a2a9-a93301beff5d urn:uuid:3de02d44-f9c6-4a94-bf48-eb92730dc3b5Important
Look for the last line in the output, for a line that start with INFO merge: Adding merged document sbomID=.
Copy the string with urn:uid (Hint: it's everything after the =), Needed in the next step.
Do another list to see the new third SBOM that has been generated, while both previous SBOMs are still available.
bomctl listNow export the merged SBOM to see the before and after:
Replace the <UUID> with the uuid copied in the previous step.
bomctl export <UUID> -f spdx -o merged-sbom.spdx.jsonThese SBOMs were originally CycloneDX, but can be exported as SPDX if desired. Or, to inspect the merge behavior more easily
export in the original CycloneDX and use the original files as reference to understand the result (remember the default export
format is CycloneDX so the -f isn't needed).
bomctl export <UUID> -o merged-sbom.cdx.jsonWorking with multiple SBOMs, it can be tricky to keep documents straight, as different formats have different expectations for naming. bomctl
typically relies on document IDs for storing documents; however, these can be taxing to use as an ID when performing operations. The alias command
gives the option to pick a more human readable name for a document for ease of use.
To get more information about alias and its' subcommands, run:
bomctl alias --helpThis step assumes the CycloneDX SBOM from exercise was previously fetched.
bomctl alias set urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db 0_3_0Displays top level info about everything in the cache, including aliases
bomctl listor this command displays only the alias information
bomctl alias listThis commmand removes the existing alias for the provided SBOM ID.
bomctl alias remove urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5dbWorking with multiple SBOMs, it can be hard to keep documents organized. There may be groups of SBOMs within your system that are related and should
be handled together, or at least linked in a way that makes it easy to know what goes with what. The tag command allows a user to specify a 'tag'
to associate with an SBOM to make searching for and organizing your SBOMs easier.
To get more information about tag and its' subcommands, run:
bomctl tag --helpThis step assumes the CycloneDX SBOM from exercise was previously fetched. Feel free to use any previously fetched SBOM in the local database instead by updating the SBOM ID in the command.
Since this SBOM originated from abomctlcontainer image, lets add those tags. Additional SBOM IDs can be specified separated by spaces.
bomctl tag add urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db bomctl container SBOM CDX TestLets list them out to illustrate how to check this for any SBOM in your database to get more info about it.
bomctl tag list urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5dbIt's probably redundant to have this SBOM tagged with bomctl since thats all we've been handling, so lets remove it.
bomctl tag remove urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db bomctlThen run a quick list command to make sure it reflects the expected tags.
bomctl tag list urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5dbThis particular SBOM still has too many superfluous tags, so just clear them all.
bomctl tag clear urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5dbThen run a quick list command to make sure it reflects the expected tags.
bomctl tag list urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db