Repository: ratify-project/ratify
Pull request #2008 (2025-01-02 22:30:53)

chore: automated PR to main 2025-01-02
Automated Pull Request to main branch


Patch:
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index f3c43e6..0dd6e71 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -24,7 +24,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        KUBERNETES_VERSION: ["1.30.6"]
+        KUBERNETES_VERSION: ["1.31.2"]
         GATEKEEPER_VERSION: ["3.18.0"]
     uses: ./.github/workflows/e2e-k8s.yml
     with:
@@ -37,7 +37,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        KUBERNETES_VERSION: ["1.29.10", "1.30.6"]
+        KUBERNETES_VERSION: ["1.30.6", "1.31.2"]
         GATEKEEPER_VERSION: ["3.16.0", "3.17.0", "3.18.0"]
     uses: ./.github/workflows/e2e-k8s.yml
     with:
@@ -53,7 +53,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        KUBERNETES_VERSION: ["1.29.10", "1.30.6"]
+        KUBERNETES_VERSION: ["1.30.6", "1.31.2"] 
         GATEKEEPER_VERSION: ["3.16.0", "3.17.0", "3.18.0"]
     uses: ./.github/workflows/e2e-aks.yml
     with:
diff --git a/.github/workflows/run-full-validation.yml b/.github/workflows/run-full-validation.yml
index b1f3042..62a6127 100644
--- a/.github/workflows/run-full-validation.yml
+++ b/.github/workflows/run-full-validation.yml
@@ -26,7 +26,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        KUBERNETES_VERSION: ["1.29.10", "1.30.6"]
+        KUBERNETES_VERSION: ["1.30.6", "1.31.2"]
         GATEKEEPER_VERSION: ["3.16.0", "3.17.0", "3.18.0"]
     uses: ./.github/workflows/e2e-k8s.yml
     with:
@@ -41,7 +41,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        KUBERNETES_VERSION: ["1.29.10", "1.30.6"]
+        KUBERNETES_VERSION: ["1.30.6", "1.31.2"]
         GATEKEEPER_VERSION: ["3.16.0", "3.17.0", "3.18.0"]
     uses: ./.github/workflows/e2e-aks.yml
     with:
diff --git a/charts/ratify/README.md b/charts/ratify/README.md
index 721328e..544abe3 100644
--- a/charts/ratify/README.md
+++ b/charts/ratify/README.md
@@ -135,6 +135,7 @@ Values marked `# DEPRECATED` in the `values.yaml` as well as **DEPRECATED** in t
 | logger.formatter                                   | Type of log formatter. Can be set to `text`, `json` or `logstash` output                                                                                                                                                                                                                                                                                               | `text`                            |
 | logger.level                                       | Sets the log level                                                                                                                                                                                                                                                                                                                                                     | `info`                            |
 | logger.requestHeaders.traceIDHeaderName            | List of headers that include the trace ID in the external data requests to Ratify. The same headers will be passed to upstream services like remote registries. e.g. Set it to `x-ms-correlation-request-id` to trace across Azure.                                                                                                                                    | `[]`                              |
+| crl.cache.enabled                                   | Enables/disables CRL Cache                                                                                                                                                                                                                                                                                                                                                      | `true`                           |
 | featureFlags.RATIFY_CERT_ROTATION                  | Enables/disables tls certificate rotation                                                                                                                                                                                                                                                                                                                              | `false`                           |
 | featureFlags.RATIFY_EXPERIMENTAL_HIGH_AVAILABILITY | **EXPERIMENTAL** Enables/disables high availability mode including distributed caching.                                                                                                                                                                                                                                                                                | `false`                           |
 | azureWorkloadIdentity.clientId                     | ClientID of AAD application/Managed identity associated with Workload Identity                                                                                                                                                                                                                                                                                         | ``                                |
diff --git a/charts/ratify/templates/configmap.yaml b/charts/ratify/templates/configmap.yaml
index b1812d0..fab6a49 100644
--- a/charts/ratify/templates/configmap.yaml
+++ b/charts/ratify/templates/configmap.yaml
@@ -14,5 +14,10 @@ data:
       "executor": {
         "verificationRequestTimeout": {{ .Values.provider.timeout.validationTimeoutSeconds | int | mul 1000 | add -100 }},
         "mutationRequestTimeout": {{ .Values.provider.timeout.mutationTimeoutSeconds | int | mul 1000 | add -50 }}
+      },
+      "crl": {
+        "cache": {
+          "enabled": {{ default "true" .Values.crl.cache.enabled }}
+        }
       }
     }
\ No newline at end of file
diff --git a/charts/ratify/templates/verifier.yaml b/charts/ratify/templates/verifier.yaml
index bdf9532..cfbafe2 100644
--- a/charts/ratify/templates/verifier.yaml
+++ b/charts/ratify/templates/verifier.yaml
@@ -101,10 +101,11 @@ spec:
             {{- end }}
           {{- end}}
           trustedIdentities:
-            {{- range $j, $store := $policy.trustedIdentities }}
-            {{- if eq $store "*" }}
+            {{- $trustedIdentities := $policy.trustedIdentities | default (list "*") }}
+            {{- range $j, $identity := $trustedIdentities }}
+            {{- if eq $identity "*" }}
             - "*"
-            {{- else }} 
+            {{- else }}
             - "x509.subject: {{ . }}"
             {{- end }}
             {{- end }}
diff --git a/charts/ratify/values.yaml b/charts/ratify/values.yaml
index 4331702..c60c219 100644
--- a/charts/ratify/values.yaml
+++ b/charts/ratify/values.yaml
@@ -168,6 +168,10 @@ logger:
     traceIDHeaderName: # List of headers that include the trace ID in the external data requests to Ratify. The same headers will be passed to upstream services like remote registries.
       - "" # e.g. Set it to `x-ms-correlation-request-id` to trace across Azure.
 
+crl:
+  cache:
+    enabled: true # Enable CRL cache
+
 # See https://ratify.dev/docs/reference/usage#feature-flags for a list of available feature flags
 featureFlags:
   # RATIFY_FEATURE_NAME: true
diff --git a/cmd/ratify/cmd/verify.go b/cmd/ratify/cmd/verify.go
index c189fa6..ab24e95 100644
--- a/cmd/ratify/cmd/verify.go
+++ b/cmd/ratify/cmd/verify.go
@@ -91,6 +91,8 @@ func verify(opts verifyCmdOptions) error {
 		logger.GetLogger(context.Background(), logOpt).Warn(taggedReferenceWarning)
 	}
 
+	config.CRLConf = cf.CRLConfig
+
 	stores, err := sf.CreateStoresFromConfig(cf.StoresConfig, config.GetDefaultPluginPath())
 
 	if err != nil {
diff --git a/config/config.go b/config/config.go
index 7bc3e0f..e2a556c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -52,6 +52,7 @@ type Config struct {
 	PoliciesConfig  pcConfig.PoliciesConfig  `json:"policy,omitempty"`
 	VerifiersConfig vfConfig.VerifiersConfig `json:"verifier,omitempty"`
 	ExecutorConfig  exConfig.ExecutorConfig  `json:"executor,omitempty"`
+	CRLConfig       CRLConfig                `json:"crl,omitempty"`
 	LoggerConfig    logger.Config            `json:"logger,omitempty"`
 	fileHash        string                   `json:"-"`
 }
diff --git a/config/configManager.go b/config/configManager.go
index cce09c6..5946e70 100644
--- a/config/configManager.go
+++ b/config/configManager.go
@@ -31,6 +31,7 @@ type GetExecutor func(context.Context) *ef.Executor
 var (
 	configHash string
 	executor   ef.Executor
+	CRLConf    CRLConfig
 )
 
 // Create a executor from configurationFile and setup config file watcher
@@ -43,6 +44,7 @@ func GetExecutorAndWatchForUpdate(configFilePath string) (GetExecutor, error) {
 	}
 
 	configHash = cf.fileHash
+	CRLConf = cf.CRLConfig
 
 	stores, verifiers, policyEnforcer, err := CreateFromConfig(cf)
 
diff --git a/config/crlConfig.go b/config/crlConfig.go
new file mode 100644
index 0000000..f000349
--- /dev/null
+++ b/config/crlConfig.go
@@ -0,0 +1,24 @@
+/*
+Copyright The Ratify Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package config
+
+type CRLConfig struct {
+	Cache Cache `json:"cache,omitempty"`
+}
+
+type Cache struct {
+	Enabled bool `json:"enabled,omitempty"`
+}
diff --git a/httpserver/Dockerfile b/httpserver/Dockerfile
index 20c4486..b134a05 100644
--- a/httpserver/Dockerfile
+++ b/httpserver/Dockerfile
@@ -11,7 +11,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM --platform=$BUILDPLATFORM golang:1.23@sha256:70031844b8c225351d0bb63e2c383f80db85d92ba894e3da7e13bcf80efa9a37 as builder
+FROM --platform=$BUILDPLATFORM golang:1.23@sha256:7ea4c9dcb2b97ff8ee80a67db3d44f98c8ffa0d191399197007d8459c1453041 as builder
 
 ARG TARGETPLATFORM
 ARG TARGETOS
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh.go b/pkg/keymanagementprovider/refresh/kubeRefresh.go
index cd296e0..b2f1e85 100644
--- a/pkg/keymanagementprovider/refresh/kubeRefresh.go
+++ b/pkg/keymanagementprovider/refresh/kubeRefresh.go
@@ -120,6 +120,6 @@ func (kr *KubeRefresher) Create(config RefresherConfig) (Refresher, error) {
 		ProviderType:            config.ProviderType,
 		ProviderRefreshInterval: config.ProviderRefreshInterval,
 		Resource:                config.Resource,
-		CRLHandler:              nv.NewCRLHandler(),
+		CRLHandler:              nv.CreateCRLHandlerFromConfig(),
 	}, nil
 }
diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go
index 6726f39..b5e6e0d 100644
--- a/pkg/manager/manager.go
+++ b/pkg/manager/manager.go
@@ -82,7 +82,7 @@ func StartServer(httpServerAddress, configFilePath, certDirectory, caCertFile st
 		logrus.Errorf("server start failed %v", fmt.Errorf("error loading config %w", err))
 		os.Exit(1)
 	}
-
+	config.CRLConf = cf.CRLConfig
 	// initialize server
 	server, err := httpserver.NewServer(context.Background(), httpServerAddress, func(ctx context.Context) *ef.Executor {
 		namespace := ctxUtils.GetNamespace(ctx)
diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go
index de54857..2453719 100644
--- a/pkg/verifier/notation/notation.go
+++ b/pkg/verifier/notation/notation.go
@@ -106,7 +106,7 @@ func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.V
 	if err != nil {
 		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
 	}
-	verifyService, err := getVerifierService(ctx, conf, pluginDirectory, NewCRLHandler())
+	verifyService, err := getVerifierService(ctx, conf, pluginDirectory, CreateCRLHandlerFromConfig())
 	if err != nil {
 		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
 	}
diff --git a/pkg/verifier/notation/notationrevocationfactory.go b/pkg/verifier/notation/notationrevocationfactory.go
index b8687f5..1a9683a 100644
--- a/pkg/verifier/notation/notationrevocationfactory.go
+++ b/pkg/verifier/notation/notationrevocationfactory.go
@@ -20,20 +20,26 @@ import (
 	"github.com/notaryproject/notation-core-go/revocation"
 	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
 	"github.com/notaryproject/notation-go/dir"
+	"github.com/ratify-project/ratify/config"
 	re "github.com/ratify-project/ratify/errors"
 )
 
 type CRLHandler struct {
 	CacheEnabled bool
-	Fetcher      corecrl.Fetcher
 	httpClient   *http.Client
 }
 
-var fetcherOnce sync.Once
+var (
+	fetcherOnce   sync.Once
+	globalFetcher corecrl.Fetcher
+)
 
-// NewCRLHandler returns a new NewCRLHandler instance. Enable cache by default.
-func NewCRLHandler() RevocationFactory {
-	return &CRLHandler{CacheEnabled: true, httpClient: &http.Client{}}
+// CreateCRLHandlerFromConfig creates a new instance of CRLHandler using the configuration
+// provided in config.CRLConf. It returns a RevocationFactory interface.
+// The CRLHandler will have its CacheDisabled field set based on the configuration,
+// and it will use a default HTTP client.
+func CreateCRLHandlerFromConfig() RevocationFactory {
+	return &CRLHandler{CacheEnabled: config.CRLConf.Cache.Enabled, httpClient: &http.Client{}}
 }
 
 // NewFetcher creates a new instance of a Fetcher if it doesn't already exist.
@@ -43,10 +49,7 @@ func NewCRLHandler() RevocationFactory {
 func (h *CRLHandler) NewFetcher() (corecrl.Fetcher, error) {
 	var err error
 	fetcherOnce.Do(func() {
-		h.Fetcher, err = CreateCRLFetcher(h.httpClient, dir.PathCRLCache)
-		if err == nil {
-			h.configureCache()
-		}
+		globalFetcher, err = CreateCRLFetcher(h.httpClient, dir.PathCRLCache)
 	})
 	if err != nil {
 		return nil, err
@@ -54,24 +57,13 @@ func (h *CRLHandler) NewFetcher() (corecrl.Fetcher, error) {
 	// Check if the fetcher is nil, return an error if it is.
 	// one possible edge case is that an error happened in the first call,
 	// the following calls will not get the error since the sync.Once block will be skipped.
-	if h.Fetcher == nil {
+	if globalFetcher == nil {
 		return nil, re.ErrorCodeConfigInvalid.WithDetail("failed to create CRL fetcher")
 	}
-	return h.Fetcher, nil
+	return globalFetcher, nil
 }
 
 // NewValidator returns a new validator instance
 func (h *CRLHandler) NewValidator(opts revocation.Options) (revocation.Validator, error) {
 	return revocation.NewWithOptions(opts)
 }
-
-// configureCache disables the cache for the HTTPFetcher if caching is not enabled.
-// If the EnableCache field is set to false, this method sets the Cache field of the
-// HTTPFetcher to nil, effectively disabling caching for HTTP fetch operations.
-func (h *CRLHandler) configureCache() {
-	if !h.CacheEnabled {
-		if httpFetcher, ok := h.Fetcher.(*corecrl.HTTPFetcher); ok {
-			httpFetcher.Cache = nil
-		}
-	}
-}
diff --git a/pkg/verifier/notation/revocationfactory.go b/pkg/verifier/notation/revocationfactory.go
index d0c576f..73486bb 100644
--- a/pkg/verifier/notation/revocationfactory.go
+++ b/pkg/verifier/notation/revocationfactory.go
@@ -23,6 +23,7 @@ import (
 	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
 	"github.com/notaryproject/notation-go/dir"
 	"github.com/notaryproject/notation-go/verifier/crl"
+	"github.com/ratify-project/ratify/config"
 	"github.com/ratify-project/ratify/internal/logger"
 )
 
@@ -43,10 +44,14 @@ func CreateCRLFetcher(httpClient *http.Client, cacheRoot string) (corecrl.Fetche
 	if err != nil {
 		return nil, err
 	}
-	crlFetcher.Cache, err = newFileCache(cacheRoot)
+	if !config.CRLConf.Cache.Enabled {
+		return crlFetcher, nil
+	}
+	cache, err := newFileCache(cacheRoot)
 	if err != nil {
 		return nil, err
 	}
+	crlFetcher.Cache = cache
 	return crlFetcher, nil
 }
 


Test patch:
diff --git a/.github/workflows/e2e-aks.yml b/.github/workflows/e2e-aks.yml
index f992ac8..1edd4a7 100644
--- a/.github/workflows/e2e-aks.yml
+++ b/.github/workflows/e2e-aks.yml
@@ -9,7 +9,7 @@ on:
       k8s_version:
         description: "Kubernetes version"
         required: true
-        default: "1.30.6"
+        default: "1.31.2"
         type: string
       gatekeeper_version:
         description: "Gatekeeper version"
diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml
index f7a7186..aeb8d46 100644
--- a/.github/workflows/e2e-k8s.yml
+++ b/.github/workflows/e2e-k8s.yml
@@ -9,7 +9,7 @@ on:
       k8s_version:
         description: "Kubernetes version"
         required: true
-        default: "1.30.6"
+        default: "1.31.2"
         type: string
       gatekeeper_version:
         description: "Gatekeeper version"
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go b/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
index 0e930f9..859180e 100644
--- a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
+++ b/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
@@ -55,7 +55,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters: []byte(`{"contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
 			providerType:          "inline",
 			IsRefreshableFunc:     func() bool { return false },
-			NewCRLHandler:         nv.NewCRLHandler(),
+			NewCRLHandler:         nv.CreateCRLHandlerFromConfig(),
 			expectedResult:        ctrl.Result{},
 			expectedError:         false,
 		},
@@ -64,7 +64,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
 			providerType:            "test-kmp",
 			providerRefreshInterval: "",
-			NewCRLHandler:           nv.NewCRLHandler(),
+			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
 			IsRefreshableFunc:       func() bool { return true },
 			expectedResult:          ctrl.Result{},
 			expectedError:           false,
@@ -74,7 +74,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
 			providerType:            "test-kmp",
 			providerRefreshInterval: "1m",
-			NewCRLHandler:           nv.NewCRLHandler(),
+			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
 			IsRefreshableFunc:       func() bool { return true },
 			expectedResult:          ctrl.Result{RequeueAfter: time.Minute},
 			expectedError:           false,
@@ -84,7 +84,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
 			providerType:            "test-kmp",
 			providerRefreshInterval: "1mm",
-			NewCRLHandler:           nv.NewCRLHandler(),
+			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
 			IsRefreshableFunc:       func() bool { return true },
 			expectedResult:          ctrl.Result{},
 			expectedError:           true,
@@ -98,7 +98,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
 			providerType:          "test-kmp-error",
 			IsRefreshableFunc:     func() bool { return true },
-			NewCRLHandler:         nv.NewCRLHandler(),
+			NewCRLHandler:         nv.CreateCRLHandlerFromConfig(),
 			expectedError:         true,
 		},
 		{
@@ -110,7 +110,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerRawParameters: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
 			providerType:          "test-kmp-error",
 			IsRefreshableFunc:     func() bool { return true },
-			NewCRLHandler:         nv.NewCRLHandler(),
+			NewCRLHandler:         nv.CreateCRLHandlerFromConfig(),
 			expectedError:         true,
 		},
 		{
@@ -124,7 +124,7 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 			providerType:            "test-kmp",
 			providerRefreshInterval: "1m",
 			IsRefreshableFunc:       func() bool { return true },
-			NewCRLHandler:           &MockCRLHandler{CacheEnabled: true, httpClient: &http.Client{}},
+			NewCRLHandler:           &MockCRLHandler{CacheDisabled: false, httpClient: &http.Client{}},
 			expectedResult:          ctrl.Result{RequeueAfter: time.Minute},
 			expectedError:           false,
 		},
@@ -172,9 +172,8 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 }
 
 type MockCRLHandler struct {
-	CacheEnabled bool
-	Fetcher      corecrl.Fetcher
-	httpClient   *http.Client
+	CacheDisabled bool
+	httpClient    *http.Client
 }
 
 func (h *MockCRLHandler) NewFetcher() (corecrl.Fetcher, error) {
@@ -188,7 +187,7 @@ func (h *MockCRLHandler) NewValidator(_ revocation.Options) (revocation.Validato
 func TestKubeRefresher_GetResult(t *testing.T) {
 	kr := &KubeRefresher{
 		Result:     ctrl.Result{RequeueAfter: time.Minute},
-		CRLHandler: nv.NewCRLHandler(),
+		CRLHandler: nv.CreateCRLHandlerFromConfig(),
 	}
 
 	result := kr.GetResult()
@@ -204,7 +203,7 @@ func TestKubeRefresher_GetStatus(t *testing.T) {
 			"attribute1": "value1",
 			"attribute2": "value2",
 		},
-		CRLHandler: nv.NewCRLHandler(),
+		CRLHandler: nv.CreateCRLHandlerFromConfig(),
 	}
 
 	status := kr.GetStatus()
@@ -253,7 +252,7 @@ func TestKubeRefresher_Create(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			kr := &KubeRefresher{CRLHandler: nv.NewCRLHandler()}
+			kr := &KubeRefresher{CRLHandler: nv.CreateCRLHandlerFromConfig()}
 			refresher, err := kr.Create(tt.config)
 			if err != nil {
 				t.Fatalf("Expected no error, but got %v", err)
diff --git a/pkg/verifier/notation/notationrevocationfactory_test.go b/pkg/verifier/notation/notationrevocationfactory_test.go
index d30e619..1cbd43e 100644
--- a/pkg/verifier/notation/notationrevocationfactory_test.go
+++ b/pkg/verifier/notation/notationrevocationfactory_test.go
@@ -14,20 +14,18 @@
 package notation
 
 import (
-	"context"
 	"net/http"
 	"runtime"
 	"testing"
 
 	"github.com/notaryproject/notation-core-go/revocation"
-	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
 	"github.com/notaryproject/notation-go/dir"
-	"github.com/notaryproject/notation-go/verifier/crl"
+	re "github.com/ratify-project/ratify/errors"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestNewRevocationFactoryImpl(t *testing.T) {
-	factory := NewCRLHandler()
+	factory := CreateCRLHandlerFromConfig()
 	assert.NotNil(t, factory)
 }
 
@@ -37,35 +35,45 @@ func TestNewFetcher(t *testing.T) {
 		cacheRoot  string
 		httpClient *http.Client
 		wantErr    bool
+		firstCall  bool
 	}{
 		{
-			name:       "valid fetcher",
-			cacheRoot:  "/valid/path",
-			httpClient: &http.Client{},
-			wantErr:    false,
-		},
-		{
-			name:       "invalid fetcher",
+			name:       "create CRL fetcher failure with nil httpClient on first call",
 			cacheRoot:  "",
 			httpClient: nil,
+			firstCall:  true,
+			wantErr:    true,
+		},
+		{
+			name:       "recreate CRL fetcher failure on second call",
+			cacheRoot:  "/valid/path",
+			httpClient: &http.Client{},
+			firstCall:  false,
 			wantErr:    true,
 		},
 	}
-
+	globalFetcher = nil
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			factory := &CRLHandler{httpClient: tt.httpClient}
 			fetcher, err := factory.NewFetcher()
-			if tt.wantErr {
-				assert.Error(t, err)
+			if tt.firstCall {
+				// Fetcher is initialized in sequential execution before this test, skip the test to avoid test failure
+				t.Skip("skipping on first call")
+			}
+			if !tt.firstCall && tt.wantErr {
 				assert.Nil(t, fetcher)
+				assert.Nil(t, globalFetcher)
+				assert.Equal(t, err, re.ErrorCodeConfigInvalid.WithDetail("failed to create CRL fetcher"))
 			}
 		})
 	}
+	// fix globalFetcher to avoid test failure
+	globalFetcher, _ = CreateCRLFetcher(&http.Client{}, dir.PathCRLCache)
 }
 
 func TestNewValidator(t *testing.T) {
-	factory := NewCRLHandler()
+	factory := CreateCRLHandlerFromConfig()
 	opts := revocation.Options{}
 
 	validator, err := factory.NewValidator(opts)
@@ -101,55 +109,3 @@ func TestNewFileCache(t *testing.T) {
 		})
 	}
 }
-func TestConfigureCache(t *testing.T) {
-	testCache, _ := crl.NewFileCache(dir.PathCRLCache)
-	tests := []struct {
-		name         string
-		cacheEnabled bool
-		fetcher      corecrl.Fetcher
-		expectCache  bool
-	}{
-		{
-			name:         "cache enabled",
-			cacheEnabled: true,
-			fetcher:      &corecrl.HTTPFetcher{Cache: testCache},
-			expectCache:  true,
-		},
-		{
-			name:         "cache disabled",
-			cacheEnabled: false,
-			fetcher:      &corecrl.HTTPFetcher{Cache: testCache},
-			expectCache:  false,
-		},
-		{
-			name:         "non-HTTP fetcher",
-			cacheEnabled: false,
-			fetcher:      &mockFetcher{},
-			expectCache:  false,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			handler := &CRLHandler{
-				CacheEnabled: tt.cacheEnabled,
-				Fetcher:      tt.fetcher,
-			}
-			handler.configureCache()
-
-			if httpFetcher, ok := handler.Fetcher.(*corecrl.HTTPFetcher); ok {
-				if tt.expectCache {
-					assert.NotNil(t, httpFetcher.Cache)
-				} else {
-					assert.Nil(t, httpFetcher.Cache)
-				}
-			}
-		})
-	}
-}
-
-type mockFetcher struct{}
-
-func (m *mockFetcher) Fetch(_ context.Context, _ string) (*corecrl.Bundle, error) {
-	return nil, nil
-}
diff --git a/pkg/verifier/notation/revocationfactory_test.go b/pkg/verifier/notation/revocationfactory_test.go
index 8b29503..79f9766 100644
--- a/pkg/verifier/notation/revocationfactory_test.go
+++ b/pkg/verifier/notation/revocationfactory_test.go
@@ -21,26 +21,10 @@ import (
 	"testing"
 
 	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
+	"github.com/ratify-project/ratify/config"
 	"github.com/stretchr/testify/assert"
 )
 
-func TestCRLNewFetcher(t *testing.T) {
-	httpClient := &http.Client{}
-	cacheRoot := "/tmp/cache"
-
-	t.Run("successful fetcher creation", func(t *testing.T) {
-		fetcher, err := CreateCRLFetcher(httpClient, cacheRoot)
-		assert.NoError(t, err)
-		assert.NotNil(t, fetcher)
-	})
-
-	t.Run("error in creating HTTP fetcher", func(t *testing.T) {
-		// Simulate error by passing nil httpClient
-		fetcher, err := CreateCRLFetcher(nil, cacheRoot)
-		assert.Error(t, err)
-		assert.Nil(t, fetcher)
-	})
-}
 func TestSupportCRL(t *testing.T) {
 	t.Run("certificate with CRL distribution points", func(t *testing.T) {
 		cert := &x509.Certificate{
@@ -128,6 +112,34 @@ func TestIntermittentFailCacheCRL(t *testing.T) {
 	})
 }
 
+func TestCreateCRLFetcher(t *testing.T) {
+	httpClient := &http.Client{}
+	cacheRoot := "/tmp/cache"
+
+	t.Run("successful fetcher creation without cache", func(t *testing.T) {
+		// Disable cache
+		config.CRLConf.Cache.Enabled = false
+		fetcher, err := CreateCRLFetcher(httpClient, cacheRoot)
+		assert.NoError(t, err)
+		assert.NotNil(t, fetcher)
+	})
+
+	t.Run("successful fetcher creation with cache", func(t *testing.T) {
+		// Enable cache
+		config.CRLConf.Cache.Enabled = true
+		fetcher, err := CreateCRLFetcher(httpClient, cacheRoot)
+		assert.NoError(t, err)
+		assert.NotNil(t, fetcher)
+	})
+
+	t.Run("error in creating HTTP fetcher", func(t *testing.T) {
+		// Simulate error by passing nil httpClient
+		fetcher, err := CreateCRLFetcher(nil, cacheRoot)
+		assert.Error(t, err)
+		assert.Nil(t, fetcher)
+	})
+}
+
 // MockFetcher is a mock implementation of corecrl.Fetcher for testing purposes
 type MockFetcher struct {
 	flag      bool
diff --git a/scripts/generate-crl-testing-certs.sh b/scripts/generate-crl-testing-certs.sh
index a02391a..79ee0c8 100755
--- a/scripts/generate-crl-testing-certs.sh
+++ b/scripts/generate-crl-testing-certs.sh
@@ -146,8 +146,8 @@ basicConstraints       = critical,CA:TRUE,pathlen:0
 keyUsage               = critical,keyCertSign,cRLSign
 subjectKeyIdentifier   = hash
 authorityKeyIdentifier = keyid:always,issuer:always
-crlDistributionPoints  = URI:http://localhost:10086/intermediate.crl
-authorityInfoAccess    = OCSP;URI:http://localhost.test/ocsp
+crlDistributionPoints  = URI:http://yourhost:10086/intermediate.crl
+authorityInfoAccess    = OCSP;URI:http://yourhost.test/ocsp
 
 [ crl_ext ]
 authorityKeyIdentifier = keyid:always
@@ -187,7 +187,7 @@ CN = LeafCert
 [ v3_req ]
 basicConstraints = critical,CA:FALSE
 keyUsage = critical,digitalSignature
-crlDistributionPoints = URI:http://localhost:10086/leaf.crl
+crlDistributionPoints = URI:http://yourhost:10086/leaf.crl
 EOF
 
 # Generate leaf private key
diff --git a/test/bats/base-test.bats b/test/bats/base-test.bats
index 28e7088..483bb09 100644
--- a/test/bats/base-test.bats
+++ b/test/bats/base-test.bats
@@ -18,6 +18,7 @@ load helpers
 BATS_TESTS_DIR=${BATS_TESTS_DIR:-test/bats/tests}
 WAIT_TIME=60
 SLEEP_TIME=1
+RATIFY_NAME=ratify
 RATIFY_NAMESPACE=gatekeeper-system
 
 @test "base test without cert rotator" {
@@ -57,6 +58,119 @@ RATIFY_NAMESPACE=gatekeeper-system
     assert_failure
 }
 
+@test "test rendering notation verifier with modified trust policies settings" {
+    teardown() {
+        echo "cleaning up"
+        rm -f notation-file1.crt
+        rm -f notation-file2.crt
+        rm -f notation-file3.crt
+    }
+
+    touch notation-file1.crt
+    echo "fake cert 1" > notation-file1.crt
+    touch notation-file2.crt
+    echo "fake cert 2" > notation-file2.crt
+    touch notation-file2.crt
+    echo "fake cert 3" > notation-file3.crt
+
+    # Happy path:
+    # Capture Helm template output
+    rendered=$(helm template multiple-trust-policies ./charts/ratify \
+        --set featureFlags.RATIFY_CERT_ROTATION=true \
+        --set-file notationCerts[0]="notation-file1.crt" \
+        --set-file notationCerts[1]="notation-file2.crt" \
+        --set-file notationCerts[2]="notation-file3.crt" \
+        --set notation.trustPolicies[0].registryScopes[0]="registry1.azurecr.io/" \
+        --set notation.trustPolicies[0].trustedIdentities[0]="cert identity 1" \
+        --set notation.trustPolicies[0].trustStores[0]=ca:notationCerts[0] \
+        --set notation.trustPolicies[0].trustStores[1]=tsa:notationCerts[1] \
+        --set notation.trustPolicies[0].trustStores[2]=signingAuthority:notationCerts[2] \
+        --set notation.trustPolicies[1].registryScopes[0]="registry2.azurecr.io/" \
+        --set notation.trustPolicies[1].trustStores[0]=ca:notationCerts[1])
+
+    # the expected partial output
+    expected_verifier_notation=$(cat <<EOF
+apiVersion: config.ratify.deislabs.io/v1beta1
+kind: Verifier
+metadata:
+  name: verifier-notation
+  annotations:
+    helm.sh/hook: pre-install,pre-upgrade
+    helm.sh/hook-weight: "5"
+spec:
+  name: notation
+  version: 1.0.0
+  artifactTypes: application/vnd.cncf.notary.signature
+  parameters:
+    verificationCertStores:
+      ca:
+        cert-0:
+          - multiple-trust-policies-ratify-notation-inline-cert-0
+        cert-3:
+          - multiple-trust-policies-ratify-notation-inline-cert-1
+      signingAuthority:
+        cert-2:
+          - multiple-trust-policies-ratify-notation-inline-cert-2
+      tsa:
+        cert-1:
+          - multiple-trust-policies-ratify-notation-inline-cert-1
+    trustPolicyDoc:
+      version: "1.0"
+      trustPolicies:
+        - name: trustPolicy-0  
+          registryScopes:
+            - "registry1.azurecr.io/"
+          signatureVerification:
+            level: strict  
+          trustStores:
+            - ca:cert-0
+            - tsa:cert-1
+            - signingAuthority:cert-2
+          trustedIdentities:
+            - "x509.subject: cert identity 1"
+        - name: trustPolicy-1  
+          registryScopes:
+            - "registry2.azurecr.io/"
+          signatureVerification:
+            level: strict  
+          trustStores:
+            - ca:cert-3
+          trustedIdentities:
+            - "*"
+EOF
+    )
+
+    # Assert that the rendered Helm output contains the expected section
+    [[ "$rendered" == *"$expected_verifier_notation"* ]] || {
+        echo "Rendered output does not contain the expected verifier-notation section."
+        echo "Rendered output:"
+        echo "$rendered"
+        echo "Expected section:"
+        echo "$expected_verifier_notation"
+        return 1
+    }
+
+    # failure path:
+    # Capture Helm template output
+    run helm template multiple-trust-policies ./charts/ratify \
+        --set featureFlags.RATIFY_CERT_ROTATION=true \
+        --set-file notationCerts[0]="notation-file1.crt" \
+        --set notation.trustPolicies[0].registryScopes[0]="registry1.azurecr.io/" \
+        --set notation.trustPolicies[0].trustedIdentities[0]="cert identity 1" \
+        --set notation.trustPolicies[0].trustStores[0]=ca:unknownCert
+
+    assert_failure
+
+    # the expected error message
+    expected_verifier_notation=$(cat <<EOF
+Unknown trust store reference: unknownCert
+EOF
+    )
+
+    # Assert that the rendered Helm output contains the expected error message
+    [[ "$output" == *"$expected_verifier_notation"* ]]
+}
+
 @test "crd version test" {
     run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notation
     assert_success
@@ -133,6 +247,9 @@ RATIFY_NAMESPACE=gatekeeper-system
         # restore the original notation verifier for other tests
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl replace -f ./config/samples/clustered/verifier/config_v1beta1_verifier_notation.yaml'
     }
+    TARGET_IP=$(ip -4 addr show "eth0" | awk '/inet/ {print $2}' | cut -d'/' -f1)
+    # RATIFY_POD=$(kubectl get pods -n ${RATIFY_NAMESPACE} --no-headers -o custom-columns=":metadata.name" | grep ratify)
+    run kubectl patch deployment ${RATIFY_NAME} -n ${RATIFY_NAMESPACE} --type='merge' -p '{"spec":{"template":{"spec":{"hostAliases":[{"ip":"'"${TARGET_IP}"'","hostnames":["yourhost"]}]}}}}'
 
     # add the tsaroot certificate as an inline key management provider
     cat ./test/bats/tests/config/config_v1beta1_keymanagementprovider_inline.yaml >> crlkmprovider.yaml
diff --git a/test/bats/cli-test.bats b/test/bats/cli-test.bats
index 85df809..31f7d80 100644
--- a/test/bats/cli-test.bats
+++ b/test/bats/cli-test.bats
@@ -34,11 +34,23 @@ load helpers
     assert_cmd_verify_failure
 }
 
-@test "notation verifier negative crl test" {
+@test "notation verifier crl test" {
+    sudo sed -i '1i 127.0.0.1 yourhost' /etc/hosts
     revoke_crl
 
     run bin/ratify verify -c $RATIFY_DIR/config_notation_crl.json -s $TEST_REGISTRY/notation:crl
     assert_cmd_verify_failure
+    
+    check_crl_cache_created
+    
+    delete_crl_cache
+    check_crl_cache_deleted
+    unrevoke_crl
+
+    run bin/ratify verify -c $RATIFY_DIR/config_notation_crl_cache_disabled.json -s $TEST_REGISTRY/notation:crl
+    assert_cmd_verify_success
+
+    check_crl_cache_deleted
 }
 
 @test "notation verifier with type test" {
diff --git a/test/bats/helpers.bash b/test/bats/helpers.bash
index 0a5ec51..af1a13d 100644
--- a/test/bats/helpers.bash
+++ b/test/bats/helpers.bash
@@ -114,8 +114,32 @@ wait_for_process() {
 
 revoke_crl() {
   URL_LEAF="http://localhost:10086/leaf/revoke"
-	curl -X POST "$URL_LEAF" -H "Content-Type: application/json"
+  curl -s -X POST "$URL_LEAF" -H "Content-Type: application/json"
   URL_INTER=http://localhost:10086/intermediate/unrevoke
-  curl -X POST "$URL_INTER" -H "Content-Type: application/json"
-  sleep 10
+  curl -s -X POST "$URL_INTER" -H "Content-Type: application/json"
 }
+
+unrevoke_crl() {
+  URL_LEAF="http://localhost:10086/leaf/unrevoke"
+  curl -s -X POST "$URL_LEAF" -H "Content-Type: application/json"
+  URL_INTER=http://localhost:10086/intermediate/unrevoke
+  curl -s -X POST "$URL_INTER" -H "Content-Type: application/json"
+}
+
+delete_crl_cache() {
+  rm -rf $HOME/.cache/notation/crl
+}
+
+check_crl_cache_deleted() {
+  if [[ -d "$HOME/.cache/notation/crl" ]]; then
+    echo "The directory exists."
+    return 1
+  fi
+}
+
+check_crl_cache_created() {
+  if [[ ! -d "$HOME/.cache/notation/crl" ]]; then
+    echo "The directory does not exist."
+    return 1
+  fi
+}
\ No newline at end of file
diff --git a/test/bats/tests/config/config_notation_crl.json b/test/bats/tests/config/config_notation_crl.json
index 3fb4aea..3122c49 100644
--- a/test/bats/tests/config/config_notation_crl.json
+++ b/test/bats/tests/config/config_notation_crl.json
@@ -46,5 +46,10 @@
                 }
             }
         ]
+    },
+    "crl": {
+        "cache":{
+            "enabled": true
+        }
     }
 }
\ No newline at end of file
diff --git a/test/bats/tests/config/config_notation_crl_cache_disabled.json b/test/bats/tests/config/config_notation_crl_cache_disabled.json
new file mode 100644
index 0000000..61b7ac6
--- /dev/null
+++ b/test/bats/tests/config/config_notation_crl_cache_disabled.json
@@ -0,0 +1,55 @@
+{
+    "store": {
+        "version": "1.0.0",
+        "plugins": [
+            {
+                "name": "oras",
+                "cosignEnabled": true,
+                "useHttp": true
+            }
+        ]
+    },
+    "policy": {
+        "version": "1.0.0",
+        "plugin": {
+            "name": "configPolicy"
+        }
+    },
+    "verifier": {
+        "version": "1.0.0",
+        "plugins": [
+            {
+                "name": "notation",
+                "artifactTypes": "application/vnd.cncf.notary.signature",
+                "verificationCerts": [
+                    "~/.config/notation/truststore/x509/ca/crl-test/root.crt"
+                ],
+                "trustPolicyDoc": {
+                    "version": "1.0",
+                    "trustPolicies": [
+                        {
+                            "name": "default",
+                            "registryScopes": [
+                                "*"
+                            ],
+                            "signatureVerification": {
+                                "level": "strict"
+                            },
+                            "trustStores": [
+                                "ca:certs"
+                            ],
+                            "trustedIdentities": [
+                                "*"
+                            ]
+                        }
+                    ]
+                }
+            }
+        ]
+    },
+    "crl": {
+        "cache":{
+            "enabled": false
+        }
+    }
+}
\ No newline at end of file