Skip to content

Commit

Permalink
Makes CycloneDX SBOM Reproducible (#369)
Browse files Browse the repository at this point in the history
* Makes CycloneDX SBOM Reproducible

- Removes the serial number and timestamp in the FormatterReader.Read()
  function

* Adds format verification check

* Update sbom/formatted_reader.go

Co-authored-by: Sophie Wigmore <swigmore@vmware.com>

Co-authored-by: Sophie Wigmore <swigmore@vmware.com>
  • Loading branch information
ForestEckhardt and Sophie Wigmore authored Aug 3, 2022
1 parent 7cc181e commit 3b843c5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
25 changes: 25 additions & 0 deletions sbom/formatted_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sbom

import (
"bytes"
"encoding/json"
"fmt"
"io"
"sync"
Expand Down Expand Up @@ -53,6 +54,30 @@ func (f *FormattedReader) Read(b []byte) (int, error) {
return 0, fmt.Errorf("failed to format sbom: %w", err)
}

// Makes CycloneDX SBOM more reproducible, see
// https://github.com/paketo-buildpacks/packit/issues/367 for more details.
if f.format.ID() == "cyclonedx-1.3-json" || f.format.ID() == "cyclonedx-1-json" {
var cycloneDXOutput map[string]interface{}
err = json.Unmarshal(output, &cycloneDXOutput)
if err != nil {
return 0, fmt.Errorf("failed to modify CycloneDX SBOM for reproducibility: %w", err)
}
for k := range cycloneDXOutput {
if k == "metadata" {
metadata := cycloneDXOutput[k].(map[string]interface{})
delete(metadata, "timestamp")
cycloneDXOutput[k] = metadata
}
if k == "serialNumber" {
delete(cycloneDXOutput, k)
}
}
output, err = json.Marshal(cycloneDXOutput)
if err != nil {
return 0, fmt.Errorf("failed to modify CycloneDX SBOM for reproducibility: %w", err)
}
}

f.reader = bytes.NewBuffer(output)
}

Expand Down
11 changes: 11 additions & 0 deletions sbom/formatted_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,20 @@ func testFormattedReader(t *testing.T, context spec.G, it spec.S) {
_, err := io.Copy(buffer, sbom.NewFormattedReader(bom, sbom.CycloneDXFormat))
Expect(err).NotTo(HaveOccurred())

format := syft.IdentifyFormat(buffer.Bytes())
Expect(format.ID()).To(Equal(syft.CycloneDxJSONFormatID))

var cdxOutput cdxOutput

err = json.Unmarshal(buffer.Bytes(), &cdxOutput)
Expect(err).NotTo(HaveOccurred(), buffer.String())

Expect(cdxOutput.BOMFormat).To(Equal("CycloneDX"), buffer.String())
Expect(cdxOutput.SpecVersion).To(Equal("1.3"), buffer.String())
Expect(cdxOutput.SerialNumber).To(Equal(""), buffer.String())

Expect(cdxOutput.Metadata.Timestamp).To(Equal(""), buffer.String())
Expect(cdxOutput.Metadata.Component.Type).To(Equal("file"), buffer.String())
Expect(cdxOutput.Metadata.Component.Type).To(Equal("file"), buffer.String())
Expect(cdxOutput.Metadata.Component.Name).To(Equal("testdata/"), buffer.String())
Expect(cdxOutput.Components[0].Name).To(Equal("collapse-white-space"), buffer.String())
Expand All @@ -55,14 +61,19 @@ func testFormattedReader(t *testing.T, context spec.G, it spec.S) {
_, err := io.Copy(buffer, sbom.NewFormattedReader(bom, sbom.Format(syft.CycloneDxJSONFormatID)))
Expect(err).NotTo(HaveOccurred())

format := syft.IdentifyFormat(buffer.Bytes())
Expect(format.ID()).To(Equal(syft.CycloneDxJSONFormatID))

var cdxOutput cdxOutput

err = json.Unmarshal(buffer.Bytes(), &cdxOutput)
Expect(err).NotTo(HaveOccurred(), buffer.String())

Expect(cdxOutput.BOMFormat).To(Equal("CycloneDX"), buffer.String())
Expect(cdxOutput.SpecVersion).To(Equal("1.4"), buffer.String())
Expect(cdxOutput.SerialNumber).To(Equal(""), buffer.String())

Expect(cdxOutput.Metadata.Timestamp).To(Equal(""), buffer.String())
Expect(cdxOutput.Metadata.Component.Type).To(Equal("file"), buffer.String())
Expect(cdxOutput.Metadata.Component.Name).To(Equal("testdata/"), buffer.String())
Expect(cdxOutput.Components[0].Name).To(Equal("collapse-white-space"), buffer.String())
Expand Down
8 changes: 5 additions & 3 deletions sbom/sbom_outputs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ type component struct {
}

type cdxOutput struct {
BOMFormat string `json:"bomFormat"`
SpecVersion string `json:"specVersion"`
Metadata struct {
BOMFormat string `json:"bomFormat"`
SpecVersion string `json:"specVersion"`
SerialNumber string `json:"serialNumber"`
Metadata struct {
Timestamp string `json:"timestamp"`
Component struct {
Type string `json:"type"`
Name string `json:"name"`
Expand Down

0 comments on commit 3b843c5

Please sign in to comment.