feat: allow disabling CVE independently from search

Agent-Logs-Url: https://github.com/project-zot/zot/sessions/9b89c154-fd36-4315-9910-9c19f96e2417

Co-authored-by: rchincha <45800463+rchincha@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-05-26 05:37:30 +00:00
committed by GitHub
parent d8a53b7096
commit b5ed56f07d
4 changed files with 135 additions and 29 deletions
+70
View File
@@ -100,6 +100,41 @@ func TestVerifyExtensionsConfig(t *testing.T) {
So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil)
})
Convey("Test verify CVE can be explicitly disabled for remote storage", t, func(c C) {
content := fmt.Sprintf(`{
"storage":{
"rootDirectory":"%s",
"dedupe":true,
"remoteCache":false,
"storageDriver":{
"name":"s3",
"rootdirectory":"/zot",
"region":"us-east-2",
"bucket":"zot-storage",
"secure":true,
"skipverify":false
}
},
"http":{
"address":"127.0.0.1",
"port":"8080"
},
"extensions":{
"search": {
"enable": true,
"cve": {
"enable": false
}
}
}
}`, t.TempDir())
tmpfile := MakeTempFileWithContent(t, "zot-test.json", content)
os.Args = []string{"cli_test", "verify", tmpfile}
So(cli.NewServerRootCmd().Execute(), ShouldBeNil)
})
Convey("Test verify w/ sync and w/o filesystem storage", t, func(c C) {
content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s", "storageDriver": {"name": "s3"}},
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
@@ -1099,6 +1134,41 @@ func TestServeSearchEnabledNoCVE(t *testing.T) {
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
})
Convey("search explicitly enabled, and CVE explicitly disabled", t, func(c C) {
content := `{
"storage": {
"rootDirectory": "%s"
},
"http": {
"address": "127.0.0.1",
"port": "%s"
},
"log": {
"level": "debug",
"output": "%s"
},
"extensions": {
"search": {
"enable": true,
"cve": {
"enable": false
}
}
}
}`
logPath, _, err := runCLIWithConfig(t, content)
So(err, ShouldBeNil)
found, err := ReadLogFileAndSearchString(logPath, `"CVE":{"Enable":false`, readLogFileTimeout)
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
found, err = ReadLogFileAndSearchString(logPath, "cve config not provided, skipping cve-db update", readLogFileTimeout)
So(found, ShouldBeTrue)
So(err, ShouldBeNil)
})
}
func TestServeSearchDisabled(t *testing.T) {
+33 -27
View File
@@ -874,41 +874,47 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, logge
}
if *config.Extensions.Search.Enable && config.Extensions.Search.CVE != nil {
defaultUpdateInterval, _ := time.ParseDuration("2h")
if config.Extensions.Search.CVE.UpdateInterval < defaultUpdateInterval {
config.Extensions.Search.CVE.UpdateInterval = defaultUpdateInterval
logger.Warn().Msg("cve update interval set to too-short interval < 2h, " +
"changing update duration to 2 hours and continuing.")
if config.Extensions.Search.CVE.Enable == nil {
config.Extensions.Search.CVE.Enable = &defaultVal
}
if config.Extensions.Search.CVE.Trivy == nil {
config.Extensions.Search.CVE.Trivy = &extconf.TrivyConfig{}
}
if *config.Extensions.Search.CVE.Enable {
defaultUpdateInterval, _ := time.ParseDuration("2h")
if config.Extensions.Search.CVE.Trivy.DBRepository == "" {
defaultDBDownloadURL := "ghcr.io/aquasecurity/trivy-db"
logger.Info().Str("url", defaultDBDownloadURL).Str("component", "config").
Msg("using default trivy-db download URL.")
if config.Extensions.Search.CVE.UpdateInterval < defaultUpdateInterval {
config.Extensions.Search.CVE.UpdateInterval = defaultUpdateInterval
config.Extensions.Search.CVE.Trivy.DBRepository = defaultDBDownloadURL
}
logger.Warn().Msg("cve update interval set to too-short interval < 2h, " +
"changing update duration to 2 hours and continuing.")
}
if config.Extensions.Search.CVE.Trivy.JavaDBRepository == "" {
defaultJavaDBDownloadURL := "ghcr.io/aquasecurity/trivy-java-db"
logger.Info().Str("url", defaultJavaDBDownloadURL).Str("component", "config").
Msg("using default trivy-java-db download URL.")
if config.Extensions.Search.CVE.Trivy == nil {
config.Extensions.Search.CVE.Trivy = &extconf.TrivyConfig{}
}
config.Extensions.Search.CVE.Trivy.JavaDBRepository = defaultJavaDBDownloadURL
}
if config.Extensions.Search.CVE.Trivy.DBRepository == "" {
defaultDBDownloadURL := "ghcr.io/aquasecurity/trivy-db"
logger.Info().Str("url", defaultDBDownloadURL).Str("component", "config").
Msg("using default trivy-db download URL.")
if len(config.Extensions.Search.CVE.Trivy.VulnSeveritySources) == 0 {
defaultVulnSeveritySources := []string{"auto"}
logger.Info().Strs("vulnSeveritySources", defaultVulnSeveritySources).Str("component", "config").
Msg("using default trivy vulnerability severity sources.")
config.Extensions.Search.CVE.Trivy.DBRepository = defaultDBDownloadURL
}
config.Extensions.Search.CVE.Trivy.VulnSeveritySources = defaultVulnSeveritySources
if config.Extensions.Search.CVE.Trivy.JavaDBRepository == "" {
defaultJavaDBDownloadURL := "ghcr.io/aquasecurity/trivy-java-db"
logger.Info().Str("url", defaultJavaDBDownloadURL).Str("component", "config").
Msg("using default trivy-java-db download URL.")
config.Extensions.Search.CVE.Trivy.JavaDBRepository = defaultJavaDBDownloadURL
}
if len(config.Extensions.Search.CVE.Trivy.VulnSeveritySources) == 0 {
defaultVulnSeveritySources := []string{"auto"}
logger.Info().Strs("vulnSeveritySources", defaultVulnSeveritySources).Str("component", "config").
Msg("using default trivy vulnerability severity sources.")
config.Extensions.Search.CVE.Trivy.VulnSeveritySources = defaultVulnSeveritySources
}
}
}
}
+10 -2
View File
@@ -53,6 +53,7 @@ type SearchConfig struct {
}
type CVEConfig struct {
Enable *bool `mapstructure:",omitempty" json:",omitempty"`
UpdateInterval time.Duration // should be 2 hours or more, if not specified default be kept as 2 hours
Trivy *TrivyConfig
}
@@ -109,8 +110,15 @@ func (e *ExtensionConfig) IsCveScanningEnabled() bool {
return false
}
return e.Search != nil && e.Search.Enable != nil && *e.Search.Enable &&
e.Search.CVE != nil && e.Search.CVE.Trivy != nil
if e.Search == nil || e.Search.Enable == nil || !*e.Search.Enable || e.Search.CVE == nil {
return false
}
if e.Search.CVE.Enable != nil && !*e.Search.CVE.Enable {
return false
}
return e.Search.CVE.Trivy != nil
}
// IsEventRecorderEnabled checks if event recording is enabled in this extensions config.
+22
View File
@@ -44,6 +44,22 @@ func buildSearchConfigWithCVE(enabled bool) *config.ExtensionConfig {
return ext
}
func buildSearchConfigWithCVEDisabled(enabled bool) *config.ExtensionConfig {
disabled := false
ext := &config.ExtensionConfig{}
ext.Search = &config.SearchConfig{
BaseConfig: config.BaseConfig{
Enable: &enabled,
},
CVE: &config.CVEConfig{
Enable: &disabled,
Trivy: &config.TrivyConfig{},
},
}
return ext
}
func buildEventsConfig(enabled bool) *config.ExtensionConfig {
ext := &config.ExtensionConfig{}
ext.Events = &events.Config{
@@ -302,6 +318,12 @@ func TestExtensionConfig(t *testing.T) {
testMethodWithNilEnable("Search", (*config.ExtensionConfig).IsCveScanningEnabled)
testMethodWithDisabledEnable("Search", (*config.ExtensionConfig).IsCveScanningEnabled, buildSearchConfig)
testMethodWithEnabledEnable("Search", (*config.ExtensionConfig).IsCveScanningEnabled, buildSearchConfigWithCVE)
Convey("Test with search enabled but cve explicitly disabled", func() {
enabled := true
extensionConfig := buildSearchConfigWithCVEDisabled(enabled)
So(extensionConfig.IsCveScanningEnabled(), ShouldBeFalse)
})
})
Convey("Test IsEventRecorderEnabled()", func() {