Files
zot/pkg/extensions/scrub/scrub_test.go
T
Piaras Hoban bc5fd1a357 feat(events): add events extension (#3045)
* feat: add events config

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* feat: implement event support with log sink

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* feat: integrate events and update tests

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* refactor: update event config

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* feat: implement http and nats sinks. remove log sink

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* refactor: events extension setup

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: cleanup tests to use nil event recorder

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: update events config example and add more logging

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* refactor: better use of build tags for minimal binary

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* fix: missing store param in evelated privileges tests

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* fix: regression in config decoding

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: update check logs script to enable cross-platform usage via GREP_BIN_PATH envvar

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: fix log lint issue for events

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: fix failing events disabled test

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: add blackbox tests for events

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: specify architecture when downloading binaries in Makefile

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: improve failure handling when no valid sinks are provided

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: fix data race in events test

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: cleanup event decoding

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: fix logging tests

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: make nats server test more reliable

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: go mod cleanup

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: add sleep when setting up nats client

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* fix: ensure event sink errors do not propogate

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: increase coverage for events

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* feat(events): Refactor events to be non-blocking from caller.

Signed-off-by: Asgeir Nilsen <asgeir.nilsen@bouvet.no>
Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: remove harded-coded linux

Co-authored-by: Andrei Aaron <andreifdaaron@gmail.com>
Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* feat(events): fail to start if incorrect event sink is configured

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* test: allow cli tests to return errors instead of panic

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

* chore: bump nats server to v2.11.3

Signed-off-by: Piaras Hoban <phoban01@gmail.com>

---------

Signed-off-by: Piaras Hoban <phoban01@gmail.com>
Signed-off-by: Asgeir Nilsen <asgeir.nilsen@bouvet.no>
Co-authored-by: Asgeir Nilsen <asgeir.nilsen@bouvet.no>
Co-authored-by: Andrei Aaron <andreifdaaron@gmail.com>
2025-05-02 12:30:06 -07:00

295 lines
8.1 KiB
Go

//go:build scrub
// +build scrub
package scrub_test
import (
"context"
"os"
"path"
"testing"
"time"
. "github.com/smartystreets/goconvey/convey"
"zotregistry.dev/zot/pkg/api"
"zotregistry.dev/zot/pkg/api/config"
extconf "zotregistry.dev/zot/pkg/extensions/config"
"zotregistry.dev/zot/pkg/extensions/monitoring"
"zotregistry.dev/zot/pkg/extensions/scrub"
"zotregistry.dev/zot/pkg/log"
"zotregistry.dev/zot/pkg/storage"
"zotregistry.dev/zot/pkg/storage/cache"
"zotregistry.dev/zot/pkg/storage/local"
test "zotregistry.dev/zot/pkg/test/common"
. "zotregistry.dev/zot/pkg/test/image-utils"
ociutils "zotregistry.dev/zot/pkg/test/oci-utils"
)
const (
repoName = "test"
)
func TestScrubExtension(t *testing.T) {
Convey("Blobs integrity not affected", t, func(c C) {
port := test.GetFreePort()
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.HTTP.Port = port
dir := t.TempDir()
subdir := t.TempDir()
conf.Storage.RootDirectory = dir
conf.Storage.Dedupe = false
conf.Storage.GC = false
substore := config.StorageConfig{RootDirectory: subdir}
conf.Storage.SubPaths = map[string]config.StorageConfig{"/a": substore}
conf.Log.Output = logFile.Name()
trueValue := true
scrubConfig := &extconf.ScrubConfig{
BaseConfig: extconf.BaseConfig{Enable: &trueValue},
Interval: 2,
}
conf.Extensions = &extconf.ExtensionConfig{
Scrub: scrubConfig,
}
ctlr := api.NewController(conf)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
err = WriteImageToFileSystem(CreateDefaultVulnerableImage(), repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
found, err := test.ReadLogFileAndSearchString(logFile.Name(), "blobs/manifest ok", 60*time.Second)
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
})
Convey("Blobs integrity affected", t, func(c C) {
port := test.GetFreePort()
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.HTTP.Port = port
dir := t.TempDir()
conf.Storage.RootDirectory = dir
conf.Storage.Dedupe = false
conf.Storage.GC = false
conf.Log.Output = logFile.Name()
trueValue := true
scrubConfig := &extconf.ScrubConfig{
BaseConfig: extconf.BaseConfig{Enable: &trueValue},
Interval: 2,
}
conf.Extensions = &extconf.ExtensionConfig{
Scrub: scrubConfig,
}
ctlr := api.NewController(conf)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
image := CreateDefaultVulnerableImage()
err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
layerDigest := image.Manifest.Layers[0].Digest
err = os.Remove(path.Join(dir, repoName, "blobs/sha256", layerDigest.Encoded()))
if err != nil {
panic(err)
}
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
found, err := test.ReadLogFileAndSearchString(logFile.Name(), "blobs/manifest affected", 60*time.Second)
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
})
Convey("Generator error - not enough permissions to access root directory", t, func(c C) {
port := test.GetFreePort()
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.HTTP.Port = port
dir := t.TempDir()
conf.Storage.RootDirectory = dir
conf.Storage.Dedupe = false
conf.Storage.GC = false
conf.Log.Output = logFile.Name()
trueValue := true
scrubConfig := &extconf.ScrubConfig{
BaseConfig: extconf.BaseConfig{Enable: &trueValue},
Interval: 2,
}
conf.Extensions = &extconf.ExtensionConfig{
Scrub: scrubConfig,
}
ctlr := api.NewController(conf)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
image := CreateDefaultVulnerableImage()
err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
So(os.Chmod(path.Join(dir, repoName), 0o000), ShouldBeNil)
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()
found, err := test.ReadLogFileAndSearchString(logFile.Name(), "failed to execute generator", 60*time.Second)
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
So(os.Chmod(path.Join(dir, repoName), 0o755), ShouldBeNil)
})
}
func TestRunScrubRepo(t *testing.T) {
Convey("Blobs integrity not affected", t, func(c C) {
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.Extensions = &extconf.ExtensionConfig{}
conf.Extensions.Lint = &extconf.LintConfig{}
dir := t.TempDir()
log := log.NewLogger("debug", logFile.Name())
metrics := monitoring.NewMetricsServer(false, log)
cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{
RootDir: dir,
Name: "cache",
UseRelPaths: true,
}, log)
imgStore := local.NewImageStore(dir, true,
true, log, metrics, nil, cacheDriver, nil, nil)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log)
image := CreateDefaultVulnerableImage()
err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log)
So(err, ShouldBeNil)
data, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(data), ShouldContainSubstring, "blobs/manifest ok")
})
Convey("Blobs integrity affected", t, func(c C) {
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.Extensions = &extconf.ExtensionConfig{}
conf.Extensions.Lint = &extconf.LintConfig{}
dir := t.TempDir()
log := log.NewLogger("debug", logFile.Name())
metrics := monitoring.NewMetricsServer(false, log)
cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{
RootDir: dir,
Name: "cache",
UseRelPaths: true,
}, log)
imgStore := local.NewImageStore(dir, true,
true, log, metrics, nil, cacheDriver, nil, nil)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log)
image := CreateDefaultVulnerableImage()
err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
layerDigest := image.Manifest.Layers[0].Digest
err = os.Remove(path.Join(dir, repoName, "blobs/sha256", layerDigest.Encoded()))
if err != nil {
panic(err)
}
err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log)
So(err, ShouldBeNil)
data, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(data), ShouldContainSubstring, "blobs/manifest affected")
})
Convey("CheckRepo error - not enough permissions to access root directory", t, func(c C) {
logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
defer os.Remove(logFile.Name()) // clean up
conf := config.New()
conf.Extensions = &extconf.ExtensionConfig{}
conf.Extensions.Lint = &extconf.LintConfig{}
dir := t.TempDir()
log := log.NewLogger("debug", logFile.Name())
metrics := monitoring.NewMetricsServer(false, log)
cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{
RootDir: dir,
Name: "cache",
UseRelPaths: true,
}, log)
imgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver, nil, nil)
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log)
image := CreateDefaultVulnerableImage()
err = WriteImageToFileSystem(image, repoName, "0.0.1", srcStorageCtlr)
So(err, ShouldBeNil)
So(os.Chmod(path.Join(dir, repoName), 0o000), ShouldBeNil)
err = scrub.RunScrubRepo(context.Background(), imgStore, repoName, log)
So(err, ShouldNotBeNil)
data, err := os.ReadFile(logFile.Name())
So(err, ShouldBeNil)
So(string(data), ShouldContainSubstring,
"failed to run scrub for "+imgStore.RootDir())
So(os.Chmod(path.Join(dir, repoName), 0o755), ShouldBeNil)
})
}