From d1f92334093e4e6d817a002339633fd23ae0d6b7 Mon Sep 17 00:00:00 2001 From: Shunichi Shinohara Date: Tue, 5 Mar 2024 15:23:45 +0900 Subject: [PATCH] Avoid to use sync.Once inside trivy javadb Updater (#1859) * Avoid to use once inside trivy javadb Updater Because detector package may be used as library-like way * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Update detector/javadb/javadb.go Co-authored-by: MaineK00n * Avoid else if, unless necessary * go mod tidy * Add package comment --------- Co-authored-by: MaineK00n --- detector/javadb/javadb.go | 108 ++++++++++++++++++++++++++++++++++++++ detector/library.go | 14 ++--- go.mod | 2 +- models/library.go | 4 +- 4 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 detector/javadb/javadb.go diff --git a/detector/javadb/javadb.go b/detector/javadb/javadb.go new file mode 100644 index 00000000..e01f3d3b --- /dev/null +++ b/detector/javadb/javadb.go @@ -0,0 +1,108 @@ +//go:build !scanner +// +build !scanner + +// Package javadb implements functions that wrap trivy-java-db module. +package javadb + +import ( + "context" + "errors" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/aquasecurity/go-dep-parser/pkg/java/jar" + "github.com/aquasecurity/trivy-java-db/pkg/db" + "github.com/aquasecurity/trivy/pkg/fanal/types" + "github.com/aquasecurity/trivy/pkg/oci" + "golang.org/x/xerrors" + + "github.com/future-architect/vuls/config" + "github.com/future-architect/vuls/logging" +) + +// UpdateJavaDB updates Trivy Java DB +func UpdateJavaDB(trivyOpts config.TrivyOpts, noProgress bool) error { + dbDir := filepath.Join(trivyOpts.TrivyCacheDBDir, "java-db") + + metac := db.NewMetadata(dbDir) + meta, err := metac.Get() + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + return xerrors.Errorf("Failed to get Java DB metadata. err: %w", err) + } + if trivyOpts.TrivySkipJavaDBUpdate { + logging.Log.Error("Could not skip, the first run cannot skip downloading Java DB") + return xerrors.New("'--trivy-skip-java-db-update' cannot be specified on the first run") + } + } + + if (meta.Version != db.SchemaVersion || meta.NextUpdate.Before(time.Now().UTC())) && !trivyOpts.TrivySkipJavaDBUpdate { + // Download DB + repo := fmt.Sprintf("%s:%d", trivyOpts.TrivyJavaDBRepository, db.SchemaVersion) + logging.Log.Infof("Trivy Java DB Repository: %s", repo) + logging.Log.Info("Downloading Trivy Java DB...") + + var a *oci.Artifact + if a, err = oci.NewArtifact(repo, noProgress, types.RegistryOptions{}); err != nil { + return xerrors.Errorf("Failed to new oci artifact. err: %w", err) + } + if err = a.Download(context.Background(), dbDir, oci.DownloadOption{MediaType: "application/vnd.aquasec.trivy.javadb.layer.v1.tar+gzip"}); err != nil { + return xerrors.Errorf("Failed to download Trivy Java DB. err: %w", err) + } + + // Parse the newly downloaded metadata.json + meta, err = metac.Get() + if err != nil { + return xerrors.Errorf("Failed to get Trivy Java DB metadata. err: %w", err) + } + + // Update DownloadedAt + meta.DownloadedAt = time.Now().UTC() + if err = metac.Update(meta); err != nil { + return xerrors.Errorf("Failed to update Trivy Java DB metadata. err: %w", err) + } + } + + return nil +} + +// DBClient is Trivy Java DB Client +type DBClient struct { + driver db.DB +} + +// NewClient returns Trivy Java DB Client +func NewClient(cacheDBDir string) (*DBClient, error) { + driver, err := db.New(filepath.Join(cacheDBDir, "java-db")) + if err != nil { + return nil, xerrors.Errorf("Failed to open Trivy Java DB. err: %w", err) + } + return &DBClient{driver: driver}, nil +} + +// Close closes Trivy Java DB Client +func (client *DBClient) Close() error { + if client == nil { + return nil + } + + return client.driver.Close() +} + +// SearchBySHA1 searches Jar Property by SHA1 +func (client *DBClient) SearchBySHA1(sha1 string) (jar.Properties, error) { + index, err := client.driver.SelectIndexBySha1(sha1) + if err != nil { + return jar.Properties{}, xerrors.Errorf("Failed to select from Trivy Java DB. err: %w", err) + } + if index.ArtifactID == "" { + return jar.Properties{}, xerrors.Errorf("Failed to search ArtifactID by digest %s. err: %w", sha1, jar.ArtifactNotFoundErr) + } + return jar.Properties{ + GroupID: index.GroupID, + ArtifactID: index.ArtifactID, + Version: index.Version, + }, nil +} diff --git a/detector/library.go b/detector/library.go index 04f0a4fd..e2575e12 100644 --- a/detector/library.go +++ b/detector/library.go @@ -10,11 +10,11 @@ import ( "github.com/aquasecurity/trivy-db/pkg/metadata" "github.com/aquasecurity/trivy/pkg/db" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/javadb" "github.com/aquasecurity/trivy/pkg/log" "golang.org/x/xerrors" "github.com/future-architect/vuls/config" + "github.com/future-architect/vuls/detector/javadb" "github.com/future-architect/vuls/logging" "github.com/future-architect/vuls/models" ) @@ -41,16 +41,18 @@ func DetectLibsCves(r *models.ScanResult, trivyOpts config.TrivyOpts, logOpts lo } defer trivydb.Close() - var javaDBClient *javadb.DB + var javaDBClient *javadb.DBClient defer javaDBClient.Close() for _, lib := range r.LibraryScanners { if lib.Type == ftypes.Jar { if javaDBClient == nil { - javadb.Init(trivyOpts.TrivyCacheDBDir, trivyOpts.TrivyJavaDBRepository, trivyOpts.TrivySkipJavaDBUpdate, noProgress, ftypes.RegistryOptions{}) + if err := javadb.UpdateJavaDB(trivyOpts, noProgress); err != nil { + return xerrors.Errorf("Failed to update Trivy Java DB. err: %w", err) + } - javaDBClient, err = javadb.NewClient() + javaDBClient, err = javadb.NewClient(trivyOpts.TrivyCacheDBDir) if err != nil { - return xerrors.Errorf("Failed to download or open trivy Java DB. err: %w", err) + return xerrors.Errorf("Failed to open Trivy Java DB. err: %w", err) } } lib.JavaDBClient = javaDBClient @@ -107,7 +109,7 @@ func showDBInfo(cacheDir string) error { if err != nil { return xerrors.Errorf("Failed to get DB metadata. err: %w", err) } - log.Logger.Debugf("DB Schema: %d, UpdatedAt: %s, NextUpdate: %s, DownloadedAt: %s", + logging.Log.Debugf("DB Schema: %d, UpdatedAt: %s, NextUpdate: %s, DownloadedAt: %s", meta.Version, meta.UpdatedAt, meta.NextUpdate, meta.DownloadedAt) return nil } diff --git a/go.mod b/go.mod index 1692dfea..e13dda2d 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/aquasecurity/go-dep-parser v0.0.0-20240202105001-4f19ab402b0b github.com/aquasecurity/trivy v0.49.1 github.com/aquasecurity/trivy-db v0.0.0-20231005141211-4fc651f7ac8d + github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 github.com/aws/aws-sdk-go v1.49.21 github.com/c-robinson/iplib v1.0.8 @@ -107,7 +108,6 @@ require ( github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 // indirect github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect github.com/aquasecurity/trivy-iac v0.8.0 // indirect - github.com/aquasecurity/trivy-java-db v0.0.0-20240109071736-184bd7481d48 // indirect github.com/aquasecurity/trivy-policies v0.8.0 // indirect github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect github.com/aws/aws-sdk-go-v2/config v1.26.3 // indirect diff --git a/models/library.go b/models/library.go index 970068d4..850dfc81 100644 --- a/models/library.go +++ b/models/library.go @@ -10,11 +10,11 @@ import ( trivyDBTypes "github.com/aquasecurity/trivy-db/pkg/types" "github.com/aquasecurity/trivy/pkg/detector/library" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" - "github.com/aquasecurity/trivy/pkg/javadb" "github.com/aquasecurity/trivy/pkg/types" "github.com/samber/lo" "golang.org/x/xerrors" + "github.com/future-architect/vuls/detector/javadb" "github.com/future-architect/vuls/logging" ) @@ -51,7 +51,7 @@ type LibraryScanner struct { // The path to the Lockfile is stored. LockfilePath string `json:"path,omitempty"` - JavaDBClient *javadb.DB `json:"-"` + JavaDBClient *javadb.DBClient `json:"-"` } // Library holds the attribute of a package library