Skip to content

Commit

Permalink
Add RPM file scanning support (#1188)
Browse files Browse the repository at this point in the history
  • Loading branch information
kzantow authored Sep 7, 2022
1 parent 1c7b7c5 commit 70db13d
Show file tree
Hide file tree
Showing 37 changed files with 470 additions and 108 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/validations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ jobs:
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/packages.fingerprint' ) }}

- name: Build cache key for rpm test-fixture blobs (for unit tests)
run: make rpm-binaries-fingerprint

- name: Restore RPM test-fixture cache
id: unit-rpm-cache
uses: actions/[email protected]
with:
path: syft/pkg/cataloger/rpm/test-fixtures/rpms
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/rpm/test-fixtures/rpms.fingerprint' ) }}

- name: Build cache key for go binary test-fixture blobs (for unit tests)
run: make go-binaries-fingerprint

Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,17 @@ go-binaries-fingerprint:
cd syft/pkg/cataloger/golang/test-fixtures/archs && \
make binaries.fingerprint

.PHONY: rpm-binaries-fingerprint
rpm-binaries-fingerprint:
$(call title,RPM binary test fixture fingerprint)
cd syft/pkg/cataloger/rpm/test-fixtures && \
make rpms.fingerprint

.PHONY: fixtures
fixtures:
$(call title,Generating test fixtures)
cd syft/pkg/cataloger/java/test-fixtures/java-builds && make
cd syft/pkg/cataloger/rpm/test-fixtures && make

.PHONY: generate-json-schema
generate-json-schema: ## Generate a new json schema
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ require (
github.com/google/go-containerregistry v0.11.0
github.com/in-toto/in-toto-golang v0.3.4-0.20220709202702-fa494aaa0add
github.com/knqyf263/go-rpmdb v0.0.0-20220629110411-9a3bd2ebb923
github.com/sassoftware/go-rpmutils v0.2.0
github.com/sigstore/cosign v1.11.1
github.com/sigstore/rekor v0.11.0
github.com/sigstore/sigstore v1.4.0
Expand All @@ -79,6 +80,7 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/DataDog/zstd v1.4.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Microsoft/go-winio v0.5.2 // indirect
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CycloneDX/cyclonedx-go v0.5.2 h1:CkdGw2R/tZWmEbSypJVZG+3+2SAsDjJirfIrG/RbIVg=
github.com/CycloneDX/cyclonedx-go v0.5.2/go.mod h1:nQCiF4Tvrg5Ieu8qPhYMvzPGMu5I7fANZkrSsJjl5mg=
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
Expand Down Expand Up @@ -1190,6 +1192,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
Expand Down Expand Up @@ -1611,6 +1614,8 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI=
github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
github.com/sassoftware/go-rpmutils v0.1.1/go.mod h1:euhXULoBpvAxqrBHEyJS4Tsu3hHxUmQWNymxoJbzgUY=
github.com/sassoftware/go-rpmutils v0.2.0 h1:pKW0HDYMFWQ5b4JQPiI3WI12hGsVoW0V8+GMoZiI/JE=
github.com/sassoftware/go-rpmutils v0.2.0/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI=
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 h1:sUNzanSKA9z/h8xXl+ZJoxIYZL0Qx306MmxqRrvUgr0=
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74/go.mod h1:YlB8wFIZmFLZ1JllNBfSURzz52fBxbliNgYALk1UDmk=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
Expand Down
2 changes: 2 additions & 0 deletions internal/formats/common/cyclonedxhelpers/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ func decodeComponent(c *cyclonedx.Component) *pkg.Package {

common.DecodeInto(p, values, "syft:package", CycloneDXFields)

p.MetadataType = pkg.CleanMetadataType(p.MetadataType)

p.Metadata = decodePackageMetadata(values, c, p.MetadataType)

if p.Type == "" {
Expand Down
58 changes: 40 additions & 18 deletions internal/formats/common/cyclonedxhelpers/component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ func Test_encodeComponentProperties(t *testing.T) {
Name: "dive",
Version: "0.9.2-1",
Type: pkg.RpmPkg,
MetadataType: pkg.RpmdbMetadataType,
Metadata: pkg.RpmdbMetadata{
MetadataType: pkg.RpmMetadataType,
Metadata: pkg.RpmMetadata{
Name: "dive",
Epoch: &epoch,
Arch: "x86_64",
Expand All @@ -124,7 +124,7 @@ func Test_encodeComponentProperties(t *testing.T) {
},
},
expected: &[]cyclonedx.Property{
{Name: "syft:package:metadataType", Value: "RpmdbMetadata"},
{Name: "syft:package:metadataType", Value: "RpmMetadata"},
{Name: "syft:package:type", Value: "rpm"},
{Name: "syft:metadata:epoch", Value: "2"},
{Name: "syft:metadata:release", Value: "1"},
Expand Down Expand Up @@ -193,29 +193,51 @@ func Test_deriveBomRef(t *testing.T) {
}

func Test_decodeComponent(t *testing.T) {
javaComponentWithNoSyftProperties := cyclonedx.Component{
Name: "ch.qos.logback/logback-classic",
Version: "1.2.3",
PackageURL: "pkg:maven/ch.qos.logback/[email protected]",
Type: "library",
BOMRef: "pkg:maven/ch.qos.logback/[email protected]",
}

tests := []struct {
name string
component cyclonedx.Component
want pkg.Language
name string
component cyclonedx.Component
wantLanguage pkg.Language
wantMetadataType pkg.MetadataType
}{
{
name: "derive language from pURL if missing",
component: javaComponentWithNoSyftProperties,
want: pkg.Java,
name: "derive language from pURL if missing",
component: cyclonedx.Component{
Name: "ch.qos.logback/logback-classic",
Version: "1.2.3",
PackageURL: "pkg:maven/ch.qos.logback/[email protected]",
Type: "library",
BOMRef: "pkg:maven/ch.qos.logback/[email protected]",
},
wantLanguage: pkg.Java,
},
{
name: "handle existing RpmdbMetadata type",
component: cyclonedx.Component{
Name: "acl",
Version: "2.2.53-1.el8",
PackageURL: "pkg:rpm/centos/[email protected]?arch=x86_64&upstream=acl-2.2.53-1.el8.src.rpm&distro=centos-8",
Type: "library",
BOMRef: "pkg:rpm/centos/[email protected]?arch=x86_64&upstream=acl-2.2.53-1.el8.src.rpm&distro=centos-8",
Properties: &[]cyclonedx.Property{
{
Name: "syft:package:metadataType",
Value: "RpmdbMetadata",
},
},
},
wantMetadataType: pkg.RpmMetadataType,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, decodeComponent(&tt.component).Language)
p := decodeComponent(&tt.component)
if tt.wantLanguage != "" {
assert.Equal(t, tt.wantLanguage, p.Language)
}
if tt.wantMetadataType != "" {
assert.Equal(t, tt.wantMetadataType, p.MetadataType)
}
})
}
}
4 changes: 2 additions & 2 deletions internal/formats/common/cyclonedxhelpers/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ func encodePublisher(p pkg.Package) string {
switch metadata := p.Metadata.(type) {
case pkg.ApkMetadata:
return metadata.Maintainer
case pkg.RpmdbMetadata:
case pkg.RpmMetadata:
return metadata.Vendor
case pkg.DpkgMetadata:
return metadata.Maintainer
Expand All @@ -22,7 +22,7 @@ func decodePublisher(publisher string, metadata interface{}) {
switch meta := metadata.(type) {
case *pkg.ApkMetadata:
meta.Maintainer = publisher
case *pkg.RpmdbMetadata:
case *pkg.RpmMetadata:
meta.Vendor = publisher
case *pkg.DpkgMetadata:
meta.Maintainer = publisher
Expand Down
2 changes: 1 addition & 1 deletion internal/formats/common/cyclonedxhelpers/publisher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func Test_encodePublisher(t *testing.T) {
{
name: "from rpm",
input: pkg.Package{
Metadata: pkg.RpmdbMetadata{
Metadata: pkg.RpmMetadata{
Vendor: "auth",
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/formats/common/spdxhelpers/originator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func Test_Originator(t *testing.T) {
{
name: "from rpm",
input: pkg.Package{
Metadata: pkg.RpmdbMetadata{
Metadata: pkg.RpmMetadata{
Vendor: "auth",
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/formats/common/spdxhelpers/origintor.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func Originator(p pkg.Package) string {
if len(metadata.Authors) > 0 {
author = metadata.Authors[0]
}
case pkg.RpmdbMetadata:
case pkg.RpmMetadata:
return "Organization: " + metadata.Vendor
case pkg.DpkgMetadata:
author = metadata.Maintainer
Expand Down
2 changes: 1 addition & 1 deletion internal/formats/common/spdxhelpers/to_syft_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ func extractMetadata(p *spdx.Package2_2, info pkgInfo) (pkg.MetadataType, interf
if license == "" {
license = p.PackageLicenseConcluded
}
return pkg.RpmdbMetadataType, pkg.RpmdbMetadata{
return pkg.RpmMetadataType, pkg.RpmMetadata{
Name: p.PackageName,
Version: p.PackageVersion,
Epoch: epoch,
Expand Down
4 changes: 2 additions & 2 deletions internal/formats/common/spdxhelpers/to_syft_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ func Test_extractMetadata(t *testing.T) {
},
},
},
metaType: pkg.RpmdbMetadataType,
meta: pkg.RpmdbMetadata{
metaType: pkg.RpmMetadataType,
meta: pkg.RpmMetadata{
Name: "SomeRpmPkg",
Version: "13.2.79",
Epoch: &oneTwoThreeFour,
Expand Down
7 changes: 4 additions & 3 deletions internal/formats/syftjson/model/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ func (p *Package) UnmarshalJSON(b []byte) error {

//nolint:funlen,gocognit,gocyclo
func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
p.MetadataType = unpacker.MetadataType
p.MetadataType = pkg.CleanMetadataType(unpacker.MetadataType)

switch p.MetadataType {
case "":
// there is no metadata, skip
Expand All @@ -91,8 +92,8 @@ func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
return err
}
p.Metadata = payload
case pkg.RpmdbMetadataType:
var payload pkg.RpmdbMetadata
case pkg.RpmMetadataType:
var payload pkg.RpmMetadata
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
return err
}
Expand Down
39 changes: 39 additions & 0 deletions internal/formats/syftjson/model/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,45 @@ func Test_unpackMetadata(t *testing.T) {
"purl": "pkg:golang/gopkg.in/square/[email protected]"
}`),
},
{
name: "can handle RpmdbMetadata",
metadataType: pkg.RpmMetadataType,
packageData: []byte(`{
"id": "4ac699c3b8fe1835",
"name": "acl",
"version": "2.2.53-1.el8",
"type": "rpm",
"foundBy": "rpm-db-cataloger",
"locations": [
{
"path": "/var/lib/rpm/Packages",
"layerID": "sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59"
}
],
"licenses": [
"GPLv2+"
],
"language": "",
"cpes": [
"cpe:2.3:a:centos:acl:2.2.53-1.el8:*:*:*:*:*:*:*",
"cpe:2.3:a:acl:acl:2.2.53-1.el8:*:*:*:*:*:*:*"
],
"purl": "pkg:rpm/centos/[email protected]?arch=x86_64&upstream=acl-2.2.53-1.el8.src.rpm&distro=centos-8",
"metadataType": "RpmdbMetadata",
"metadata": {
"name": "acl",
"version": "2.2.53",
"epoch": null,
"architecture": "x86_64",
"release": "1.el8",
"sourceRpm": "acl-2.2.53-1.el8.src.rpm",
"size": 205740,
"license": "GPLv2+",
"vendor": "CentOS",
"modularityLabel": ""
}
}`),
},
{
name: "bad metadata type is an error",
metadataType: "BOGOSITY",
Expand Down
2 changes: 1 addition & 1 deletion schema/json/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type artifactMetadataContainer struct {
Java pkg.JavaMetadata
Npm pkg.NpmPackageJSONMetadata
Python pkg.PythonPackageMetadata
Rpm pkg.RpmdbMetadata
Rpm pkg.RpmMetadata
Cargo pkg.CargoPackageMetadata
Go pkg.GolangBinMetadata
Php pkg.PhpComposerJSONMetadata
Expand Down
10 changes: 6 additions & 4 deletions syft/pkg/cataloger/cataloger.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/php"
"github.com/anchore/syft/syft/pkg/cataloger/portage"
"github.com/anchore/syft/syft/pkg/cataloger/python"
"github.com/anchore/syft/syft/pkg/cataloger/rpmdb"
"github.com/anchore/syft/syft/pkg/cataloger/rpm"
"github.com/anchore/syft/syft/pkg/cataloger/ruby"
"github.com/anchore/syft/syft/pkg/cataloger/rust"
"github.com/anchore/syft/syft/pkg/cataloger/swift"
Expand Down Expand Up @@ -52,7 +52,7 @@ func ImageCatalogers(cfg Config) []Cataloger {
php.NewPHPComposerInstalledCataloger(),
javascript.NewJavascriptPackageCataloger(),
deb.NewDpkgdbCataloger(),
rpmdb.NewRpmdbCataloger(),
rpm.NewRpmdbCataloger(),
java.NewJavaCataloger(cfg.Java()),
apkdb.NewApkdbCataloger(),
golang.NewGoModuleBinaryCataloger(),
Expand All @@ -71,7 +71,8 @@ func DirectoryCatalogers(cfg Config) []Cataloger {
php.NewPHPComposerLockCataloger(),
javascript.NewJavascriptLockCataloger(),
deb.NewDpkgdbCataloger(),
rpmdb.NewRpmdbCataloger(),
rpm.NewRpmdbCataloger(),
rpm.NewFileCataloger(),
java.NewJavaCataloger(cfg.Java()),
java.NewJavaPomCataloger(),
apkdb.NewApkdbCataloger(),
Expand All @@ -98,7 +99,8 @@ func AllCatalogers(cfg Config) []Cataloger {
javascript.NewJavascriptLockCataloger(),
javascript.NewJavascriptPackageCataloger(),
deb.NewDpkgdbCataloger(),
rpmdb.NewRpmdbCataloger(),
rpm.NewRpmdbCataloger(),
rpm.NewFileCataloger(),
java.NewJavaCataloger(cfg.Java()),
java.NewJavaPomCataloger(),
apkdb.NewApkdbCataloger(),
Expand Down
2 changes: 1 addition & 1 deletion syft/pkg/cataloger/common/cpe/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func candidateVendors(p pkg.Package) []string {
}

switch p.MetadataType {
case pkg.RpmdbMetadataType:
case pkg.RpmMetadataType:
vendors.union(candidateVendorsForRPM(p))
case pkg.GemMetadataType:
vendors.union(candidateVendorsForRuby(p))
Expand Down
8 changes: 4 additions & 4 deletions syft/pkg/cataloger/common/cpe/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,8 @@ func TestGeneratePackageCPEs(t *testing.T) {
Version: "3.2",
FoundBy: "some-analyzer",
Type: pkg.RpmPkg,
MetadataType: pkg.RpmdbMetadataType,
Metadata: pkg.RpmdbMetadata{
MetadataType: pkg.RpmMetadataType,
Metadata: pkg.RpmMetadata{
Vendor: "some-vendor",
},
},
Expand All @@ -334,8 +334,8 @@ func TestGeneratePackageCPEs(t *testing.T) {
Version: "1:3.2",
FoundBy: "some-analyzer",
Type: pkg.RpmPkg,
MetadataType: pkg.RpmdbMetadataType,
Metadata: pkg.RpmdbMetadata{
MetadataType: pkg.RpmMetadataType,
Metadata: pkg.RpmMetadata{
Vendor: "some-vendor",
},
},
Expand Down
2 changes: 1 addition & 1 deletion syft/pkg/cataloger/common/cpe/rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package cpe
import "github.com/anchore/syft/syft/pkg"

func candidateVendorsForRPM(p pkg.Package) fieldCandidateSet {
metadata, ok := p.Metadata.(pkg.RpmdbMetadata)
metadata, ok := p.Metadata.(pkg.RpmMetadata)
if !ok {
return nil
}
Expand Down
Loading

0 comments on commit 70db13d

Please sign in to comment.