diff --git a/application.go b/application.go index ffa8aba..1d11438 100644 --- a/application.go +++ b/application.go @@ -73,6 +73,8 @@ type LaunchTOML struct { Slices []Slice `toml:"slices"` // BOM is a collection of entries for the bill of materials. + // + // Deprecated: as of Buildpack API 0.7, write to `layer.BOMPath()` instead BOM []BOMEntry `toml:"bom"` } @@ -83,6 +85,8 @@ func (l LaunchTOML) isEmpty() bool { // BuildTOML represents the contents of build.toml. type BuildTOML struct { // BOM contains the build-time bill of materials. + // + // Deprecated: as of Buildpack API 0.7, write to `layer.BOMPath()` instead BOM []BOMEntry `toml:"bom"` // Unmet is a collection of buildpack plan entries that should be passed through to subsequent providers. @@ -94,6 +98,8 @@ func (b BuildTOML) isEmpty() bool { } // BOMEntry contains a bill of materials entry. +// +// Deprecated: as of Buildpack API 0.7, BOM should use standard formats like CycloneDX going forward type BOMEntry struct { // Name represents the name of the entry. Name string `toml:"name"` diff --git a/build.go b/build.go index 3084a8e..223a298 100644 --- a/build.go +++ b/build.go @@ -58,6 +58,8 @@ type BuildContext struct { // BuildResult contains the results of detection. type BuildResult struct { // BOM contains entries to be appended to the app image Bill of Materials and/or build Bill of Materials. + // + // Deprecated: as of Buildpack API 0.7, write to `layer.BOMPath()` instead BOM *BOM // Labels are the image labels contributed by the buildpack. @@ -81,6 +83,8 @@ type BuildResult struct { } // BOM contains all Bill of Materials entries +// +// Deprecated: as of Buildpack API 0.7, write to `layer.BOMPath()` instead type BOM struct { Entries []BOMEntry } @@ -302,6 +306,7 @@ func Build(builder Builder, options ...Option) { } } + // Deprecated: as of Buildpack API 0.7, to be removed in a future version var launchBOM, buildBOM []BOMEntry if result.BOM != nil { for _, entry := range result.BOM.Entries { diff --git a/layer.go b/layer.go index 1795849..0ddc71b 100644 --- a/layer.go +++ b/layer.go @@ -28,7 +28,6 @@ import ( // Exec represents the exec.d layer location type Exec struct { - // Path is the path to the exec.d directory. Path string } @@ -68,9 +67,21 @@ func (p Profile) ProcessAddf(processType string, name string, format string, a . p.Addf(filepath.Join(processType, name), format, a...) } -// Contribute represents a layer managed by the buildpack. -type Layer struct { +// BOMFormat indicates the format of the SBOM entry +type SBOMFormat int + +const ( + CycloneDXJSON SBOMFormat = iota + SPDXJSON + SyftJSON +) +func (b SBOMFormat) String() string { + return []string{"cdx.json", "spdx.json", "syft.json"}[b] +} + +// Layer represents a layer managed by the buildpack. +type Layer struct { // LayerTypes indicates the type of layer LayerTypes `toml:"types"` @@ -99,6 +110,10 @@ type Layer struct { Exec Exec `toml:"-"` } +func (l Layer) SBOMPath(bt SBOMFormat) string { + return filepath.Join(filepath.Dir(l.Path), fmt.Sprintf("%s.sbom.%s", l.Name, bt)) +} + // LayerTypes describes which types apply to a given layer. A layer may have any combination of Launch, Build, and // Cache types. type LayerTypes struct { @@ -116,7 +131,6 @@ type LayerTypes struct { // LayerContributor is an interface for types that create layers. type LayerContributor interface { - // Contribute accepts a layer and transforms it, returning a layer. Contribute(layer Layer) (Layer, error) @@ -126,7 +140,6 @@ type LayerContributor interface { // Layers represents the layers part of the specification. type Layers struct { - // Path is the layers filesystem location. Path string } @@ -162,3 +175,13 @@ func (l *Layers) Layer(name string) (Layer, error) { return layer, nil } + +// BOMBuildPath returns the full path to the build SBoM file for the buildpack +func (l Layers) BuildSBOMPath(bt SBOMFormat) string { + return filepath.Join(l.Path, fmt.Sprintf("build.sbom.%s", bt)) +} + +// BOMLaunchPath returns the full path to the launch SBoM file for the buildpack +func (l Layers) LaunchSBOMPath(bt SBOMFormat) string { + return filepath.Join(l.Path, fmt.Sprintf("launch.sbom.%s", bt)) +} diff --git a/layer_test.go b/layer_test.go index 5b15ee2..0d6d6e2 100644 --- a/layer_test.go +++ b/layer_test.go @@ -110,6 +110,18 @@ func testLayer(t *testing.T, context spec.G, it spec.S) { Expect(l.Profile).To(Equal(libcnb.Profile{})) }) + it("generates BOM paths", func() { + l, err := layers.Layer("test-name") + Expect(err).NotTo(HaveOccurred()) + + Expect(l.Path).To(Equal(filepath.Join(path, "test-name"))) + Expect(layers.BuildSBOMPath(libcnb.CycloneDXJSON)).To(Equal(filepath.Join(path, "build.sbom.cdx.json"))) + Expect(layers.BuildSBOMPath(libcnb.SPDXJSON)).To(Equal(filepath.Join(path, "build.sbom.spdx.json"))) + Expect(layers.BuildSBOMPath(libcnb.SyftJSON)).To(Equal(filepath.Join(path, "build.sbom.syft.json"))) + Expect(layers.LaunchSBOMPath(libcnb.SyftJSON)).To(Equal(filepath.Join(path, "launch.sbom.syft.json"))) + Expect(l.SBOMPath(libcnb.SyftJSON)).To(Equal(filepath.Join(path, "test-name.sbom.syft.json"))) + }) + it("reads existing 0.5 metadata", func() { Expect(ioutil.WriteFile( filepath.Join(path, "test-name.toml"), diff --git a/platform.go b/platform.go index 5bcc2c1..937cbcf 100644 --- a/platform.go +++ b/platform.go @@ -43,6 +43,7 @@ const ( // EnvCNBBindings is the name of the environment variable that contains the path to the CNB bindings directory. // See the CNB bindings extension spec for more details - https://github.com/buildpacks/spec/blob/main/extensions/bindings.md + // // Deprecated: Use the Service Binding Specification for Kubernetes instead - // https://github.com/buildpacks/rfcs/blob/main/text/0055-deprecate-service-bindings.md. EnvCNBBindings = "CNB_BINDINGS"