Skip to content

Latest commit

 

History

History
173 lines (139 loc) · 6.87 KB

0038-cdx-syft-sbom.md

File metadata and controls

173 lines (139 loc) · 6.87 KB

Support for CycloneDX and Syft SBoM in Paketo

Summary

Buildpacks which directly provide a dependency or buildpacks which install application dependencies will support the generation of SBoM in the format of CycloneDX and Syft. Per CNB RFC#95, the SBoM documents will live at <layer>.bom.<ext>.json, launch.bom.<ext>.json and build.bom.<ext>.json where <ext> will be cdx (CycloneDX) or syft (Syft).

Motivation

Paketo RFC#33 describes the initial strategy used to add support for SBoM generation in Paketo buildpacks. This RFC outlines the process by which Paketo buildpacks will build upon that initial strategy by including support for CycloneDX and Syft SBoM formats in accordance with the structure proposed in CNB RFC#95:SBOM.

Detailed Explanation

Paketo buildpacks may produce SBoM for runtime & application dependencies in CycloneDX and Syft formats. SBoM information may be provided in three locations, namely <layers>/<layer>.bom.<ext>.json, <layers>/launch.bom.<ext>.json and <layers>/build.bom.<ext>.json, where is cdx for CycloneDX or syft for Syft formats. The preferred content of these files is outlined below:

  • <layer>.bom.<ext>.json: This file should be used only for SBoM information that is specific to a layer. This allows for greater specificity on the origin of the SBoM metadata, including which layer it relates to and which buildpack created the layer. Storing metadata here also potentially reduces overhead incurred by SBoM generation as the file would follow the lifecycle of the layer itself in terms caching and reuse.

  • launch.bom.<ext>.json: This file should contain SBoM entries for dependencies which are contributed to the app image, but are not necessarily scoped to a specific layer. SBoM information stored here is ephemeral and would need to be regenerated on each build.

  • build.bom.<ext>.json: This file should contain SBoM entries for dependencies which are contributed to the build environment, but are not necessarily scoped to a specific layer. SBoM information stored here is ephemeral and would need to be regenerated on each build.

Note: The above schema is not a hard requirement. What each of these files consists of is ultimately the buildpack author's decision. Additional context can be found here.

Buildpack authors will also need to specify which SBoM formats are supported by a given buildpack via buildpack.toml. This should look like:

api = "0.x"

[buildpack]
id = "<buildpack ID>"
name = "<buildpack name>"
# This can be an array of supported SBOM formats by the buildpack.
# Valid array values are sbom media types based on https://www.iana.org/assignments/media-types/media-types.xhtml
sbom = ["application/vnd.cyclonedx+json", "application/vnd.syft+json"]

SBoM Formats

Syft

The minimum set of Syft fields that will be initially supported is represented below. It is possible that additional fields will be supported in the future.

{
 "artifacts": [
  {
   "id": <Syft-generated UUID string for in-file dependency graphing>,
   "name": <dependency name>,
   "version": <dependency version>,
   "licenses": [<dependency license ID(s) in SPDX-format>],
   "cpes": [<version-specific common platform enumerations>],
   "purl": [<package URL per github.com/package-url>]
  }
 ],
 "descriptor": {
  "name": "syft",
  "version": <Syft version>
 },
 "schema": {
  "version": "1.1.0",
  "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.1.0.json"
 }
}

CycloneDX

The minimum set of CycloneDX fields that will be initially supported is represented below. It is possible that additional fields will be supported in the future.

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.3",
  "version": <BOM revision number>,
  "components": [
    {
      "type": <component type, usually library>,
      "name": <package name>,
      "version": <package version>,
      "licenses": [<package license ID(s) in SPDX-format>],
      "purl": <package URL per github.com/package-url>,
    }
  ]
}

Amendment: SBOM Reproducibility

Summary

Build reproducibility is a selling point of Cloud Native Buildpacks. Since SBOMs are currently included inside OCI images built with buildpacks, if SBOMs are not reproducible, buildpack builds cannot be reproducible. It's come to our attention that the CycloneDX JSON SBOM generated by Syft includes some optional metadata that makes SBOMs irreproducible. This amendment proposes that we remove these optional metadata fields to preserve buildpack build reproducibility.

Motivation

Users have brought to our attention that SBOMs in the Go buildpack broke build reproducibility, which users had been relying on. Since build reproducibility is a major value proposition of Cloud Native Buildpacks, we should not make users choose between SBOMs and reproducible builds.

Detailed Explanation

As outlined on the implementation issue for this RFC, the CycloneDX v1.3 specification includes two optional pieces of metadata that result in irreproducible SBOMs. They are:

  • metadata.timestamp (optional) – the time when the SBOM was generated
  • serialNumber (optional) - a UUID that is intended to be unique to each SBOM; intentionally not reproducible

Since these fields are optional, this RFC proposes that we omit them both from the CycloneDX v1.3 SBOMs generated by the buildpacks.

Implementation

For buildpacks that use packit, we can omit the metadata.timestamp and serialNumber fields from the Go struct that represents a CycloneDX v1.3 SBOM. Once buildpacks upgrade to the newer version of packit, SBOMs will no longer include the irreproducible fields.

For buildpacks that don't use packit, the fields can be stripped from the SBOM JSON after it's generated, during the build process. At the time of writing this, this is already implemented in the Java buildpacks.

Prior Art

Paketo RFC#33

CNB RFC #95: SBOM

CNB Run Image SBoM RFC (WIP)