mirror of
https://github.com/anchore/syft.git
synced 2026-10-12 22:27:22 +02:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51159ce204 | ||
|
|
7c644ea3d1 | ||
|
|
319bb12627 | ||
|
|
7a131ff462 | ||
|
|
6fa1831484 | ||
|
|
9b60b3e33d |
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
@@ -44,6 +45,7 @@ type Catalog struct {
|
||||
Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"`
|
||||
|
||||
// ecosystem-specific cataloger configuration
|
||||
Debian debianConfig `yaml:"debian" json:"debian" mapstructure:"debian"`
|
||||
Dotnet dotnetConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
|
||||
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
|
||||
@@ -76,6 +78,7 @@ func DefaultCatalog() Catalog {
|
||||
Scope: source.SquashedScope.String(),
|
||||
Package: defaultPackageConfig(),
|
||||
License: defaultLicenseConfig(),
|
||||
Debian: defaultDebianConfig(),
|
||||
LinuxKernel: defaultLinuxKernelConfig(),
|
||||
Nix: defaultNixConfig(),
|
||||
Dotnet: defaultDotnetConfig(),
|
||||
@@ -170,6 +173,8 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
}
|
||||
return pkgcataloging.Config{
|
||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
||||
Debian: debian.DefaultCatalogerConfig().
|
||||
WithIncludeDeInstalled(cfg.Debian.IncludeDeInstalled),
|
||||
Dotnet: dotnet.DefaultCatalogerConfig().
|
||||
WithDepPackagesMustHaveDLL(cfg.Dotnet.DepPackagesMustHaveDLL).
|
||||
WithDepPackagesMustClaimDLL(cfg.Dotnet.DepPackagesMustClaimDLL).
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
||||
)
|
||||
|
||||
type debianConfig struct {
|
||||
IncludeDeInstalled bool `yaml:"include-deinstalled" json:"include-deinstalled" mapstructure:"include-deinstalled"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*debianConfig)(nil)
|
||||
|
||||
func (o *debianConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.IncludeDeInstalled, `include debian packages that have been removed but not purged (deinstall status)
|
||||
by default these packages are excluded from the SBOM`)
|
||||
}
|
||||
|
||||
func defaultDebianConfig() debianConfig {
|
||||
def := debian.DefaultCatalogerConfig()
|
||||
return debianConfig{
|
||||
IncludeDeInstalled: def.IncludeDeInstalled,
|
||||
}
|
||||
}
|
||||
@@ -59,13 +59,23 @@ func DefaultPackageTaskFactories() Factories {
|
||||
// OS package installed catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(arch.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "alpm", "archlinux"),
|
||||
newSimplePackageTaskFactory(alpine.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "apk", "alpine"),
|
||||
newSimplePackageTaskFactory(debian.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "dpkg", "debian"),
|
||||
newPackageTaskFactory(
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
return debian.NewDpkgDBCataloger(cfg.PackagesConfig.Debian)
|
||||
},
|
||||
pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "dpkg", "debian",
|
||||
),
|
||||
newSimplePackageTaskFactory(gentoo.NewPortageCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "portage", "gentoo"),
|
||||
newSimplePackageTaskFactory(redhat.NewDBCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.OSTag, "linux", "rpm", "redhat"),
|
||||
|
||||
// OS package declared catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(redhat.NewArchiveCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.OSTag, "linux", "rpm", "redhat"),
|
||||
newSimplePackageTaskFactory(debian.NewArchiveCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.OSTag, "linux", "deb", "debian"),
|
||||
newPackageTaskFactory(
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
return debian.NewDpkgArchiveCataloger(cfg.PackagesConfig.Debian)
|
||||
},
|
||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.OSTag, "linux", "deb", "debian",
|
||||
),
|
||||
|
||||
// language-specific package installed catalogers ///////////////////////////////////////////////////////////////////////////
|
||||
newSimplePackageTaskFactory(cpp.NewConanInfoCataloger, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, pkgcataloging.LanguageTag, "cpp", "conan"),
|
||||
|
||||
@@ -2,6 +2,7 @@ package pkgcataloging
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
|
||||
type Config struct {
|
||||
Binary binary.ClassifierCatalogerConfig `yaml:"binary" json:"binary" mapstructure:"binary"`
|
||||
Debian debian.CatalogerConfig `yaml:"debian" json:"debian" mapstructure:"debian"`
|
||||
Dotnet dotnet.CatalogerConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
|
||||
Golang golang.CatalogerConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||
JavaArchive java.ArchiveCatalogerConfig `yaml:"java-archive" json:"java-archive" mapstructure:"java-archive"`
|
||||
@@ -25,6 +27,7 @@ type Config struct {
|
||||
func DefaultConfig() Config {
|
||||
return Config{
|
||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
||||
Debian: debian.DefaultCatalogerConfig(),
|
||||
Dotnet: dotnet.DefaultCatalogerConfig(),
|
||||
Golang: golang.DefaultCatalogerConfig(),
|
||||
JavaArchive: java.DefaultArchiveCatalogerConfig(),
|
||||
@@ -73,3 +76,8 @@ func (c Config) WithJavaArchiveConfig(cfg java.ArchiveCatalogerConfig) Config {
|
||||
c.JavaArchive = cfg
|
||||
return c
|
||||
}
|
||||
|
||||
func (c Config) WithDebianConfig(cfg debian.CatalogerConfig) Config {
|
||||
c.Debian = cfg
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -10,16 +10,28 @@ import (
|
||||
)
|
||||
|
||||
// NewDBCataloger returns a new Deb package cataloger capable of parsing DPKG status DB flat-file stores.
|
||||
// Deprecated: use NewDpkgDBCataloger with a configuration
|
||||
func NewDBCataloger() pkg.Cataloger {
|
||||
return NewDpkgDBCataloger(DefaultCatalogerConfig())
|
||||
}
|
||||
|
||||
// NewDpkgDBCataloger returns a new Deb package cataloger capable of parsing DPKG status DB flat-file stores with syft configuration.
|
||||
func NewDpkgDBCataloger(cfg CatalogerConfig) pkg.Cataloger {
|
||||
return generic.NewCataloger("dpkg-db-cataloger").
|
||||
// note: these globs have been intentionally split up in order to improve search performance,
|
||||
// please do NOT combine into: "**/var/lib/dpkg/{status,status.d/*}"
|
||||
WithParserByGlobs(parseDpkgDB, "**/lib/dpkg/status", "**/lib/dpkg/status.d/*", "**/lib/opkg/info/*.control", "**/lib/opkg/status").
|
||||
WithParserByGlobs(parseDpkgDB(cfg), "**/lib/dpkg/status", "**/lib/dpkg/status.d/*", "**/lib/opkg/info/*.control", "**/lib/opkg/status").
|
||||
WithProcessors(dependency.Processor(dbEntryDependencySpecifier))
|
||||
}
|
||||
|
||||
// NewArchiveCataloger returns a new Debian package cataloger object capable of parsing .deb archive files
|
||||
// Deprecated: use NewDpkgArchiveCataloger with a configuration
|
||||
func NewArchiveCataloger() pkg.Cataloger {
|
||||
return NewDpkgDBCataloger(DefaultCatalogerConfig())
|
||||
}
|
||||
|
||||
// NewDpkgArchiveCataloger returns a new Debian package cataloger object capable of parsing .deb archive files with syft configuration.
|
||||
func NewDpkgArchiveCataloger(cfg CatalogerConfig) pkg.Cataloger {
|
||||
return generic.NewCataloger("deb-archive-cataloger").
|
||||
WithParserByGlobs(parseDebArchive, "**/*.deb")
|
||||
WithParserByGlobs(parseDebArchive(cfg), "**/*.deb")
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ func TestDpkgArchiveCataloger(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := NewArchiveCataloger()
|
||||
c := NewDpkgArchiveCataloger(CatalogerConfig{IncludeDeInstalled: true})
|
||||
pkgtest.NewCatalogTester().
|
||||
WithImageResolver(t, tt.name).
|
||||
IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package debian
|
||||
|
||||
type CatalogerConfig struct {
|
||||
IncludeDeInstalled bool `yaml:"include-deinstalled" json:"include-deinstalled" mapstructure:"include-deinstalled"`
|
||||
}
|
||||
|
||||
func DefaultCatalogerConfig() CatalogerConfig {
|
||||
return CatalogerConfig{
|
||||
IncludeDeInstalled: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (c CatalogerConfig) WithIncludeDeInstalled(include bool) CatalogerConfig {
|
||||
c.IncludeDeInstalled = include
|
||||
return c
|
||||
}
|
||||
@@ -28,7 +28,13 @@ import (
|
||||
// - data.tar.gz/xz/zst: Contains the actual files to be installed (not processed by this cataloger)
|
||||
//
|
||||
// This function extracts and processes the control information to create package metadata.
|
||||
func parseDebArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
func parseDebArchive(cfg CatalogerConfig) generic.Parser {
|
||||
return func(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
return parseDebArchiveWithConfig(ctx, resolver, env, reader, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func parseDebArchiveWithConfig(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser, cfg CatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
arReader := ar.NewReader(reader)
|
||||
|
||||
var metadata *pkg.DpkgArchiveEntry
|
||||
@@ -50,7 +56,7 @@ func parseDebArchive(ctx context.Context, _ file.Resolver, _ *generic.Environmen
|
||||
if err != nil {
|
||||
return nil, nil, unknown.New(reader.Location, fmt.Errorf("failed to decompress control.tar.* file: %w", err))
|
||||
}
|
||||
metadata, err = processControlTar(dcReader)
|
||||
metadata, err = processControlTar(dcReader, cfg)
|
||||
if err != nil {
|
||||
return nil, nil, unknown.New(reader.Location, fmt.Errorf("failed to process control.tar.* file: %w", err))
|
||||
}
|
||||
@@ -104,7 +110,7 @@ func processDataTar(dcReader io.ReadCloser) ([]string, error) {
|
||||
return licenses, nil
|
||||
}
|
||||
|
||||
func processControlTar(dcReader io.ReadCloser) (*pkg.DpkgArchiveEntry, error) {
|
||||
func processControlTar(dcReader io.ReadCloser, cfg CatalogerConfig) (*pkg.DpkgArchiveEntry, error) {
|
||||
defer internal.CloseAndLogError(dcReader, "")
|
||||
|
||||
// Extract control, md5sums, and conffiles files from control.tar
|
||||
@@ -118,7 +124,7 @@ func processControlTar(dcReader io.ReadCloser) (*pkg.DpkgArchiveEntry, error) {
|
||||
return nil, fmt.Errorf("control file not found in archive")
|
||||
}
|
||||
|
||||
metadata, err := newDpkgArchiveMetadata(controlFileContent, md5Content, confContent)
|
||||
metadata, err := newDpkgArchiveMetadata(controlFileContent, md5Content, confContent, cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create package metadata: %w", err)
|
||||
}
|
||||
@@ -126,9 +132,9 @@ func processControlTar(dcReader io.ReadCloser) (*pkg.DpkgArchiveEntry, error) {
|
||||
return &metadata, nil
|
||||
}
|
||||
|
||||
func newDpkgArchiveMetadata(controlFile, md5sums, confFiles []byte) (pkg.DpkgArchiveEntry, error) {
|
||||
func newDpkgArchiveMetadata(controlFile, md5sums, confFiles []byte, cfg CatalogerConfig) (pkg.DpkgArchiveEntry, error) {
|
||||
// parse the control file to get package metadata
|
||||
metadata, err := parseControlFile(string(controlFile))
|
||||
metadata, err := parseControlFile(string(controlFile), cfg)
|
||||
if err != nil {
|
||||
return pkg.DpkgArchiveEntry{}, fmt.Errorf("failed to parse control file: %w", err)
|
||||
}
|
||||
@@ -201,11 +207,11 @@ func readControlFiles(tarReader *tar.Reader) (controlFile, md5sums, conffiles []
|
||||
}
|
||||
|
||||
// parseControlFile parses the content of a debian control file into package metadata
|
||||
func parseControlFile(controlFileContent string) (pkg.DpkgArchiveEntry, error) {
|
||||
func parseControlFile(controlFileContent string, cfg CatalogerConfig) (pkg.DpkgArchiveEntry, error) {
|
||||
// Reuse the existing dpkg status file parsing logic
|
||||
reader := strings.NewReader(controlFileContent)
|
||||
|
||||
entries, err := parseDpkgStatus(reader)
|
||||
entries, err := parseDpkgStatus(reader, cfg)
|
||||
if err != nil {
|
||||
return pkg.DpkgArchiveEntry{}, fmt.Errorf("failed to parse control file: %w", err)
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ Description: This is a test package
|
||||
And even more details
|
||||
`
|
||||
|
||||
metadata, err := parseControlFile(controlContent)
|
||||
metadata, err := parseControlFile(controlContent, CatalogerConfig{})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "test-package", metadata.Package)
|
||||
|
||||
@@ -24,14 +24,23 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
const (
|
||||
deinstallStatus string = "deinstall"
|
||||
)
|
||||
|
||||
var (
|
||||
errEndOfPackages = fmt.Errorf("no more packages to read")
|
||||
sourceRegexp = regexp.MustCompile(`(?P<name>\S+)( \((?P<version>.*)\))?`)
|
||||
)
|
||||
|
||||
// parseDpkgDB reads a dpkg database "status" file (and surrounding data files) and returns the packages and relationships found.
|
||||
func parseDpkgDB(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
metadata, err := parseDpkgStatus(reader)
|
||||
func parseDpkgDB(cfg CatalogerConfig) generic.Parser {
|
||||
return func(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
return parseDpkgDBWithConfig(ctx, resolver, env, reader, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func parseDpkgDBWithConfig(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser, cfg CatalogerConfig) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
metadata, err := parseDpkgStatus(reader, cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to catalog dpkg DB=%q: %w", reader.RealPath, err)
|
||||
}
|
||||
@@ -73,14 +82,13 @@ func findDpkgInfoFiles(name string, resolver file.Resolver, dbLocation file.Loca
|
||||
return locations
|
||||
}
|
||||
|
||||
// parseDpkgStatus is a parser function for Debian DB status contents, returning all Debian packages listed.
|
||||
func parseDpkgStatus(reader io.Reader) ([]pkg.DpkgDBEntry, error) {
|
||||
func parseDpkgStatus(reader io.Reader, cfg CatalogerConfig) ([]pkg.DpkgDBEntry, error) {
|
||||
buffedReader := bufio.NewReader(reader)
|
||||
var metadata []pkg.DpkgDBEntry
|
||||
|
||||
continueProcessing := true
|
||||
for continueProcessing {
|
||||
entry, err := parseDpkgStatusEntry(buffedReader)
|
||||
entry, err := parseDpkgStatusEntry(buffedReader, cfg)
|
||||
if err != nil {
|
||||
if errors.Is(err, errEndOfPackages) {
|
||||
continueProcessing = false
|
||||
@@ -112,10 +120,10 @@ type dpkgExtractedMetadata struct {
|
||||
Provides string `mapstructure:"Provides"`
|
||||
Depends string `mapstructure:"Depends"`
|
||||
PreDepends string `mapstructure:"PreDepends"` // note: original doc is Pre-Depends
|
||||
Status string `mapstructure:"Status"`
|
||||
}
|
||||
|
||||
// parseDpkgStatusEntry returns an individual Dpkg entry, or returns errEndOfPackages if there are no more packages to parse from the reader.
|
||||
func parseDpkgStatusEntry(reader *bufio.Reader) (*pkg.DpkgDBEntry, error) {
|
||||
func parseDpkgStatusEntry(reader *bufio.Reader, cfg CatalogerConfig) (*pkg.DpkgDBEntry, error) {
|
||||
var retErr error
|
||||
dpkgFields, err := extractAllFields(reader)
|
||||
if err != nil {
|
||||
@@ -134,6 +142,11 @@ func parseDpkgStatusEntry(reader *bufio.Reader) (*pkg.DpkgDBEntry, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Skip entries which have been removed but not purged, e.g. "rc" status in dpkg -l
|
||||
if !cfg.IncludeDeInstalled && strings.Contains(raw.Status, deinstallStatus) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sourceName, sourceVersion := extractSourceVersion(raw.Source)
|
||||
if sourceVersion != "" {
|
||||
raw.SourceVersion = sourceVersion
|
||||
|
||||
@@ -237,6 +237,37 @@ func Test_parseDpkgStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "deinstall status packages are ignored",
|
||||
fixturePath: "test-fixtures/var/lib/dpkg/status.d/deinstall",
|
||||
expected: []pkg.DpkgDBEntry{
|
||||
{
|
||||
Package: "linux-image-6.14.0-1012-aws",
|
||||
Source: "linux-signed-aws-6.14",
|
||||
Version: "6.14.0-1012.12~24.04.1",
|
||||
Architecture: "amd64",
|
||||
InstalledSize: 15221,
|
||||
Maintainer: "Canonical Kernel Team <kernel-team@lists.ubuntu.com>",
|
||||
Description: `Signed kernel image aws
|
||||
A kernel image for aws. This version of it is signed with
|
||||
Canonical's signing key.`,
|
||||
Provides: []string{"fuse-module",
|
||||
"linux-image",
|
||||
"spl-dkms",
|
||||
"spl-modules",
|
||||
"v4l2loopback-dkms",
|
||||
"v4l2loopback-modules",
|
||||
"zfs-dkms",
|
||||
"zfs-modules"},
|
||||
Depends: []string{
|
||||
"kmod",
|
||||
"linux-base (>= 4.5ubuntu1~16.04.1)",
|
||||
"linux-modules-6.14.0-1012-aws",
|
||||
},
|
||||
Files: []pkg.DpkgFileRecord{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -247,7 +278,7 @@ func Test_parseDpkgStatus(t *testing.T) {
|
||||
|
||||
reader := bufio.NewReader(f)
|
||||
|
||||
entries, err := parseDpkgStatus(reader)
|
||||
entries, err := parseDpkgStatus(reader, CatalogerConfig{})
|
||||
require.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(test.expected, entries); diff != "" {
|
||||
@@ -264,7 +295,7 @@ func Test_corruptEntry(t *testing.T) {
|
||||
|
||||
reader := bufio.NewReader(f)
|
||||
|
||||
_, err = parseDpkgStatus(reader)
|
||||
_, err = parseDpkgStatus(reader, CatalogerConfig{})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -372,7 +403,7 @@ Installed-Size: 10kib
|
||||
WithErrorAssertion(tt.wantErr).
|
||||
WithLinuxRelease(linux.Release{ID: "debian", VersionID: "10"}).
|
||||
Expects(tt.want, nil).
|
||||
TestParser(t, parseDpkgDB)
|
||||
TestParser(t, parseDpkgDB(DefaultCatalogerConfig()))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -463,3 +494,54 @@ func abstractRelationships(t testing.TB, relationships []artifact.Relationship)
|
||||
|
||||
return abstracted
|
||||
}
|
||||
|
||||
func Test_parseDpkgStatus_deinstall(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
includeDeinstall bool
|
||||
expectedCount int
|
||||
}{
|
||||
{
|
||||
name: "exclude deinstalled packages (default)",
|
||||
includeDeinstall: false,
|
||||
expectedCount: 1,
|
||||
},
|
||||
{
|
||||
name: "include deinstalled packages",
|
||||
includeDeinstall: true,
|
||||
expectedCount: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fixture, err := os.Open("test-fixtures/var/lib/dpkg/status.d/deinstall")
|
||||
require.NoError(t, err)
|
||||
defer fixture.Close()
|
||||
|
||||
cfg := CatalogerConfig{
|
||||
IncludeDeInstalled: tt.includeDeinstall,
|
||||
}
|
||||
|
||||
entries, err := parseDpkgStatus(fixture, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Len(t, entries, tt.expectedCount, "expected %d entries", tt.expectedCount)
|
||||
|
||||
if tt.includeDeinstall {
|
||||
var foundDeinstalled bool
|
||||
for _, entry := range entries {
|
||||
if entry.Package == "linux-image-6.8.0-1029-aws" {
|
||||
foundDeinstalled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, foundDeinstalled, "should find deinstalled package when includeDeinstall=true")
|
||||
} else {
|
||||
for _, entry := range entries {
|
||||
assert.NotEqual(t, "linux-image-6.8.0-1029-aws", entry.Package, "should not find deinstalled package when includeDeinstall=false")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
Package: linux-image-6.14.0-1012-aws
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: kernel
|
||||
Installed-Size: 15221
|
||||
Maintainer: Canonical Kernel Team <kernel-team@lists.ubuntu.com>
|
||||
Architecture: amd64
|
||||
Source: linux-signed-aws-6.14
|
||||
Version: 6.14.0-1012.12~24.04.1
|
||||
Provides: fuse-module, linux-image, spl-dkms, spl-modules, v4l2loopback-dkms, v4l2loopback-modules, zfs-dkms, zfs-modules
|
||||
Depends: kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-6.14.0-1012-aws
|
||||
Recommends: grub-pc | grub-efi-amd64 | grub-efi-ia32 | grub | lilo, initramfs-tools | linux-initramfs-tool
|
||||
Suggests: bpftool, linux-perf, linux-aws-6.14-doc-6.14.0 | linux-aws-6.14-source-6.14.0, linux-aws-6.14-tools, linux-headers-6.14.0-1012-aws
|
||||
Conflicts: linux-image-unsigned-6.14.0-1012-aws
|
||||
Description: Signed kernel image aws
|
||||
A kernel image for aws. This version of it is signed with
|
||||
Canonical's signing key.
|
||||
Built-Using: linux-aws-6.14 (= 6.14.0-1012.12~24.04.1)
|
||||
|
||||
Package: linux-image-6.8.0-1029-aws
|
||||
Status: deinstall ok config-files
|
||||
Priority: optional
|
||||
Section: kernel
|
||||
Installed-Size: 14591
|
||||
Maintainer: Canonical Kernel Team <kernel-team@lists.ubuntu.com>
|
||||
Architecture: amd64
|
||||
Source: linux-signed-aws
|
||||
Version: 6.8.0-1029.31
|
||||
Config-Version: 6.8.0-1029.31
|
||||
Provides: fuse-module, linux-image, spl-dkms, spl-modules, v4l2loopback-dkms, v4l2loopback-modules, zfs-dkms, zfs-modules
|
||||
Depends: kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-6.8.0-1029-aws
|
||||
Recommends: grub-pc | grub-efi-amd64 | grub-efi-ia32 | grub | lilo, initramfs-tools | linux-initramfs-tool
|
||||
Suggests: fdutils, linux-aws-doc-6.8.0 | linux-aws-source-6.8.0, linux-aws-tools, linux-headers-6.8.0-1029-aws
|
||||
Conflicts: linux-image-unsigned-6.8.0-1029-aws
|
||||
Description: Signed kernel image aws
|
||||
A kernel image for aws. This version of it is signed with
|
||||
Canonical's signing key.
|
||||
Built-Using: linux-aws (= 6.8.0-1029.31)
|
||||
Reference in New Issue
Block a user