diff --git a/examples/create_custom_sbom/main.go b/examples/create_custom_sbom/main.go index 11f1757c9..44fa33749 100644 --- a/examples/create_custom_sbom/main.go +++ b/examples/create_custom_sbom/main.go @@ -7,6 +7,7 @@ import ( "os" "gopkg.in/yaml.v3" + _ "modernc.org/sqlite" // required for rpmdb and other features "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging" diff --git a/examples/create_simple_sbom/main.go b/examples/create_simple_sbom/main.go index 9116f0561..788e8e530 100644 --- a/examples/create_simple_sbom/main.go +++ b/examples/create_simple_sbom/main.go @@ -5,6 +5,8 @@ import ( "fmt" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/format/syftjson" diff --git a/examples/select_catalogers/main.go b/examples/select_catalogers/main.go index 3ff3ecd8d..bc8c6c813 100644 --- a/examples/select_catalogers/main.go +++ b/examples/select_catalogers/main.go @@ -5,6 +5,8 @@ import ( "encoding/json" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cataloging/pkgcataloging" diff --git a/examples/source_from_registry/main.go b/examples/source_from_registry/main.go index 158731259..c43ad8afd 100644 --- a/examples/source_from_registry/main.go +++ b/examples/source_from_registry/main.go @@ -4,6 +4,8 @@ import ( "context" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/format/syftjson" ) diff --git a/syft/pkg/cataloger/generic/cataloger.go b/syft/pkg/cataloger/generic/cataloger.go index 77863dd6d..abdad6293 100644 --- a/syft/pkg/cataloger/generic/cataloger.go +++ b/syft/pkg/cataloger/generic/cataloger.go @@ -53,6 +53,7 @@ func (p resolvingProcessorWrapper) process(ctx context.Context, resolver file.Re type Cataloger struct { processors []processExecutor requesters []requester + checks []func() error upstreamCataloger string } @@ -127,6 +128,11 @@ func (c *Cataloger) WithResolvingProcessors(processors ...ResolvingProcessor) *C return c } +func (c *Cataloger) WithChecks(checks ...func() error) *Cataloger { + c.checks = append(c.checks, checks...) + return c +} + func makeRequests(parser Parser, locations []file.Location) []request { var requests []request for _, l := range locations { @@ -152,6 +158,12 @@ func (c *Cataloger) Name() string { // Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source. func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { + for _, check := range c.checks { + if err := check(); err != nil { + return nil, nil, err + } + } + var packages []pkg.Package var relationships []artifact.Relationship diff --git a/syft/pkg/cataloger/redhat/cataloger.go b/syft/pkg/cataloger/redhat/cataloger.go index f2d1c1428..ba065695b 100644 --- a/syft/pkg/cataloger/redhat/cataloger.go +++ b/syft/pkg/cataloger/redhat/cataloger.go @@ -5,8 +5,8 @@ package redhat import ( "database/sql" + "fmt" - "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" @@ -15,15 +15,11 @@ import ( // NewDBCataloger returns a new RPM DB cataloger object. func NewDBCataloger() pkg.Cataloger { - // check if a sqlite driver is available - if !isSqliteDriverAvailable() { - log.Debugf("sqlite driver is not available, newer RPM databases might not be cataloged") - } - return generic.NewCataloger("rpm-db-cataloger"). WithParserByGlobs(parseRpmDB, pkg.RpmDBGlob). WithParserByGlobs(parseRpmManifest, pkg.RpmManifestGlob). - WithProcessors(dependency.Processor(dbEntryDependencySpecifier), denySelfReferences) + WithProcessors(dependency.Processor(dbEntryDependencySpecifier), denySelfReferences). + WithChecks(ensureSqliteDriverAvailable) } func denySelfReferences(pkgs []pkg.Package, rels []artifact.Relationship, err error) ([]pkg.Package, []artifact.Relationship, error) { @@ -47,11 +43,11 @@ func NewArchiveCataloger() pkg.Cataloger { WithParserByGlobs(parseRpmArchive, "**/*.rpm") } -func isSqliteDriverAvailable() bool { +func ensureSqliteDriverAvailable() error { db, err := sql.Open("sqlite", ":memory:") if err != nil { - return false + return fmt.Errorf("sqlite driver is required for cataloging newer RPM databases, none registered: %v", err) } _ = db.Close() - return true + return nil } diff --git a/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go b/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go new file mode 100644 index 000000000..f1a3f17e4 --- /dev/null +++ b/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go @@ -0,0 +1,22 @@ +package sqlitetest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/internal/fileresolver" + "github.com/anchore/syft/syft/pkg/cataloger/redhat" +) + +func Test_noSQLiteDriverError(t *testing.T) { + // this test package does must not import the sqlite library + file := "../test-fixtures/Packages" + resolver, err := fileresolver.NewFromFile(file, file) + require.NoError(t, err) + + cataloger := redhat.NewDBCataloger() + _, _, err = cataloger.Catalog(context.TODO(), resolver) + require.ErrorContains(t, err, "sqlite") +}