Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RPM file scanning support #1188

Merged
merged 11 commits into from
Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/cache@v2.1.3
with:
path: syft/pkg/cataloger/rpm/test-fixtures/rpms
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/rpm/test-fixtures/rpms.fingerprint' ) }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be simplified to just hash the Makefile, I've left it this way for consistency


- 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/logback-classic@1.2.3",
Type: "library",
BOMRef: "pkg:maven/ch.qos.logback/logback-classic@1.2.3",
}

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/logback-classic@1.2.3",
Type: "library",
BOMRef: "pkg:maven/ch.qos.logback/logback-classic@1.2.3",
},
wantLanguage: pkg.Java,
},
{
name: "handle existing RpmdbMetadata type",
component: cyclonedx.Component{
Name: "acl",
Version: "2.2.53-1.el8",
PackageURL: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=x86_64&upstream=acl-2.2.53-1.el8.src.rpm&distro=centos-8",
Type: "library",
BOMRef: "pkg:rpm/centos/acl@2.2.53-1.el8?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/go-jose.v2@v2.6.0"
}`),
},
{
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/acl@2.2.53-1.el8?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