mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 21:17:58 +08:00
fix(trivy): cleanup Trivy temporary directory (#3618)
This Trivy commit changed the way the cleanup is done for Trivy operations: https://github.com/aquasecurity/trivy/commit/8f5b56005a4e8752976524750089dc9ea2c91e40 We need to start calling the APIs to create and cleanup the temp dir to ensure we don't leave around content in the /tmp folder Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/flag"
|
||||
"github.com/aquasecurity/trivy/pkg/javadb"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
xos "github.com/aquasecurity/trivy/pkg/x/os"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
regTypes "github.com/google/go-containerregistry/pkg/v1/types"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
@@ -193,29 +194,54 @@ func (scanner Scanner) getTrivyOptions(image string) flag.Options {
|
||||
return opts
|
||||
}
|
||||
|
||||
// withTempDir creates a temporary directory using xos.TempDir(), executes the provided function,
|
||||
// and then calls xos.Cleanup() to clean up Trivy's process-specific temp directory.
|
||||
func (scanner Scanner) withTempDir(wrappedFunc func() error) error {
|
||||
// Ensure Trivy's process-specific temp directory is initialized,
|
||||
// call TempDir() to get the path, then create it if it doesn't exist with MkdirAll.
|
||||
tempDir := xos.TempDir()
|
||||
|
||||
if err := os.MkdirAll(tempDir, 0o755); err != nil {
|
||||
scanner.log.Error().Err(err).Str("tempDir", tempDir).Msg("failed to create Trivy temp directory")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// Clean up Trivy's process-specific temp directory (includes our tmpDir)
|
||||
if err := xos.Cleanup(); err != nil {
|
||||
scanner.log.Warn().Err(err).Str("tempDir", tempDir).Msg("failed to cleanup Trivy temp directory")
|
||||
}
|
||||
}()
|
||||
|
||||
return wrappedFunc()
|
||||
}
|
||||
|
||||
func (scanner Scanner) runTrivy(ctx context.Context, opts flag.Options) (types.Report, error) {
|
||||
err := scanner.checkDBPresence()
|
||||
if err != nil {
|
||||
return types.Report{}, err
|
||||
}
|
||||
|
||||
runner, err := artifact.NewRunner(ctx, opts, artifact.TargetContainerImage)
|
||||
if err != nil {
|
||||
return types.Report{}, err
|
||||
}
|
||||
defer runner.Close(ctx)
|
||||
report := types.Report{}
|
||||
err = scanner.withTempDir(func() error {
|
||||
runner, err := artifact.NewRunner(ctx, opts, artifact.TargetContainerImage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer runner.Close(ctx)
|
||||
|
||||
report, err := runner.ScanImage(ctx, opts)
|
||||
if err != nil {
|
||||
return types.Report{}, err
|
||||
}
|
||||
report, err = runner.ScanImage(ctx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
report, err = runner.Filter(ctx, opts, report)
|
||||
if err != nil {
|
||||
return types.Report{}, err
|
||||
}
|
||||
report, err = runner.Filter(ctx, opts, report)
|
||||
|
||||
return report, nil
|
||||
return err
|
||||
})
|
||||
|
||||
return report, err
|
||||
}
|
||||
|
||||
func (scanner Scanner) IsImageFormatScannable(repo, ref string) (bool, error) {
|
||||
@@ -581,6 +607,12 @@ func (scanner Scanner) UpdateDB(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (scanner Scanner) updateDB(ctx context.Context, dbDir string) error {
|
||||
return scanner.withTempDir(func() error {
|
||||
return scanner.updateDBInternal(ctx, dbDir)
|
||||
})
|
||||
}
|
||||
|
||||
func (scanner Scanner) updateDBInternal(ctx context.Context, dbDir string) error {
|
||||
scanner.log.Debug().Str("dbDir", dbDir).Msg("download Trivy DB to destination dir")
|
||||
|
||||
registryOpts := fanalTypes.RegistryOptions{Insecure: false}
|
||||
|
||||
@@ -5,10 +5,12 @@ package trivy_test
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
xos "github.com/aquasecurity/trivy/pkg/x/os"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
@@ -287,6 +289,131 @@ func TestVulnerableLayer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithTempDirErrorHandling(t *testing.T) {
|
||||
Convey("Temp Dir error handling", t, func() {
|
||||
vulnerableLayer, err := GetLayerWithVulnerability()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
created, err := time.Parse(time.RFC3339, "2023-03-29T18:19:24Z")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
config := ispec.Image{
|
||||
Created: &created,
|
||||
Platform: ispec.Platform{
|
||||
Architecture: "amd64",
|
||||
OS: "linux",
|
||||
},
|
||||
Config: ispec.ImageConfig{
|
||||
Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
|
||||
Cmd: []string{"/bin/sh"},
|
||||
},
|
||||
RootFS: ispec.RootFS{
|
||||
Type: "layers",
|
||||
DiffIDs: []godigest.Digest{"sha256:f1417ff83b319fbdae6dd9cd6d8c9c88002dcd75ecf6ec201c8c6894681cf2b5"},
|
||||
},
|
||||
}
|
||||
|
||||
img := CreateImageWith().
|
||||
LayerBlobs([][]byte{vulnerableLayer}).
|
||||
ImageConfig(config).
|
||||
Build()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
|
||||
log := log.NewTestLogger()
|
||||
imageStore := local.NewImageStore(tempDir, false, false,
|
||||
log, monitoring.NewMetricsServer(false, log), nil, nil, nil, nil)
|
||||
|
||||
storeController := storage.StoreController{
|
||||
DefaultStore: imageStore,
|
||||
}
|
||||
|
||||
err = WriteImageToFileSystem(img, "repo", img.DigestStr(), storeController)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
params := boltdb.DBParameters{
|
||||
RootDir: tempDir,
|
||||
}
|
||||
boltDriver, err := boltdb.GetBoltDriver(params)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
metaDB, err := boltdb.New(boltDriver, log)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = meta.ParseStorage(metaDB, storeController, log)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
scanner := trivy.NewScanner(storeController, metaDB, "ghcr.io/project-zot/trivy-db", "", log)
|
||||
|
||||
// Clean up any existing temp directory first
|
||||
_ = xos.Cleanup()
|
||||
|
||||
// Get temp directory path (xos.TempDir() uses sync.OnceValues, so it won't recreate after cleanup)
|
||||
tempDirPath := xos.TempDir()
|
||||
// Manually create the directory since xos.Cleanup() removed it
|
||||
err = os.MkdirAll(tempDirPath, 0o755)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// Change permissions to 0o000 to test error handling
|
||||
err = os.Chmod(tempDirPath, 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
defer func() {
|
||||
// Clean up in case test fails
|
||||
// Note: directory may have been cleaned up by withTempDir, so we just call xos.Cleanup()
|
||||
_ = os.Chmod(tempDirPath, 0o755)
|
||||
_ = xos.Cleanup()
|
||||
}()
|
||||
|
||||
err = scanner.UpdateDB(context.Background())
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
// Verify temp directory no longer exists
|
||||
_, err = os.Stat(tempDirPath)
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
err = scanner.UpdateDB(context.Background())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// Verify temp directory no longer exists
|
||||
_, err = os.Stat(tempDirPath)
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
// Test scan with no permissions on temp directory
|
||||
// Ensure directory exists again after cleanup (xos.Cleanup() removed it)
|
||||
tempDirPath = xos.TempDir()
|
||||
err = os.MkdirAll(tempDirPath, 0o755)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = os.Chmod(tempDirPath, 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
_, err = scanner.ScanImage(context.Background(), "repo@"+img.DigestStr())
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
// Verify temp directory no longer exists
|
||||
_, err = os.Stat(tempDirPath)
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
cveMap, err := scanner.ScanImage(context.Background(), "repo@"+img.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
t.Logf("cveMap: %v", cveMap)
|
||||
// As of September 17 2023 there are 5 CVEs:
|
||||
// CVE-2023-1255, CVE-2023-2650, CVE-2023-2975, CVE-2023-3817, CVE-2023-3446
|
||||
// There may be more discovered in the future
|
||||
So(len(cveMap), ShouldBeGreaterThanOrEqualTo, 5)
|
||||
So(cveMap, ShouldContainKey, "CVE-2023-1255")
|
||||
So(cveMap, ShouldContainKey, "CVE-2023-2650")
|
||||
So(cveMap, ShouldContainKey, "CVE-2023-2975")
|
||||
So(cveMap, ShouldContainKey, "CVE-2023-3817")
|
||||
So(cveMap, ShouldContainKey, "CVE-2023-3446")
|
||||
|
||||
// Verify temp directory no longer exists
|
||||
_, err = os.Stat(tempDirPath)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestScannerErrors(t *testing.T) {
|
||||
Convey("Errors", t, func() {
|
||||
storeController := storage.StoreController{}
|
||||
|
||||
Reference in New Issue
Block a user