mirror of
https://github.com/anchore/syft.git
synced 2026-10-31 14:36:33 +01:00
Add RPM file scanning support (#1188)
This commit is contained in:
@@ -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"
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
Package rpmdb provides a concrete Cataloger implementation for RPM "Package" DB files.
|
||||
Package rpm provides a concrete DBCataloger implementation for RPM "Package" DB files
|
||||
and a FileCataloger for RPM files.
|
||||
*/
|
||||
package rpmdb
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
const catalogerName = "rpmdb-cataloger"
|
||||
const dbCatalogerName = "rpm-db-cataloger"
|
||||
|
||||
type Cataloger struct{}
|
||||
type DBCataloger struct{}
|
||||
|
||||
// NewRpmdbCataloger returns a new RPM DB cataloger object.
|
||||
func NewRpmdbCataloger() *Cataloger {
|
||||
return &Cataloger{}
|
||||
func NewRpmdbCataloger() *DBCataloger {
|
||||
return &DBCataloger{}
|
||||
}
|
||||
|
||||
// Name returns a string that uniquely describes a cataloger
|
||||
func (c *Cataloger) Name() string {
|
||||
return catalogerName
|
||||
func (c *DBCataloger) Name() string {
|
||||
return dbCatalogerName
|
||||
}
|
||||
|
||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing rpm db installation.
|
||||
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
func (c *DBCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
fileMatches, err := resolver.FilesByGlob(pkg.RpmDBGlob)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to find rpmdb's by glob: %w", err)
|
||||
@@ -0,0 +1,136 @@
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
rpmdb "github.com/knqyf263/go-rpmdb/pkg"
|
||||
"github.com/sassoftware/go-rpmutils"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
type FileCataloger struct{}
|
||||
|
||||
// NewFileCataloger returns a new RPM file cataloger object.
|
||||
func NewFileCataloger() *FileCataloger {
|
||||
return &FileCataloger{}
|
||||
}
|
||||
|
||||
// Name returns a string that uniquely describes a cataloger
|
||||
func (c *FileCataloger) Name() string {
|
||||
return "rpm-file-cataloger"
|
||||
}
|
||||
|
||||
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing rpm files
|
||||
func (c *FileCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
fileMatches, err := resolver.FilesByGlob("**/*.rpm")
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to find rpm files's by glob: %w", err)
|
||||
}
|
||||
|
||||
var pkgs []pkg.Package
|
||||
for _, location := range fileMatches {
|
||||
contentReader, err := resolver.FileContentsByLocation(location)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rpm, err := rpmutils.ReadRpm(contentReader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
nevra, err := rpm.Header.GetNEVRA()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
licenses, _ := rpm.Header.GetStrings(rpmutils.LICENSE)
|
||||
sourceRpm, _ := rpm.Header.GetString(rpmutils.SOURCERPM)
|
||||
vendor, _ := rpm.Header.GetString(rpmutils.VENDOR)
|
||||
digestAlgorithm := getDigestAlgorithm(rpm.Header)
|
||||
size, _ := rpm.Header.InstalledSize()
|
||||
files, _ := rpm.Header.GetFiles()
|
||||
|
||||
p := pkg.Package{
|
||||
Name: nevra.Name,
|
||||
Version: nevra.Version,
|
||||
FoundBy: c.Name(),
|
||||
Licenses: licenses,
|
||||
Locations: source.NewLocationSet(location),
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: nevra.Name,
|
||||
Version: nevra.Version,
|
||||
Epoch: parseEpoch(nevra.Epoch),
|
||||
Arch: nevra.Arch,
|
||||
Release: nevra.Release,
|
||||
SourceRpm: sourceRpm,
|
||||
Vendor: vendor,
|
||||
License: strings.Join(licenses, " AND "),
|
||||
Size: int(size),
|
||||
Files: mapFiles(files, digestAlgorithm),
|
||||
},
|
||||
}
|
||||
p.SetID()
|
||||
pkgs = append(pkgs, p)
|
||||
|
||||
internal.CloseAndLogError(contentReader, location.VirtualPath)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to catalog rpm file=%+v: %w", location.RealPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil, nil
|
||||
}
|
||||
|
||||
func getDigestAlgorithm(header *rpmutils.RpmHeader) string {
|
||||
digestAlgorithm, _ := header.GetString(rpmutils.FILEDIGESTALGO)
|
||||
if digestAlgorithm != "" {
|
||||
return digestAlgorithm
|
||||
}
|
||||
digestAlgorithms, _ := header.GetUint32s(rpmutils.FILEDIGESTALGO)
|
||||
if len(digestAlgorithms) > 0 {
|
||||
digestAlgo := int(digestAlgorithms[0])
|
||||
return rpmutils.GetFileAlgoName(digestAlgo)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func mapFiles(files []rpmutils.FileInfo, digestAlgorithm string) []pkg.RpmdbFileRecord {
|
||||
var out []pkg.RpmdbFileRecord
|
||||
for _, f := range files {
|
||||
digest := file.Digest{}
|
||||
if f.Digest() != "" {
|
||||
digest = file.Digest{
|
||||
Algorithm: digestAlgorithm,
|
||||
Value: f.Digest(),
|
||||
}
|
||||
}
|
||||
out = append(out, pkg.RpmdbFileRecord{
|
||||
Path: f.Name(),
|
||||
Mode: pkg.RpmdbFileMode(f.Mode()),
|
||||
Size: int(f.Size()),
|
||||
Digest: digest,
|
||||
UserName: f.UserName(),
|
||||
GroupName: f.GroupName(),
|
||||
Flags: rpmdb.FileFlags(f.Flags()).String(),
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func parseEpoch(epoch string) *int {
|
||||
i, err := strconv.Atoi(epoch)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &i
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/go-test/deep"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestParseRpmFiles(t *testing.T) {
|
||||
tests := []struct {
|
||||
fixture string
|
||||
expected map[string]pkg.Package
|
||||
}{
|
||||
{
|
||||
fixture: "test-fixtures/rpms",
|
||||
expected: map[string]pkg.Package{
|
||||
"abc": {
|
||||
Name: "abc",
|
||||
Version: "1.01",
|
||||
Locations: source.NewLocationSet(),
|
||||
FoundBy: "rpm-file-cataloger",
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "abc",
|
||||
Epoch: intRef(0),
|
||||
Arch: "x86_64",
|
||||
Release: "9.hg20160905.el7",
|
||||
Version: "1.01",
|
||||
SourceRpm: "abc-1.01-9.hg20160905.el7.src.rpm",
|
||||
Size: 17396,
|
||||
License: "MIT",
|
||||
Vendor: "Fedora Project",
|
||||
Files: []pkg.RpmdbFileRecord{
|
||||
{"/usr/bin/abc", 33261, 7120, file.Digest{"sha256", "8f8495a65c66762b60afa0c3949d81b275ca6fa0601696caba5af762f455d0b9"}, "root", "root", ""},
|
||||
{"/usr/share/doc/abc-1.01", 16877, 4096, file.Digest{}, "root", "root", ""},
|
||||
{"/usr/share/doc/abc-1.01/readme.md", 33188, 4984, file.Digest{"sha256", "808af8a28391e96ca0d91086789488dda3724fe7c8b2859efd464fb04b94b2d4"}, "root", "root", "d"},
|
||||
{"/usr/share/doc/abc-1.01/readmeaig", 33188, 3324, file.Digest{"sha256", "530ec6175cf7fbeb7b595cbe7a50994429c4e62cae6666fb3a1d5745f3127b19"}, "root", "root", "d"},
|
||||
{"/usr/share/man/man1/abc.1.gz", 33188, 1968, file.Digest{"sha256", "cf2cfe25b29087e60ffd5f31f974a0762172fc2f009704951f12ff750ea77ed6"}, "root", "root", "d"},
|
||||
},
|
||||
},
|
||||
},
|
||||
"zork": {
|
||||
Name: "zork",
|
||||
Version: "1.0.3",
|
||||
Locations: source.NewLocationSet(),
|
||||
FoundBy: "rpm-file-cataloger",
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Licenses: []string{"Public Domain"},
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "zork",
|
||||
Epoch: intRef(0),
|
||||
Arch: "x86_64",
|
||||
Release: "1.el7",
|
||||
Version: "1.0.3",
|
||||
SourceRpm: "zork-1.0.3-1.el7.src.rpm",
|
||||
Size: 262367,
|
||||
License: "Public Domain",
|
||||
Vendor: "Fedora Project",
|
||||
Files: []pkg.RpmdbFileRecord{
|
||||
{"/usr/bin/zork", 33261, 115440, file.Digest{"sha256", "31b2ffc20b676a8fff795a45308f584273b9c47e8f7e196b4f36220b2734b472"}, "root", "root", ""},
|
||||
{"/usr/share/doc/zork-1.0.3", 16877, 38, file.Digest{}, "root", "root", ""},
|
||||
{"/usr/share/doc/zork-1.0.3/README.md", 33188, 5123, file.Digest{"sha256", "0013d67610a80c9f62d151a952f18d520b15b4c505b3ec2af34b96ab824654a4"}, "root", "root", "d"},
|
||||
{"/usr/share/doc/zork-1.0.3/history", 33188, 4816, file.Digest{"sha256", "6949044a65adefca6ac0132c18cfccc4ba8fdaec948424b6ccb60afd8a6ac82f"}, "root", "root", "d"},
|
||||
{"/usr/share/licenses/zork-1.0.3", 16877, 24, file.Digest{}, "root", "root", ""},
|
||||
{"/usr/share/licenses/zork-1.0.3/readme.txt", 33188, 146, file.Digest{"sha256", "9d6f7500555a2ecc3cb289dcca1e37fb96894dab1e4ba692b4d36fd6c3bdf939"}, "root", "root", "l"},
|
||||
{"/usr/share/man/man6/dungeon.6.gz", 33188, 3800, file.Digest{"sha256", "9b065d6a6f65b4d2d038fcca0af47a38e8723c32008d08659739ac34abe018da"}, "root", "root", "d"},
|
||||
{"/usr/share/man/man6/zork.6.gz", 33188, 34, file.Digest{"sha256", "18fbcb598bc40a25befe26256e29366984d2288dd154f877b8ac5fc138dd0884"}, "root", "root", "d"},
|
||||
{"/usr/share/zork/dtextc.dat", 33188, 133008, file.Digest{"sha256", "25ca42857c2b32054916d9258152293ead644023d5e03bec039ea92014e2ef91"}, "root", "root", ""},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.fixture, func(t *testing.T) {
|
||||
s, err := source.NewFromDirectory(test.fixture)
|
||||
require.NoError(t, err)
|
||||
|
||||
r, err := s.FileResolver(source.SquashedScope)
|
||||
require.NoError(t, err)
|
||||
|
||||
packages, _, err := NewFileCataloger().Catalog(r)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, a := range packages {
|
||||
e := test.expected[a.Name]
|
||||
diffs := deep.Equal(e, a)
|
||||
if len(diffs) > 0 {
|
||||
for _, d := range diffs {
|
||||
t.Errorf("diff: %+v", d)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package rpmdb
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -68,7 +68,7 @@ func newPkg(resolver source.FilePathResolver, dbLocation source.Location, entry
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadata := pkg.RpmdbMetadata{
|
||||
metadata := pkg.RpmMetadata{
|
||||
Name: entry.Name,
|
||||
Version: entry.Version,
|
||||
Epoch: entry.Epoch,
|
||||
@@ -86,9 +86,9 @@ func newPkg(resolver source.FilePathResolver, dbLocation source.Location, entry
|
||||
Name: entry.Name,
|
||||
Version: toELVersion(metadata),
|
||||
Locations: source.NewLocationSet(dbLocation),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func newPkg(resolver source.FilePathResolver, dbLocation source.Location, entry
|
||||
// version string, containing epoch (optional), version, and release information. Epoch is an optional field and can be
|
||||
// assumed to be 0 when not provided for comparison purposes, however, if the underlying RPM DB entry does not have
|
||||
// an epoch specified it would be slightly disingenuous to display a value of 0.
|
||||
func toELVersion(metadata pkg.RpmdbMetadata) string {
|
||||
func toELVersion(metadata pkg.RpmMetadata) string {
|
||||
if metadata.Epoch != nil {
|
||||
return fmt.Sprintf("%d:%s-%s", *metadata.Epoch, metadata.Version, metadata.Release)
|
||||
}
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
package rpmdb
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -72,11 +72,11 @@ func TestParseRpmDB(t *testing.T) {
|
||||
Name: "dive",
|
||||
Version: "0.9.2-1",
|
||||
Locations: source.NewLocationSet(dbLocation),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "dive",
|
||||
Epoch: nil,
|
||||
Arch: "x86_64",
|
||||
@@ -100,11 +100,11 @@ func TestParseRpmDB(t *testing.T) {
|
||||
Name: "dive",
|
||||
Version: "0.9.2-1",
|
||||
Locations: source.NewLocationSet(dbLocation),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Licenses: []string{"MIT"},
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "dive",
|
||||
Epoch: nil,
|
||||
Arch: "x86_64",
|
||||
@@ -170,12 +170,12 @@ func TestParseRpmDB(t *testing.T) {
|
||||
func TestToElVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
entry pkg.RpmdbMetadata
|
||||
entry pkg.RpmMetadata
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "no epoch",
|
||||
entry: pkg.RpmdbMetadata{
|
||||
entry: pkg.RpmMetadata{
|
||||
Version: "1.2.3-4",
|
||||
Release: "el7",
|
||||
Arch: "x86-64",
|
||||
@@ -184,7 +184,7 @@ func TestToElVersion(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with 0 epoch",
|
||||
entry: pkg.RpmdbMetadata{
|
||||
entry: pkg.RpmMetadata{
|
||||
Version: "1.2.3-4",
|
||||
Release: "el7",
|
||||
Arch: "x86-64",
|
||||
@@ -194,7 +194,7 @@ func TestToElVersion(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with non-zero epoch",
|
||||
entry: pkg.RpmdbMetadata{
|
||||
entry: pkg.RpmMetadata{
|
||||
Version: "1.2.3-4",
|
||||
Release: "el7",
|
||||
Arch: "x86-64",
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package rpmdb
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -43,7 +43,7 @@ func parseRpmManifestEntry(entry string, location source.Location) (*pkg.Package
|
||||
size = converted
|
||||
}
|
||||
|
||||
metadata := pkg.RpmdbMetadata{
|
||||
metadata := pkg.RpmMetadata{
|
||||
Name: parts[0],
|
||||
Version: version,
|
||||
Epoch: epoch,
|
||||
@@ -58,9 +58,9 @@ func parseRpmManifestEntry(entry string, location source.Location) (*pkg.Package
|
||||
Name: parts[0],
|
||||
Version: toELVersion(metadata),
|
||||
Locations: source.NewLocationSet(location),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
+13
-13
@@ -1,4 +1,4 @@
|
||||
package rpmdb
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -18,10 +18,10 @@ func TestParseRpmManifest(t *testing.T) {
|
||||
Name: "mariner-release",
|
||||
Version: "2.0-12.cm2",
|
||||
Locations: source.NewLocationSet(location),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "mariner-release",
|
||||
Epoch: nil,
|
||||
Arch: "noarch",
|
||||
@@ -36,10 +36,10 @@ func TestParseRpmManifest(t *testing.T) {
|
||||
Name: "filesystem",
|
||||
Version: "1.1-9.cm2",
|
||||
Locations: source.NewLocationSet(location),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "filesystem",
|
||||
Epoch: nil,
|
||||
Arch: "x86_64",
|
||||
@@ -54,10 +54,10 @@ func TestParseRpmManifest(t *testing.T) {
|
||||
Name: "glibc",
|
||||
Version: "2.35-2.cm2",
|
||||
Locations: source.NewLocationSet(location),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "glibc",
|
||||
Epoch: nil,
|
||||
Arch: "x86_64",
|
||||
@@ -72,10 +72,10 @@ func TestParseRpmManifest(t *testing.T) {
|
||||
Name: "openssl-libs",
|
||||
Version: "1.1.1k-15.cm2",
|
||||
Locations: source.NewLocationSet(location),
|
||||
FoundBy: catalogerName,
|
||||
FoundBy: dbCatalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: pkg.RpmdbMetadata{
|
||||
MetadataType: pkg.RpmMetadataType,
|
||||
Metadata: pkg.RpmMetadata{
|
||||
Name: "openssl-libs",
|
||||
Epoch: nil,
|
||||
Arch: "x86_64",
|
||||
@@ -0,0 +1,2 @@
|
||||
/rpms/*
|
||||
*.fingerprint
|
||||
@@ -0,0 +1,21 @@
|
||||
RPMSDIR=rpms
|
||||
|
||||
ifndef RPMSDIR
|
||||
$(error RPMSDIR is not set)
|
||||
endif
|
||||
|
||||
all: rpms
|
||||
|
||||
clean:
|
||||
rm -rf $(RPMSDIR)
|
||||
|
||||
rpms:
|
||||
mkdir -p $(RPMSDIR)
|
||||
cd $(RPMSDIR) && curl https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/a/abc-1.01-9.hg20160905.el7.x86_64.rpm -O
|
||||
cd $(RPMSDIR) && curl https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/z/zork-1.0.3-1.el7.x86_64.rpm -O
|
||||
|
||||
# we need a way to determine if CI should bust the test cache based on the source material
|
||||
.PHONY: $(RPMSDIR).fingerprint
|
||||
$(RPMSDIR).fingerprint:
|
||||
find Makefile -type f -exec sha256sum {} \; | sort | tee /dev/stderr | tee $(RPMSDIR).fingerprint
|
||||
sha256sum $(RPMSDIR).fingerprint
|
||||
+10
-3
@@ -17,7 +17,7 @@ const (
|
||||
GemMetadataType MetadataType = "GemMetadata"
|
||||
JavaMetadataType MetadataType = "JavaMetadata"
|
||||
NpmPackageJSONMetadataType MetadataType = "NpmPackageJsonMetadata"
|
||||
RpmdbMetadataType MetadataType = "RpmdbMetadata"
|
||||
RpmMetadataType MetadataType = "RpmMetadata"
|
||||
DartPubMetadataType MetadataType = "DartPubMetadata"
|
||||
DotnetDepsMetadataType MetadataType = "DotnetDepsMetadata"
|
||||
PythonPackageMetadataType MetadataType = "PythonPackageMetadata"
|
||||
@@ -38,7 +38,7 @@ var AllMetadataTypes = []MetadataType{
|
||||
GemMetadataType,
|
||||
JavaMetadataType,
|
||||
NpmPackageJSONMetadataType,
|
||||
RpmdbMetadataType,
|
||||
RpmMetadataType,
|
||||
DartPubMetadataType,
|
||||
DotnetDepsMetadataType,
|
||||
PythonPackageMetadataType,
|
||||
@@ -59,7 +59,7 @@ var MetadataTypeByName = map[MetadataType]reflect.Type{
|
||||
GemMetadataType: reflect.TypeOf(GemMetadata{}),
|
||||
JavaMetadataType: reflect.TypeOf(JavaMetadata{}),
|
||||
NpmPackageJSONMetadataType: reflect.TypeOf(NpmPackageJSONMetadata{}),
|
||||
RpmdbMetadataType: reflect.TypeOf(RpmdbMetadata{}),
|
||||
RpmMetadataType: reflect.TypeOf(RpmMetadata{}),
|
||||
DartPubMetadataType: reflect.TypeOf(DartPubMetadata{}),
|
||||
DotnetDepsMetadataType: reflect.TypeOf(DotnetDepsMetadata{}),
|
||||
PythonPackageMetadataType: reflect.TypeOf(PythonPackageMetadata{}),
|
||||
@@ -72,3 +72,10 @@ var MetadataTypeByName = map[MetadataType]reflect.Type{
|
||||
PortageMetadataType: reflect.TypeOf(PortageMetadata{}),
|
||||
HackageMetadataType: reflect.TypeOf(HackageMetadata{}),
|
||||
}
|
||||
|
||||
func CleanMetadataType(typ MetadataType) MetadataType {
|
||||
if typ == "RpmdbMetadata" {
|
||||
return RpmMetadataType
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ func TestOwnershipByFilesRelationship(t *testing.T) {
|
||||
source.NewVirtualLocation("/b/path", "/bee/path"),
|
||||
),
|
||||
Type: RpmPkg,
|
||||
MetadataType: RpmdbMetadataType,
|
||||
Metadata: RpmdbMetadata{
|
||||
MetadataType: RpmMetadataType,
|
||||
Metadata: RpmMetadata{
|
||||
Files: []RpmdbFileRecord{
|
||||
{Path: "/owning/path/1"},
|
||||
{Path: "/owning/path/2"},
|
||||
@@ -66,8 +66,8 @@ func TestOwnershipByFilesRelationship(t *testing.T) {
|
||||
source.NewVirtualLocation("/b/path", "/bee/path"),
|
||||
),
|
||||
Type: RpmPkg,
|
||||
MetadataType: RpmdbMetadataType,
|
||||
Metadata: RpmdbMetadata{
|
||||
MetadataType: RpmMetadataType,
|
||||
Metadata: RpmMetadata{
|
||||
Files: []RpmdbFileRecord{
|
||||
{Path: "/owning/path/1"},
|
||||
{Path: "/owning/path/2"},
|
||||
@@ -108,8 +108,8 @@ func TestOwnershipByFilesRelationship(t *testing.T) {
|
||||
source.NewVirtualLocation("/b/path", "/bee/path"),
|
||||
),
|
||||
Type: RpmPkg,
|
||||
MetadataType: RpmdbMetadataType,
|
||||
Metadata: RpmdbMetadata{
|
||||
MetadataType: RpmMetadataType,
|
||||
Metadata: RpmMetadata{
|
||||
Files: []RpmdbFileRecord{
|
||||
{Path: "/owning/path/1"},
|
||||
{Path: "/owning/path/2"},
|
||||
|
||||
@@ -20,12 +20,12 @@ const RpmDBGlob = "**/var/lib/rpm/{Packages,Packages.db,rpmdb.sqlite}"
|
||||
const RpmManifestGlob = "**/var/lib/rpmmanifest/container-manifest-2"
|
||||
|
||||
var (
|
||||
_ FileOwner = (*RpmdbMetadata)(nil)
|
||||
_ urlIdentifier = (*RpmdbMetadata)(nil)
|
||||
_ FileOwner = (*RpmMetadata)(nil)
|
||||
_ urlIdentifier = (*RpmMetadata)(nil)
|
||||
)
|
||||
|
||||
// RpmdbMetadata represents all captured data for a RPM DB package entry.
|
||||
type RpmdbMetadata struct {
|
||||
// RpmMetadata represents all captured data for a RPM DB package entry.
|
||||
type RpmMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Epoch *int `json:"epoch" cyclonedx:"epoch" jsonschema:"nullable"`
|
||||
@@ -54,7 +54,7 @@ type RpmdbFileRecord struct {
|
||||
type RpmdbFileMode uint16
|
||||
|
||||
// PackageURL returns the PURL for the specific RHEL package (see https://github.com/package-url/purl-spec)
|
||||
func (m RpmdbMetadata) PackageURL(distro *linux.Release) string {
|
||||
func (m RpmMetadata) PackageURL(distro *linux.Release) string {
|
||||
var namespace string
|
||||
if distro != nil {
|
||||
namespace = distro.ID
|
||||
@@ -87,7 +87,7 @@ func (m RpmdbMetadata) PackageURL(distro *linux.Release) string {
|
||||
).ToString()
|
||||
}
|
||||
|
||||
func (m RpmdbMetadata) OwnedFiles() (result []string) {
|
||||
func (m RpmMetadata) OwnedFiles() (result []string) {
|
||||
s := strset.New()
|
||||
for _, f := range m.Files {
|
||||
if f.Path != "" {
|
||||
@@ -14,7 +14,7 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
distro *linux.Release
|
||||
metadata RpmdbMetadata
|
||||
metadata RpmMetadata
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
@@ -23,7 +23,7 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
ID: "rhel",
|
||||
VersionID: "8.4",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
@@ -37,7 +37,7 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
ID: "centos",
|
||||
VersionID: "7",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Arch: "a",
|
||||
@@ -48,7 +48,7 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "missing distro",
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
@@ -62,7 +62,7 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
ID: "rhel",
|
||||
VersionID: "8.4",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
@@ -86,11 +86,11 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
|
||||
func TestRpmMetadata_FileOwner(t *testing.T) {
|
||||
tests := []struct {
|
||||
metadata RpmdbMetadata
|
||||
metadata RpmMetadata
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Files: []RpmdbFileRecord{
|
||||
{Path: "/somewhere"},
|
||||
{Path: "/else"},
|
||||
@@ -102,7 +102,7 @@ func TestRpmMetadata_FileOwner(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
metadata: RpmdbMetadata{
|
||||
metadata: RpmMetadata{
|
||||
Files: []RpmdbFileRecord{
|
||||
{Path: "/somewhere"},
|
||||
{Path: ""},
|
||||
@@ -121,7 +121,7 @@ func TestPackageURL(t *testing.T) {
|
||||
Name: "bad-name",
|
||||
Version: "bad-v0.1.0",
|
||||
Type: RpmPkg,
|
||||
Metadata: RpmdbMetadata{
|
||||
Metadata: RpmMetadata{
|
||||
Name: "name",
|
||||
Version: "0.1.0",
|
||||
Epoch: intRef(2),
|
||||
|
||||
Reference in New Issue
Block a user