fix(CVE): attempt to scan now returns early with an error if trivyDB metadata json is missing (#1548)

Also modify zli to retry in case of such errors,
assuming the trivyDB will eventually be downloaded by the scheduled task.

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
This commit is contained in:
Andrei Aaron
2023-07-05 19:08:16 +03:00
committed by GitHub
parent 137e5bd793
commit 7fee57e7cc
6 changed files with 159 additions and 10 deletions
+36 -1
View File
@@ -4,9 +4,11 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"path"
"sync"
"github.com/aquasecurity/trivy-db/pkg/metadata"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/commands/artifact"
"github.com/aquasecurity/trivy/pkg/commands/operation"
@@ -155,6 +157,11 @@ func (scanner Scanner) getTrivyOptions(image string) flag.Options {
func (scanner Scanner) runTrivy(opts flag.Options) (types.Report, error) {
ctx := context.Background()
err := scanner.checkDBPresence()
if err != nil {
return types.Report{}, err
}
runner, err := artifact.NewRunner(ctx, opts)
if err != nil {
return types.Report{}, err
@@ -333,7 +340,7 @@ func (scanner Scanner) ScanImage(image string) (map[string]cvemodel.CVE, error)
return cveidMap, nil
}
// UpdateDb download the Trivy DB / Cache under the store root directory.
// UpdateDB downloads the Trivy DB / Cache under the store root directory.
func (scanner Scanner) UpdateDB() error {
// We need a lock as using multiple substores each with it's own DB
// can result in a DATARACE because some varibles in trivy-db are global
@@ -395,6 +402,34 @@ func (scanner Scanner) updateDB(dbDir string) error {
return nil
}
// checkDBPresence errors if the DB metadata files cannot be accessed.
func (scanner Scanner) checkDBPresence() error {
result := true
if scanner.storeController.DefaultStore != nil {
dbDir := path.Join(scanner.storeController.DefaultStore.RootDir(), "_trivy")
if _, err := os.Stat(metadata.Path(dbDir)); err != nil {
result = false
}
}
if scanner.storeController.SubStore != nil {
for _, storage := range scanner.storeController.SubStore {
dbDir := path.Join(storage.RootDir(), "_trivy")
if _, err := os.Stat(metadata.Path(dbDir)); err != nil {
result = false
}
}
}
if !result {
return zerr.ErrCVEDBNotFound
}
return nil
}
func (scanner Scanner) CompareSeverities(severity1, severity2 string) int {
return dbTypes.CompareSeverityString(severity1, severity2)
}
@@ -15,6 +15,7 @@ import (
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
zerr "zotregistry.io/zot/errors"
"zotregistry.io/zot/pkg/common"
"zotregistry.io/zot/pkg/extensions/monitoring"
"zotregistry.io/zot/pkg/log"
@@ -124,6 +125,11 @@ func TestMultipleStoragePath(t *testing.T) {
generateTestImage(storeController, img1)
generateTestImage(storeController, img2)
// Try to scan without the DB being downloaded
_, err = scanner.ScanImage(img0)
So(err, ShouldNotBeNil)
So(err, ShouldWrap, zerr.ErrCVEDBNotFound)
// Download DB since DB download on scan is disabled
err = scanner.UpdateDB()
So(err, ShouldBeNil)
@@ -197,12 +203,20 @@ func TestTrivyLibraryErrors(t *testing.T) {
err = repodb.ParseStorage(repoDB, storeController, log)
So(err, ShouldBeNil)
img := "zot-test:0.0.1" //nolint:goconst
// Download DB fails for missing DB url
scanner := NewScanner(storeController, repoDB, "", "", log)
err = scanner.UpdateDB()
So(err, ShouldNotBeNil)
// Try to scan without the DB being downloaded
opts := scanner.getTrivyOptions(img)
_, err = scanner.runTrivy(opts)
So(err, ShouldNotBeNil)
So(err, ShouldWrap, zerr.ErrCVEDBNotFound)
// Download DB fails for invalid Java DB
scanner = NewScanner(storeController, repoDB, "ghcr.io/project-zot/trivy-db",
"ghcr.io/project-zot/trivy-not-db", log)
@@ -217,10 +231,8 @@ func TestTrivyLibraryErrors(t *testing.T) {
err = scanner.UpdateDB()
So(err, ShouldBeNil)
img := "zot-test:0.0.1"
// Scanning image with correct options
opts := scanner.getTrivyOptions(img)
opts = scanner.getTrivyOptions(img)
_, err = scanner.runTrivy(opts)
So(err, ShouldBeNil)
@@ -482,7 +494,7 @@ func TestDefaultTrivyDBUrl(t *testing.T) {
So(err, ShouldBeNil)
// Scanning image
img := "zot-test:0.0.1"
img := "zot-test:0.0.1" //nolint:goconst
opts := scanner.getTrivyOptions(img)
_, err = scanner.runTrivy(opts)