From 525e51d68efce3a018da4f3df10ec0dc6e24ef6e Mon Sep 17 00:00:00 2001 From: Matthias Bertschy Date: Fri, 25 Jul 2025 09:50:10 +0200 Subject: [PATCH] close grype DB at the very end of processing Signed-off-by: Matthias Bertschy --- core/core/image_scan.go | 7 +++++- core/core/patch.go | 7 +++++- core/core/scan.go | 9 ++++++-- pkg/imagescan/imagescan.go | 41 +++++++++++++++++++-------------- pkg/imagescan/imagescan_test.go | 9 ++++++-- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/core/core/image_scan.go b/core/core/image_scan.go index e028e584..0f2b7491 100644 --- a/core/core/image_scan.go +++ b/core/core/image_scan.go @@ -165,7 +165,12 @@ func (ks *Kubescape) ScanImage(imgScanInfo *ksmetav1.ImageScanInfo, scanInfo *ca logger.L().Start(fmt.Sprintf("Scanning image %s...", imgScanInfo.Image)) dbCfg, _ := imagescan.NewDefaultDBConfig() - svc := imagescan.NewScanService(dbCfg) + svc, err := imagescan.NewScanService(dbCfg) + if err != nil { + logger.L().StopError(fmt.Sprintf("Failed to initialize image scanner: %s", err)) + return nil, err + } + defer svc.Close() creds := imagescan.RegistryCredentials{ Username: imgScanInfo.Username, diff --git a/core/core/patch.go b/core/core/patch.go index 5601f458..48ff70d3 100644 --- a/core/core/patch.go +++ b/core/core/patch.go @@ -31,7 +31,12 @@ func (ks *Kubescape) Patch(patchInfo *ksmetav1.PatchInfo, scanInfo *cautils.Scan // Setup the scan service dbCfg, _ := imagescan.NewDefaultDBConfig() - svc := imagescan.NewScanService(dbCfg) + svc, err := imagescan.NewScanService(dbCfg) + if err != nil { + logger.L().StopError(fmt.Sprintf("Failed to initialize image scanner: %s", err)) + return nil, err + } + defer svc.Close() creds := imagescan.RegistryCredentials{ Username: patchInfo.Username, Password: patchInfo.Password, diff --git a/core/core/scan.go b/core/core/scan.go index 579d1d21..c26a2382 100644 --- a/core/core/scan.go +++ b/core/core/scan.go @@ -244,7 +244,12 @@ func scanImages(scanType cautils.ScanTypes, scanData *cautils.OPASessionObj, ctx } dbCfg, _ := imagescan.NewDefaultDBConfig() - svc := imagescan.NewScanService(dbCfg) + svc, err := imagescan.NewScanService(dbCfg) + if err != nil { + logger.L().StopError(fmt.Sprintf("Failed to initialize image scanner: %s", err)) + return + } + defer svc.Close() for _, img := range imagesToScan { logger.L().Start("Scanning", helpers.String("image", img)) @@ -255,7 +260,7 @@ func scanImages(scanType cautils.ScanTypes, scanData *cautils.OPASessionObj, ctx } } -func scanSingleImage(ctx context.Context, img string, svc imagescan.Service, resultsHandling *resultshandling.ResultsHandler) error { +func scanSingleImage(ctx context.Context, img string, svc *imagescan.Service, resultsHandling *resultshandling.ResultsHandler) error { scanResults, err := svc.Scan(ctx, img, imagescan.RegistryCredentials{}, nil, nil) if err != nil { diff --git a/pkg/imagescan/imagescan.go b/pkg/imagescan/imagescan.go index 2f02ba7a..21edcc5c 100644 --- a/pkg/imagescan/imagescan.go +++ b/pkg/imagescan/imagescan.go @@ -115,7 +115,10 @@ func getProviderConfig(creds RegistryCredentials) pkg.ProviderConfig { // // It performs image scanning and everything needed in between. type Service struct { - dbCfg db.Config + dbCfg db.Config + dbCloser *db.Closer + dbStatus *db.Status + dbStore *store.Store } func getIgnoredMatches(vulnerabilityExceptions []string, store *store.Store, packages []pkg.Package, pkgContext pkg.Context) (*match.Matches, []match.IgnoredMatch, error) { @@ -178,47 +181,51 @@ func filterMatchesBasedOnSeverity(severityExceptions []string, remainingMatches return filteredMatches } -func (s *Service) Scan(ctx context.Context, userInput string, creds RegistryCredentials, vulnerabilityExceptions, severityExceptions []string) (*models.PresenterConfig, error) { - store, status, dbCloser, err := NewVulnerabilityDB(s.dbCfg, true) - if err = validateDBLoad(err, status); err != nil { - return nil, err - } - +func (s *Service) Scan(_ context.Context, userInput string, creds RegistryCredentials, vulnerabilityExceptions, severityExceptions []string) (*models.PresenterConfig, error) { packages, pkgContext, sbom, err := pkg.Provide(userInput, getProviderConfig(creds)) if err != nil { return nil, err } - if dbCloser != nil { - defer dbCloser.Close() - } - - remainingMatches, ignoredMatches, err := getIgnoredMatches(vulnerabilityExceptions, store, packages, pkgContext) + remainingMatches, ignoredMatches, err := getIgnoredMatches(vulnerabilityExceptions, s.dbStore, packages, pkgContext) if err != nil { return nil, err } - filteredMatches := filterMatchesBasedOnSeverity(severityExceptions, *remainingMatches, store) + filteredMatches := filterMatchesBasedOnSeverity(severityExceptions, *remainingMatches, s.dbStore) pb := models.PresenterConfig{ Matches: filteredMatches, IgnoredMatches: ignoredMatches, Packages: packages, Context: pkgContext, - MetadataProvider: store, + MetadataProvider: s.dbStore, SBOM: sbom, AppConfig: nil, - DBStatus: status, + DBStatus: s.dbStatus, } return &pb, nil } +func (s *Service) Close() { + s.dbCloser.Close() +} + func NewVulnerabilityDB(cfg db.Config, update bool) (*store.Store, *db.Status, *db.Closer, error) { return grype.LoadVulnerabilityDB(cfg, update) } -func NewScanService(dbCfg db.Config) Service { - return Service{dbCfg: dbCfg} +func NewScanService(dbCfg db.Config) (*Service, error) { + dbStore, dbStatus, dbCloser, err := NewVulnerabilityDB(dbCfg, true) + if err = validateDBLoad(err, dbStatus); err != nil { + return nil, err + } + return &Service{ + dbCfg: dbCfg, + dbCloser: dbCloser, + dbStatus: dbStatus, + dbStore: dbStore, + }, nil } // ParseSeverity returns a Grype severity given a severity string diff --git a/pkg/imagescan/imagescan_test.go b/pkg/imagescan/imagescan_test.go index 3efc2c9d..c232d875 100644 --- a/pkg/imagescan/imagescan_test.go +++ b/pkg/imagescan/imagescan_test.go @@ -17,6 +17,7 @@ import ( syftPkg "github.com/anchore/syft/syft/pkg" "github.com/google/uuid" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestVulnerabilityAndSeverityExceptions(t *testing.T) { @@ -27,7 +28,9 @@ func TestVulnerabilityAndSeverityExceptions(t *testing.T) { DBRootDir: path.Join(xdg.CacheHome, "grype-light", "db"), ListingURL: "http://localhost:8000/listing.json", } - svc := NewScanService(dbCfg) + svc, err := NewScanService(dbCfg) + require.NoError(t, err) + defer svc.Close() creds := RegistryCredentials{} tests := []struct { @@ -338,7 +341,9 @@ func TestGetProviderConfig(t *testing.T) { func TestNewScanService(t *testing.T) { defaultConfig, _ := NewDefaultDBConfig() - svc := NewScanService(defaultConfig) + svc, err := NewScanService(defaultConfig) + require.NoError(t, err) + defer svc.Close() assert.Equal(t, defaultConfig, svc.dbCfg) }