Skip to content

Commit

Permalink
spdx: Add converter for index reports
Browse files Browse the repository at this point in the history
Adding a function to be able to convert index reports
into SPDX documents.

Signed-off-by: crozzy <[email protected]>
  • Loading branch information
crozzy committed Apr 1, 2024
1 parent 395b041 commit 60e5597
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 1 deletion.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/quay/zlog v1.1.8
github.com/remind101/migrate v0.0.0-20170729031349-52c1edff7319
github.com/rs/zerolog v1.30.0
github.com/spdx/tools-golang v0.5.3
github.com/ulikunitz/xz v0.5.11
go.opentelemetry.io/otel v1.24.0
go.opentelemetry.io/otel/trace v1.24.0
Expand All @@ -35,6 +36,7 @@ require (
)

require (
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
13 changes: 12 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3Q
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
Expand Down Expand Up @@ -170,15 +172,22 @@ github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXY
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.5.3 h1:ialnHeEYUC4+hkm5vJm4qz2x+oEJbS0mAMFrNXdQraY=
github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/uFZm2NTMhI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
Expand Down Expand Up @@ -290,6 +299,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand All @@ -310,3 +320,4 @@ modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
74 changes: 74 additions & 0 deletions pkg/sbom/spdx/spdx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package spdx

import (
"fmt"
"runtime/debug"
"time"

"github.com/spdx/tools-golang/spdx/v2/common"
spdxtools "github.com/spdx/tools-golang/spdx/v2/v2_3"

"github.com/quay/claircore"
)

func ParseIndexReport(vr *claircore.IndexReport) (*spdxtools.Document, error) {
// Initial metadata
out := &spdxtools.Document{
SPDXVersion: spdxtools.Version,
DataLicense: spdxtools.DataLicense,
SPDXIdentifier: "DOCUMENT",
DocumentName: "SPDX-claircore-" + vr.Hash.String(),
// This would be nice to have but don't know how we'd get context w/o
// having to accept it as an argument.
// DocumentNamespace: "https://clairproject.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301",
CreationInfo: &spdxtools.CreationInfo{
Creators: []common.Creator{
{CreatorType: "Tool", Creator: "Claircore"},
{CreatorType: "Organization", Creator: "Clair"},
},
Created: time.Now().Format("2006-01-02T15:04:05Z"),
},
DocumentComment: fmt.Sprintf("This document was created using claircore (%s).", getVersion()),
}

for _, p := range vr.Packages {
pkgDB := ""
for _, e := range vr.Environments[p.ID] {
if e.PackageDB != "" {
pkgDB = e.PackageDB
}
}
pkg := &spdxtools.Package{
PackageName: p.Name,
PackageSPDXIdentifier: common.ElementID("SPDXRef-" + p.ID),
PackageVersion: p.Version,
PackageFileName: pkgDB,
PackageDownloadLocation: "NOASSERTION",
FilesAnalyzed: true,
}
out.Packages = append(out.Packages, pkg)
}
return out, nil
}

// GetVersion is copied from Clair and can hopefully give some
// context as to which revision of claircore was used.
func getVersion() string {
info, infoOK := debug.ReadBuildInfo()
var core string
if infoOK {
for _, m := range info.Deps {
if m.Path != "github.com/quay/claircore" {
continue

Check warning on line 62 in pkg/sbom/spdx/spdx.go

View check run for this annotation

Codecov / codecov/patch

pkg/sbom/spdx/spdx.go#L61-L62

Added lines #L61 - L62 were not covered by tests
}
core = m.Version
if m.Replace != nil && m.Replace.Version != m.Version {
core = m.Replace.Version

Check warning on line 66 in pkg/sbom/spdx/spdx.go

View check run for this annotation

Codecov / codecov/patch

pkg/sbom/spdx/spdx.go#L64-L66

Added lines #L64 - L66 were not covered by tests
}
}
}
if core == "" {
core = "unknown revision"
}
return core
}
120 changes: 120 additions & 0 deletions pkg/sbom/spdx/spdx_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package spdx

import (
"bytes"
"strings"
"testing"

"github.com/quay/claircore"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/spdx/tools-golang/spdx/v2/common"
spdxtools "github.com/spdx/tools-golang/spdx/v2/v2_3"
"github.com/spdx/tools-golang/tagvalue"
)

func TestParseIndexReport(t *testing.T) {
opts := cmp.Options{
cmp.AllowUnexported(spdxtools.Package{}),
cmpopts.IgnoreFields(spdxtools.CreationInfo{}, "Created"),
}
//ctx := context.Background()
for _, tt := range testIndexReports {
t.Run(tt.name, func(t *testing.T) {

s, err := ParseIndexReport(tt.indexReport)
if err != nil {
t.Fatal(err)
}
w := &bytes.Buffer{}
err = tagvalue.Write(s, w)
if err != nil {
t.Fatal(err)
}
if !cmp.Equal(s, tt.SPDXReport, opts) {
t.Error(cmp.Diff(tt.SPDXReport, s, opts))
}
})
}
}

type testcase struct {
name string
indexReport *claircore.IndexReport
SPDXReport *spdxtools.Document
}

var testIndexReports = []testcase{
{
name: "simple index report",
indexReport: &claircore.IndexReport{
Hash: claircore.MustParseDigest(`sha256:` + strings.Repeat(`a`, 64)),
Packages: map[string]*claircore.Package{
"123": {
ID: "123",
Name: "package A",
Version: "v1.0.0",
},
"456": {
ID: "456",
Name: "package B",
Version: "v2.0.0",
},
},
Environments: map[string][]*claircore.Environment{
"123": {
{
PackageDB: "var/lib/dpkg/status",
IntroducedIn: claircore.MustParseDigest(`sha256:` + strings.Repeat(`b`, 64)),
RepositoryIDs: []string{"11"},
},
},
"456": {
{
PackageDB: "maven:opt/couchbase/lib/cbas/repo/eventstream-1.0.1.jar",
IntroducedIn: claircore.MustParseDigest(`sha256:` + strings.Repeat(`c`, 64)),
RepositoryIDs: []string{"12"},
},
},
},
},
SPDXReport: &spdxtools.Document{
SPDXVersion: "SPDX-2.3",
DataLicense: "CC0-1.0",
SPDXIdentifier: "DOCUMENT",
DocumentName: "SPDX-claircore-sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
DocumentComment: "This document was created using claircore (unknown revision).",
CreationInfo: &spdxtools.CreationInfo{
Creators: []common.Creator{
{
Creator: "Claircore",
CreatorType: "Tool",
},
{
Creator: "Clair",
CreatorType: "Organization",
},
},
},
Packages: []*spdxtools.Package{
{
PackageName: "package A",
PackageSPDXIdentifier: "SPDXRef-123",
PackageVersion: "v1.0.0",
PackageFileName: "var/lib/dpkg/status",
PackageDownloadLocation: "NOASSERTION",
FilesAnalyzed: true,
},
{
PackageName: "package B",
PackageSPDXIdentifier: "SPDXRef-456",
PackageVersion: "v2.0.0",
PackageFileName: "maven:opt/couchbase/lib/cbas/repo/eventstream-1.0.1.jar",
PackageDownloadLocation: "NOASSERTION",
FilesAnalyzed: true,
},
},
},
},
}

0 comments on commit 60e5597

Please sign in to comment.