Skip to content

Commit

Permalink
add CPEs to buildpack.toml dependency schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Frankie Gallina-Jones authored and ForestEckhardt committed Aug 8, 2022
1 parent 444cccb commit c773010
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
7 changes: 6 additions & 1 deletion postal/buildpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import (

// Dependency is a representation of a buildpack dependency.
type Dependency struct {
// CPE is the Common Platform Enumerator for the dependency.
// CPE is the Common Platform Enumerator for the dependency. Used in legacy
// image label SBOM (GenerateBillOfMaterials).
CPE string `toml:"cpe"`

// CPEs are the Common Platform Enumerators for the dependency. Used in Syft
// and SPDX JSON SBOMs. If unset, falls back to CPE.
CPEs []string `toml:"cpes"`

// DeprecationDate is the data upon which this dependency is considered deprecated.
DeprecationDate time.Time `toml:"deprecation_date"`

Expand Down
42 changes: 42 additions & 0 deletions postal/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,48 @@ version = "this is super not semver"
},
}))
})
context("and there are CPEs", func() {
it("uses CPE, ignores CPEs, for backward compatibility", func() {
entries := service.GenerateBillOfMaterials(
postal.Dependency{
CPE: "some-cpe",
CPEs: []string{"some-other-cpe"},
ID: "some-entry",
Name: "Some Entry",
SHA256: "some-sha",
Source: "some-source",
SourceSHA256: "some-source-sha",
Stacks: []string{"some-stack"},
URI: "some-uri",
Version: "1.2.3",
},
)

Expect(entries).To(Equal([]packit.BOMEntry{
{
Name: "Some Entry",
Metadata: paketosbom.BOMMetadata{
CPE: "some-cpe",
Checksum: paketosbom.BOMChecksum{
Algorithm: paketosbom.SHA256,
Hash: "some-sha",
},
Source: paketosbom.BOMSource{
Checksum: paketosbom.BOMChecksum{
Algorithm: paketosbom.SHA256,
Hash: "some-source-sha",
},
URI: "some-source",
},

URI: "some-uri",
Version: "1.2.3",
},
},
}))
})

})
})

context("when there is a deprecation date", func() {
Expand Down
15 changes: 11 additions & 4 deletions sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,24 @@ func GenerateFromDependency(dependency postal.Dependency, path string) (SBOM, er
if dependency.CPE == "" {
dependency.CPE = UnknownCPE
}
if len(dependency.CPEs) == 0 {
dependency.CPEs = []string{dependency.CPE}
}

cpe, err := pkg.NewCPE(dependency.CPE)
if err != nil {
return SBOM{}, err
var cpes []pkg.CPE
for _, cpeString := range dependency.CPEs {
cpe, err := pkg.NewCPE(cpeString)
if err != nil {
return SBOM{}, err
}
cpes = append(cpes, cpe)
}

catalog := pkg.NewCatalog(pkg.Package{
Name: dependency.Name,
Version: dependency.Version,
Licenses: dependency.Licenses,
CPEs: []pkg.CPE{cpe},
CPEs: cpes,
PURL: dependency.PURL,
})

Expand Down
49 changes: 49 additions & 0 deletions sbom/sbom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,55 @@ func testSBOM(t *testing.T, context spec.G, it spec.S) {
}}), spdx.String())
})
})
context("when the input dependency has CPEs and CPE", func() {
it("uses CPEs, not CPE", func() {
bom, err := sbom.GenerateFromDependency(postal.Dependency{
CPE: "cpe:2.3:a:golang:go:1.16.9:*:*:*:*:*:*:*",
CPEs: []string{"cpe:2.3:a:some:other:cpe:*:*:*:*:*:*:*", "cpe:2.3:a:another:cpe:to:include:*:*:*:*:*:*"},
ID: "go",
Licenses: []string{"BSD-3-Clause"},
Name: "Go",
SHA256: "ca9ef23a5db944b116102b87c1ae9344b27e011dae7157d2f1e501abd39e9829",
Source: "https://dl.google.com/go/go1.16.9.src.tar.gz",
SourceSHA256: "0a1cc7fd7bd20448f71ebed64d846138850d5099b18cf5cc10a4fc45160d8c3d",
Stacks: []string{"io.buildpacks.stacks.bionic", "io.paketo.stacks.tiny"},
URI: "https://deps.paketo.io/go/go_go1.16.9_linux_x64_bionic_ca9ef23a.tgz",
Version: "1.16.9",
}, "some-path")
Expect(err).NotTo(HaveOccurred())

formatter, err := bom.InFormats(sbom.SyftFormat, sbom.CycloneDXFormat, sbom.SPDXFormat)
Expect(err).NotTo(HaveOccurred())

formats := formatter.Formats()

syft := bytes.NewBuffer(nil)
for _, format := range formats {
if format.Extension == "syft.json" {
_, err = io.Copy(syft, format.Content)
Expect(err).NotTo(HaveOccurred())
}
}

var syftDefaultOutput syftOutput
err = json.NewDecoder(syft).Decode(&syftDefaultOutput)
Expect(err).NotTo(HaveOccurred(), syft.String())

Expect(syftDefaultOutput.Schema.Version).To(Equal(`3.0.1`), syft.String())

goArtifact := syftDefaultOutput.Artifacts[0]
Expect(goArtifact.Name).To(Equal("Go"), syft.String())
Expect(goArtifact.Version).To(Equal("1.16.9"), syft.String())
Expect(goArtifact.Licenses).To(Equal([]string{"BSD-3-Clause"}), syft.String())
Expect(syftDefaultOutput.Source.Type).To(Equal("directory"), syft.String())
Expect(syftDefaultOutput.Source.Target).To(Equal("some-path"), syft.String())
Expect(goArtifact.PURL).To(BeEmpty())
Expect(goArtifact.CPEs).To(Equal([]string{
"cpe:2.3:a:some:other:cpe:*:*:*:*:*:*:*",
"cpe:2.3:a:another:cpe:to:include:*:*:*:*:*:*",
}))
})
})

context("failure cases", func() {
context("when the CPE is invalid", func() {
Expand Down

0 comments on commit c773010

Please sign in to comment.