add DBCloser. Clients can aviod db connection leak if vulnerability db is loaded many times (#825)

This commit is contained in:
artsv79 2022-07-12 16:54:42 +03:00 committed by GitHub
parent cb6bddfeeb
commit 2233736e98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 48 additions and 15 deletions

View file

@ -284,6 +284,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
var store *store.Store
var status *db.Status
var dbCloser *db.Closer
var packages []pkg.Package
var context pkg.Context
var wg = &sync.WaitGroup{}
@ -294,7 +295,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
go func() {
defer wg.Done()
log.Debug("loading DB")
store, status, err = grype.LoadVulnerabilityDB(appConfig.DB.ToCuratorConfig(), appConfig.DB.AutoUpdate)
store, status, dbCloser, err = grype.LoadVulnerabilityDB(appConfig.DB.ToCuratorConfig(), appConfig.DB.AutoUpdate)
if err = validateDBLoad(err, status); err != nil {
errs <- err
return
@ -318,6 +319,10 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
return
}
if dbCloser != nil {
defer dbCloser.Close()
}
if appConfig.OnlyFixed {
appConfig.Ignore = append(appConfig.Ignore, ignoreNonFixedMatches...)
}

View file

@ -77,15 +77,15 @@ func (c Curator) SupportedSchema() int {
return c.targetSchema
}
func (c *Curator) GetStore() (grypeDB.StoreReader, error) {
func (c *Curator) GetStore() (grypeDB.StoreReader, grypeDB.DBCloser, error) {
// ensure the DB is ok
_, err := c.validateIntegrity(c.dbDir)
if err != nil {
return nil, fmt.Errorf("vulnerability database is invalid (run db update to correct): %+v", err)
return nil, nil, fmt.Errorf("vulnerability database is invalid (run db update to correct): %+v", err)
}
s, err := store.New(c.dbPath, false)
return s, err
return s, s, err
}
func (c *Curator) Status() Status {

9
grype/db/db_closer.go Normal file
View file

@ -0,0 +1,9 @@
package db
import v4 "github.com/anchore/grype/grype/db/v4"
// Closer lets receiver close the db connection and free any allocated db resources.
// It's especially useful if vulnerability DB loaded repeatedly during some periodic SBOM scanning process.
type Closer struct {
v4.DBCloser
}

View file

@ -3,6 +3,7 @@ package v4
type Store interface {
StoreReader
StoreWriter
DBCloser
}
type StoreReader interface {
@ -18,9 +19,12 @@ type StoreWriter interface {
VulnerabilityStoreWriter
VulnerabilityMetadataStoreWriter
VulnerabilityMatchExclusionStoreWriter
Close()
}
type DiffReader interface {
DiffStore(s StoreReader) (*[]Diff, error)
}
type DBCloser interface {
Close()
}

View file

@ -263,6 +263,11 @@ func (s *store) AddVulnerabilityMatchExclusion(exclusions ...v4.VulnerabilityMat
func (s *store) Close() {
s.db.Exec("VACUUM;")
sqlDB, err := s.db.DB()
if err != nil {
_ = sqlDB.Close()
}
}
// GetAllVulnerabilities gets all vulnerabilities in the database

View file

@ -117,16 +117,20 @@ func download(curator *db.Curator, listing *db.ListingEntry) error {
}
func (d *Differ) DiffDatabases() (*[]v4.Diff, error) {
baseStore, err := d.baseCurator.GetStore()
baseStore, baseDBCloser, err := d.baseCurator.GetStore()
if err != nil {
return nil, err
}
targetStore, err := d.targetCurator.GetStore()
defer baseDBCloser.Close()
targetStore, targetDBCloser, err := d.targetCurator.GetStore()
if err != nil {
return nil, err
}
defer targetDBCloser.Close()
return baseStore.DiffStore(targetStore)
}

View file

@ -38,30 +38,30 @@ func FindVulnerabilitiesForPackage(store store.Store, d *linux.Release, matchers
return matcher.FindMatches(store, d, matchers, packages)
}
func LoadVulnerabilityDB(cfg db.Config, update bool) (*store.Store, *db.Status, error) {
func LoadVulnerabilityDB(cfg db.Config, update bool) (*store.Store, *db.Status, *db.Closer, error) {
dbCurator, err := db.NewCurator(cfg)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
if update {
log.Debug("looking for updates on vulnerability database")
_, err := dbCurator.Update()
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
}
storeReader, err := dbCurator.GetStore()
storeReader, dbCloser, err := dbCurator.GetStore()
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
status := dbCurator.Status()
p, err := db.NewVulnerabilityProvider(storeReader)
if err != nil {
return nil, &status, err
return nil, &status, nil, err
}
s := &store.Store{
@ -70,7 +70,9 @@ func LoadVulnerabilityDB(cfg db.Config, update bool) (*store.Store, *db.Status,
ExclusionProvider: db.NewMatchExclusionProvider(storeReader),
}
return s, &status, nil
closer := &db.Closer{DBCloser: dbCloser}
return s, &status, closer, nil
}
func SetLogger(logger logger.Logger) {

View file

@ -43,13 +43,17 @@ func TestCompareSBOMInputToLibResults(t *testing.T) {
}
// get a grype DB
store, _, err := grype.LoadVulnerabilityDB(db.Config{
store, _, closer, err := grype.LoadVulnerabilityDB(db.Config{
DBRootDir: "test-fixtures/grype-db",
ListingURL: getListingURL(),
ValidateByHashOnGet: false,
}, true)
assert.NoError(t, err)
if closer != nil {
defer closer.Close()
}
definedPkgTypes := strset.New()
for _, p := range syftPkg.AllPkgs {
definedPkgTypes.Add(string(p))