mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 23:16:30 +01:00
Support RPM distros with newer RPM db formats (#1018)
* Support RPM distros with newer db formats Recent RPM distros (Fedora 33+, CBL-Mariner 2.0+, amazonlinux 2022+) use an sqlite package database in /var/lib/rpm/rpmdb.sqlite, or "ndb" format (SUSE). Remove anchore's fork in favour of the upstream, https://github.com/knqyf263/go-rpmdb, to gain support for these formats. Signed-off-by: Tom Fay <tomfay@microsoft.com> * add exception for modernc.org repos Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * shorten rpmdb helper function Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Co-authored-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
@@ -6,13 +6,12 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
|
||||
rpmdb "github.com/anchore/go-rpmdb/pkg"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
rpmdb "github.com/knqyf263/go-rpmdb/pkg"
|
||||
)
|
||||
|
||||
// parseApkDb parses an "Packages" RPM DB and returns the Packages listed within it.
|
||||
@@ -47,37 +46,49 @@ func parseRpmDB(resolver source.FilePathResolver, dbLocation source.Location, re
|
||||
allPkgs := make([]pkg.Package, 0)
|
||||
|
||||
for _, entry := range pkgList {
|
||||
metadata := pkg.RpmdbMetadata{
|
||||
Name: entry.Name,
|
||||
Version: entry.Version,
|
||||
Epoch: entry.Epoch,
|
||||
Arch: entry.Arch,
|
||||
Release: entry.Release,
|
||||
SourceRpm: entry.SourceRpm,
|
||||
Vendor: entry.Vendor,
|
||||
License: entry.License,
|
||||
Size: entry.Size,
|
||||
Files: extractRpmdbFileRecords(resolver, entry),
|
||||
p, err := newPkg(resolver, dbLocation, entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := pkg.Package{
|
||||
Name: entry.Name,
|
||||
Version: toELVersion(metadata),
|
||||
Locations: source.NewLocationSet(dbLocation),
|
||||
FoundBy: catalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
p.SetID()
|
||||
|
||||
allPkgs = append(allPkgs, p)
|
||||
allPkgs = append(allPkgs, *p)
|
||||
}
|
||||
|
||||
return allPkgs, nil
|
||||
}
|
||||
|
||||
func newPkg(resolver source.FilePathResolver, dbLocation source.Location, entry *rpmdb.PackageInfo) (*pkg.Package, error) {
|
||||
fileRecords, err := extractRpmdbFileRecords(resolver, entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metadata := pkg.RpmdbMetadata{
|
||||
Name: entry.Name,
|
||||
Version: entry.Version,
|
||||
Epoch: entry.Epoch,
|
||||
Arch: entry.Arch,
|
||||
Release: entry.Release,
|
||||
SourceRpm: entry.SourceRpm,
|
||||
Vendor: entry.Vendor,
|
||||
License: entry.License,
|
||||
Size: entry.Size,
|
||||
Files: fileRecords,
|
||||
}
|
||||
|
||||
p := pkg.Package{
|
||||
Name: entry.Name,
|
||||
Version: toELVersion(metadata),
|
||||
Locations: source.NewLocationSet(dbLocation),
|
||||
FoundBy: catalogerName,
|
||||
Type: pkg.RpmPkg,
|
||||
MetadataType: pkg.RpmdbMetadataType,
|
||||
Metadata: metadata,
|
||||
}
|
||||
|
||||
p.SetID()
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
// The RPM naming scheme is [name]-[version]-[release]-[arch], where version is implicitly expands to [epoch]:[version].
|
||||
// RPM version comparison depends on comparing at least the version and release fields together as a subset of the
|
||||
// naming scheme. This toELVersion function takes a RPM DB package information and converts it into a minimally comparable
|
||||
@@ -91,10 +102,15 @@ func toELVersion(metadata pkg.RpmdbMetadata) string {
|
||||
return fmt.Sprintf("%s-%s", metadata.Version, metadata.Release)
|
||||
}
|
||||
|
||||
func extractRpmdbFileRecords(resolver source.FilePathResolver, entry *rpmdb.PackageInfo) []pkg.RpmdbFileRecord {
|
||||
func extractRpmdbFileRecords(resolver source.FilePathResolver, entry *rpmdb.PackageInfo) ([]pkg.RpmdbFileRecord, error) {
|
||||
var records = make([]pkg.RpmdbFileRecord, 0)
|
||||
|
||||
for _, record := range entry.Files {
|
||||
files, err := entry.InstalledFiles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, record := range files {
|
||||
// only persist RPMDB file records which exist in the image/directory, otherwise ignore them
|
||||
if resolver.HasPath(record.Path) {
|
||||
records = append(records, pkg.RpmdbFileRecord{
|
||||
@@ -111,5 +127,5 @@ func extractRpmdbFileRecords(resolver source.FilePathResolver, entry *rpmdb.Pack
|
||||
})
|
||||
}
|
||||
}
|
||||
return records
|
||||
return records, nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,10 @@ import (
|
||||
"github.com/scylladb/go-set/strset"
|
||||
)
|
||||
|
||||
const RpmDBGlob = "**/var/lib/rpm/Packages"
|
||||
// Packages is the legacy Berkely db based format
|
||||
// Packages.db is the "ndb" format used in SUSE
|
||||
// rpmdb.sqlite is the sqlite format used in fedora + derivates
|
||||
const RpmDBGlob = "**/var/lib/rpm/{Packages,Packages.db,rpmdb.sqlite}"
|
||||
|
||||
var (
|
||||
_ FileOwner = (*RpmdbMetadata)(nil)
|
||||
|
||||
Reference in New Issue
Block a user