Repository: ratify-project/ratify
Pull request #1921 (2024-11-10 08:33:04)

chore: automated PR to main 2024-11-10
Automated Pull Request to main branch


Patch:
diff --git a/.github/actions/restore_trivy_cache/action.yml b/.github/actions/restore_trivy_cache/action.yml
new file mode 100644
index 0000000..fcc0e4a
--- /dev/null
+++ b/.github/actions/restore_trivy_cache/action.yml
@@ -0,0 +1,20 @@
+name: "Steps to restore trivy cache"
+description: "Steps to restore Trivy cache under ~/.cache/trivy"
+
+runs:
+  using: "composite"
+  steps:
+    - name: Get current date
+      id: date
+      run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+      shell: bash
+    - name: Restore trivy cache directory
+      uses: actions/cache/restore@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
+      with:
+        path: ${{ github.workspace }}/.cache/trivy
+        key: cache-trivy-${{ steps.date.outputs.date }}
+    - name: Set up trivy cache directory
+      run: |
+        mkdir -p ~/.cache/trivy
+        cp -r ${{ github.workspace }}/.cache/trivy/db ~/.cache/trivy
+      shell: bash
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ec43b4a..5479ad2 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,7 +26,7 @@ jobs:
           fetch-depth: 0
 
       - name: Install Syft
-        uses: anchore/sbom-action/download-syft@251a468eed47e5082b105c3ba6ee500c0e65a764 # v0.17.6
+        uses: anchore/sbom-action/download-syft@fc46e51fd3cb168ffb36c6d1915723c47db58abb # v0.17.7
 
       - name: Set up Go
         uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
@@ -35,7 +35,7 @@ jobs:
 
       - name: Goreleaser
         id: goreleaser
-        uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
+        uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
         with:
           version: "2.0.1"
           args: release --clean
diff --git a/.github/workflows/scan-vulns.yaml b/.github/workflows/scan-vulns.yaml
index 1a554a6..fc9d9c9 100644
--- a/.github/workflows/scan-vulns.yaml
+++ b/.github/workflows/scan-vulns.yaml
@@ -55,15 +55,8 @@ jobs:
           tar zxvf trivy_${{ env.TRIVY_VERSION }}_Linux-64bit.tar.gz
           echo "$(pwd)" >> $GITHUB_PATH
       
-      - name: Download vulnerability database
-        uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
-        with:
-          max_attempts: 3
-          retry_on: error
-          timeout_seconds: 30
-          retry_wait_seconds: 5
-          command: |
-            trivy image --download-db-only
+      - name: Restore Trivy cache
+        uses: ./.github/actions/restore_trivy_cache
 
       - name: Run trivy on git repository
         run: |
diff --git a/.github/workflows/update-trivy-cache.yml b/.github/workflows/update-trivy-cache.yml
new file mode 100644
index 0000000..6d2fea0
--- /dev/null
+++ b/.github/workflows/update-trivy-cache.yml
@@ -0,0 +1,42 @@
+name: Update Trivy Cache
+
+on:
+  schedule:
+    - cron: '0 0 * * *'  # Run daily at midnight UTC
+  workflow_dispatch:
+
+permissions: read-all
+
+jobs:
+  update-trivy-db:
+    runs-on: ubuntu-latest
+    if: ${{ github.ref_name == github.event.repository.default_branch }}
+    steps:
+      - name: Setup oras
+        uses: oras-project/setup-oras@9c92598691bfef1424de2f8fae81941568f5889c # v1.2.1
+
+      - name: Get current date
+        id: date
+        run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
+
+      - name: Prepare DB directory
+        run: |
+          mkdir -p $GITHUB_WORKSPACE/.cache/trivy/db
+      
+      - name: Download vulnerability database
+        uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
+        with:
+          max_attempts: 60
+          retry_on: error
+          timeout_seconds: 30
+          retry_wait_seconds: 60
+          command: |
+            oras pull ghcr.io/aquasecurity/trivy-db:2
+            tar -xzf db.tar.gz -C $GITHUB_WORKSPACE/.cache/trivy/db
+            rm db.tar.gz
+
+      - name: Cache DBs
+        uses: actions/cache/save@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.1.2
+        with:
+          path: ${{ github.workspace }}/.cache/trivy
+          key: cache-trivy-${{ steps.date.outputs.date }}
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 3d06df5..fde9cad 100644
--- a/Makefile
+++ b/Makefile
@@ -467,25 +467,6 @@ e2e-trivy-setup:
 	curl -L https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz --output .staging/trivy/trivy.tar.gz
 	tar -zxf .staging/trivy/trivy.tar.gz -C .staging/trivy
 
-	# Download vulnerability database in retry mode
-	max_retries=3; \
-	attempt=1; \
-	wait_time=2; \
-	while [ $$attempt -le $$max_retries ]; do \
-		echo "Attempt $$attempt of $$max_retries..."; \
-		if .staging/trivy/trivy image --download-db-only; then \
-			break; \
-		fi; \
-		if [ $$attempt -eq $$max_retries ]; then \
-			echo "Failed after $$max_retries attempts."; \
-			exit 1; \
-		fi; \
-		echo "Failed. Retrying in $$wait_time seconds..."; \
-		sleep $$wait_time; \
-		wait_time=$$(( wait_time * 2 )); \
-		attempt=$$(( attempt + 1 )); \
-	done
-
 e2e-schemavalidator-setup:
 	rm -rf .staging/schemavalidator
 	mkdir -p .staging/schemavalidator
diff --git a/go.mod b/go.mod
index d503714..32985ce 100644
--- a/go.mod
+++ b/go.mod
@@ -29,8 +29,8 @@ require (
 	github.com/golang/protobuf v1.5.4
 	github.com/google/go-containerregistry v0.20.2
 	github.com/gorilla/mux v1.8.1
-	github.com/notaryproject/notation-core-go v1.1.0
-	github.com/notaryproject/notation-go v1.2.1
+	github.com/notaryproject/notation-core-go v1.2.0-rc.1
+	github.com/notaryproject/notation-go v1.3.0-rc.1
 	github.com/notaryproject/notation-plugin-framework-go v1.0.0
 	github.com/open-policy-agent/cert-controller v0.8.0
 	github.com/open-policy-agent/frameworks/constraint v0.0.0-20230411224310-3f237e2710fa
@@ -173,7 +173,7 @@ require (
 	github.com/go-openapi/swag v0.23.0 // indirect
 	github.com/go-openapi/validate v0.24.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
-	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+	github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
 	github.com/golang/glog v1.2.1 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/snappy v0.0.4 // indirect
@@ -238,7 +238,7 @@ require (
 	go.uber.org/zap v1.27.0 // indirect
 	golang.org/x/crypto v0.28.0
 	golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
-	golang.org/x/mod v0.20.0 // indirect
+	golang.org/x/mod v0.21.0 // indirect
 	golang.org/x/net v0.29.0 // indirect
 	golang.org/x/oauth2 v0.23.0 // indirect
 	golang.org/x/sys v0.26.0 // indirect
diff --git a/go.sum b/go.sum
index b9c4f32..72451b6 100644
--- a/go.sum
+++ b/go.sum
@@ -333,8 +333,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
+github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -518,10 +519,10 @@ github.com/mozillazg/docker-credential-acr-helper v0.3.0/go.mod h1:cZlu3tof523uj
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/notaryproject/notation-core-go v1.1.0 h1:xCybcONOKcCyPNihJUSa+jRNsyQFNkrk0eJVVs1kWeg=
-github.com/notaryproject/notation-core-go v1.1.0/go.mod h1:+6AOh41JPrnVLbW/19SJqdhVHwKgIINBO/np0e7nXJA=
-github.com/notaryproject/notation-go v1.2.1 h1:fbCMBcvg1xttrisd5CyM60QDectGYYF701Us0M3cKN8=
-github.com/notaryproject/notation-go v1.2.1/go.mod h1:re9V+TfuNRaUq5e3NuNcCJN53++sL2KbnJrjGyOUpgE=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1 h1:VMFlG+9a1JoNAQ3M96g8iqCq0cDRtE7XBaiTD8Ouvqw=
+github.com/notaryproject/notation-core-go v1.2.0-rc.1/go.mod h1:b/70rA4OgOHlg0A7pb8zTWKJadFO6781zS3a37KHEJQ=
+github.com/notaryproject/notation-go v1.3.0-rc.1 h1:pm9tdUy2tWYqlwyRDZyKXgLwAscDATPUYv0ul2RK/Iw=
+github.com/notaryproject/notation-go v1.3.0-rc.1/go.mod h1:W4o45yolX4Q+3PKlcpGleLLXEKWHa3BshEqw/JX5c6I=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0 h1:6Qzr7DGXoCgXEQN+1gTZWuJAZvxh3p8Lryjn5FaLzi4=
 github.com/notaryproject/notation-plugin-framework-go v1.0.0/go.mod h1:RqWSrTOtEASCrGOEffq0n8pSg2KOgKYiWqFWczRSics=
 github.com/notaryproject/tspclient-go v0.2.0 h1:g/KpQGmyk/h7j60irIRG1mfWnibNOzJ8WhLqAzuiQAQ=
@@ -795,8 +796,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
-golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
+golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/pkg/controllers/clusterresource/keymanagementprovider_controller.go b/pkg/controllers/clusterresource/keymanagementprovider_controller.go
index afb53a9..df454b3 100644
--- a/pkg/controllers/clusterresource/keymanagementprovider_controller.go
+++ b/pkg/controllers/clusterresource/keymanagementprovider_controller.go
@@ -80,7 +80,7 @@ func (r *KeyManagementProviderReconciler) ReconcileWithType(ctx context.Context,
 		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
 	}
 
-	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
+	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type, resource)
 	if err != nil {
 		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
 
diff --git a/pkg/controllers/namespaceresource/keymanagementprovider_controller.go b/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
index 2bbdd0b..dcba257 100644
--- a/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
+++ b/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
@@ -79,7 +79,7 @@ func (r *KeyManagementProviderReconciler) ReconcileWithType(ctx context.Context,
 		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
 	}
 
-	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
+	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type, resource)
 	if err != nil {
 		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
 
diff --git a/pkg/controllers/utils/kmp.go b/pkg/controllers/utils/kmp.go
index a2085cf..8bda6a6 100644
--- a/pkg/controllers/utils/kmp.go
+++ b/pkg/controllers/utils/kmp.go
@@ -26,8 +26,8 @@ import (
 )
 
 // SpecToKeyManagementProvider creates KeyManagementProvider from  KeyManagementProviderSpec config
-func SpecToKeyManagementProvider(raw []byte, keyManagamentSystemName string) (kmp.KeyManagementProvider, error) {
-	kmProviderConfig, err := rawToKeyManagementProviderConfig(raw, keyManagamentSystemName)
+func SpecToKeyManagementProvider(raw []byte, keyManagamentSystemName, resource string) (kmp.KeyManagementProvider, error) {
+	kmProviderConfig, err := rawToKeyManagementProviderConfig(raw, keyManagamentSystemName, resource)
 	if err != nil {
 		return nil, err
 	}
@@ -42,7 +42,7 @@ func SpecToKeyManagementProvider(raw []byte, keyManagamentSystemName string) (km
 }
 
 // rawToKeyManagementProviderConfig converts raw json to KeyManagementProviderConfig
-func rawToKeyManagementProviderConfig(raw []byte, keyManagamentSystemName string) (config.KeyManagementProviderConfig, error) {
+func rawToKeyManagementProviderConfig(raw []byte, keyManagamentSystemName, resource string) (config.KeyManagementProviderConfig, error) {
 	pluginConfig := config.KeyManagementProviderConfig{}
 
 	if string(raw) == "" {
@@ -53,6 +53,7 @@ func rawToKeyManagementProviderConfig(raw []byte, keyManagamentSystemName string
 	}
 
 	pluginConfig[types.Type] = keyManagamentSystemName
+	pluginConfig[types.Resource] = resource
 
 	return pluginConfig, nil
 }
diff --git a/pkg/keymanagementprovider/azurekeyvault/provider.go b/pkg/keymanagementprovider/azurekeyvault/provider.go
index da885af..22c3fba 100644
--- a/pkg/keymanagementprovider/azurekeyvault/provider.go
+++ b/pkg/keymanagementprovider/azurekeyvault/provider.go
@@ -24,7 +24,9 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"encoding/pem"
+	"errors"
 	"fmt"
+	"strconv"
 	"strings"
 	"time"
 
@@ -40,6 +42,7 @@ import (
 	"golang.org/x/crypto/pkcs12"
 
 	kv "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
+	"github.com/Azure/go-autorest/autorest"
 	"github.com/Azure/go-autorest/autorest/azure"
 )
 
@@ -59,6 +62,7 @@ type AKVKeyManagementProviderConfig struct {
 	TenantID     string                `json:"tenantID"`
 	ClientID     string                `json:"clientID"`
 	CloudName    string                `json:"cloudName,omitempty"`
+	Resource     string                `json:"resource,omitempty"`
 	Certificates []types.KeyVaultValue `json:"certificates,omitempty"`
 	Keys         []types.KeyVaultValue `json:"keys,omitempty"`
 }
@@ -69,13 +73,44 @@ type akvKMProvider struct {
 	tenantID     string
 	clientID     string
 	cloudName    string
+	resource     string
 	certificates []types.KeyVaultValue
 	keys         []types.KeyVaultValue
 	cloudEnv     *azure.Environment
-	kvClient     *kv.BaseClient
+	kvClient     kvClient
 }
+
 type akvKMProviderFactory struct{}
 
+// kvClient is an interface to interact with the keyvault client used for mocking purposes
+type kvClient interface {
+	// GetCertificate retrieves a certificate from the keyvault
+	GetCertificate(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (kv.CertificateBundle, error)
+	// GetKey retrieves a key from the keyvault
+	GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (kv.KeyBundle, error)
+	// GetSecret retrieves a secret from the keyvault
+	GetSecret(ctx context.Context, vaultBaseURL string, secretName string, secretVersion string) (kv.SecretBundle, error)
+}
+
+type kvClientImpl struct {
+	kv.BaseClient
+}
+
+// GetCertificate retrieves a certificate from the keyvault
+func (c *kvClientImpl) GetCertificate(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (kv.CertificateBundle, error) {
+	return c.BaseClient.GetCertificate(ctx, vaultBaseURL, certificateName, certificateVersion)
+}
+
+// GetKey retrieves a key from the keyvault
+func (c *kvClientImpl) GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (kv.KeyBundle, error) {
+	return c.BaseClient.GetKey(ctx, vaultBaseURL, keyName, keyVersion)
+}
+
+// GetSecret retrieves a secret from the keyvault
+func (c *kvClientImpl) GetSecret(ctx context.Context, vaultBaseURL string, secretName string, secretVersion string) (kv.SecretBundle, error) {
+	return c.BaseClient.GetSecret(ctx, vaultBaseURL, secretName, secretVersion)
+}
+
 // initKVClient is a function to initialize the keyvault client
 // used for mocking purposes
 var initKVClient = initializeKvClient
@@ -116,6 +151,7 @@ func (f *akvKMProviderFactory) Create(_ string, keyManagementProviderConfig conf
 		certificates: conf.Certificates,
 		keys:         conf.Keys,
 		cloudEnv:     azureCloudEnv,
+		resource:     conf.Resource,
 	}
 	if err := provider.validate(); err != nil {
 		return nil, err
@@ -127,7 +163,7 @@ func (f *akvKMProviderFactory) Create(_ string, keyManagementProviderConfig conf
 	if err != nil {
 		return nil, re.ErrorCodePluginInitFailure.NewError(re.KeyManagementProvider, ProviderName, re.AKVLink, err, "failed to create keyvault client", re.HideStackTrace)
 	}
-	provider.kvClient = kvClient
+	provider.kvClient = &kvClientImpl{*kvClient}
 
 	return provider, nil
 }
@@ -140,25 +176,42 @@ func (s *akvKMProvider) GetCertificates(ctx context.Context) (map[keymanagementp
 	for _, keyVaultCert := range s.certificates {
 		logger.GetLogger(ctx, logOpt).Debugf("fetching secret from key vault, certName %v,  keyvault %v", keyVaultCert.Name, s.vaultURI)
 
-		// fetch the object from Key Vault
-		// GetSecret is required so we can fetch the entire cert chain. See issue https://github.com/ratify-project/ratify/issues/695 for details
 		startTime := time.Now()
+
+		// GetSecret is required so we can fetch the entire cert chain. See issue https://github.com/ratify-project/ratify/issues/695 for details
 		secretBundle, err := s.kvClient.GetSecret(ctx, s.vaultURI, keyVaultCert.Name, keyVaultCert.Version)
 		if err != nil {
+			if isSecretDisabledError(err) {
+				// if secret is disabled, get the version of the certificate for status
+				certBundle, err := s.kvClient.GetCertificate(ctx, s.vaultURI, keyVaultCert.Name, keyVaultCert.Version)
+				if err != nil {
+					return nil, nil, fmt.Errorf("failed to get certificate objectName:%s, objectVersion:%s, error: %w", keyVaultCert.Name, keyVaultCert.Version, err)
+				}
+				keyVaultCert.Version = getObjectVersion(*certBundle.Kid)
+				isEnabled := *certBundle.Attributes.Enabled
+				lastRefreshed := startTime.Format(time.RFC3339)
+				certProperty := getStatusProperty(keyVaultCert.Name, keyVaultCert.Version, lastRefreshed, isEnabled)
+				certsStatus = append(certsStatus, certProperty)
+				mapKey := keymanagementprovider.KMPMapKey{Name: keyVaultCert.Name, Version: keyVaultCert.Version, Enabled: isEnabled}
+				keymanagementprovider.DeleteCertificateFromMap(s.resource, mapKey)
+				continue
+			}
+
 			return nil, nil, fmt.Errorf("failed to get secret objectName:%s, objectVersion:%s, error: %w", keyVaultCert.Name, keyVaultCert.Version, err)
 		}
 
-		certResult, certProperty, err := getCertsFromSecretBundle(ctx, secretBundle, keyVaultCert.Name)
+		isEnabled := *secretBundle.Attributes.Enabled
+
+		certResult, certProperty, err := getCertsFromSecretBundle(ctx, secretBundle, keyVaultCert.Name, isEnabled)
 		if err != nil {
 			return nil, nil, fmt.Errorf("failed to get certificates from secret bundle:%w", err)
 		}
 
 		metrics.ReportAKVCertificateDuration(ctx, time.Since(startTime).Milliseconds(), keyVaultCert.Name)
 		certsStatus = append(certsStatus, certProperty...)
-		certMapKey := keymanagementprovider.KMPMapKey{Name: keyVaultCert.Name, Version: keyVaultCert.Version}
+		certMapKey := keymanagementprovider.KMPMapKey{Name: keyVaultCert.Name, Version: keyVaultCert.Version, Enabled: isEnabled}
 		certsMap[certMapKey] = certResult
 	}
-
 	return certsMap, getStatusMap(certsStatus, types.CertificatesStatus), nil
 }
 
@@ -177,17 +230,27 @@ func (s *akvKMProvider) GetKeys(ctx context.Context) (map[keymanagementprovider.
 			return nil, nil, fmt.Errorf("failed to get key objectName:%s, objectVersion:%s, error: %w", keyVaultKey.Name, keyVaultKey.Version, err)
 		}
 
-		if keyBundle.Attributes != nil && keyBundle.Attributes.Enabled != nil && !*keyBundle.Attributes.Enabled {
-			return nil, nil, fmt.Errorf("key %s version %s is disabled. please re-enable in azure key vault or remove reference to this key", keyVaultKey.Name, keyVaultKey.Version)
+		isEnabled := *keyBundle.Attributes.Enabled
+		// if version is set as "" in the config, use the version from the key bundle
+		keyVaultKey.Version = getObjectVersion(*keyBundle.Key.Kid)
+
+		if !isEnabled {
+			startTime := time.Now()
+			lastRefreshed := startTime.Format(time.RFC3339)
+			properties := getStatusProperty(keyVaultKey.Name, keyVaultKey.Version, lastRefreshed, isEnabled)
+			keysStatus = append(keysStatus, properties)
+			mapKey := keymanagementprovider.KMPMapKey{Name: keyVaultKey.Name, Version: keyVaultKey.Version, Enabled: isEnabled}
+			keymanagementprovider.DeleteKeyFromMap(s.resource, mapKey)
+			continue
 		}
 
 		publicKey, err := getKeyFromKeyBundle(keyBundle)
 		if err != nil {
 			return nil, nil, fmt.Errorf("failed to get key from key bundle:%w", err)
 		}
-		keysMap[keymanagementprovider.KMPMapKey{Name: keyVaultKey.Name, Version: keyVaultKey.Version}] = publicKey
+		keysMap[keymanagementprovider.KMPMapKey{Name: keyVaultKey.Name, Version: keyVaultKey.Version, Enabled: isEnabled}] = publicKey
 		metrics.ReportAKVCertificateDuration(ctx, time.Since(startTime).Milliseconds(), keyVaultKey.Name)
-		properties := getStatusProperty(keyVaultKey.Name, keyVaultKey.Version, time.Now().Format(time.RFC3339))
+		properties := getStatusProperty(keyVaultKey.Name, keyVaultKey.Version, time.Now().Format(time.RFC3339), isEnabled)
 		keysStatus = append(keysStatus, properties)
 	}
 
@@ -205,11 +268,12 @@ func getStatusMap(statusMap []map[string]string, contentType string) keymanageme
 	return status
 }
 
-// return a status object that consist of the cert/key name, version and last refreshed time
-func getStatusProperty(name, version, lastRefreshed string) map[string]string {
+// return a status object that consist of the cert/key name, version, enabled and last refreshed time
+func getStatusProperty(name, version, lastRefreshed string, enabled bool) map[string]string {
 	properties := map[string]string{}
 	properties[types.StatusName] = name
 	properties[types.StatusVersion] = version
+	properties[types.StatusEnabled] = strconv.FormatBool(enabled)
 	properties[types.StatusLastRefreshed] = lastRefreshed
 	return properties
 }
@@ -230,7 +294,7 @@ func initializeKvClient(ctx context.Context, keyVaultEndpoint, tenantID, clientI
 	kvClient := kv.New()
 	kvEndpoint := strings.TrimSuffix(keyVaultEndpoint, "/")
 
-	err := kvClient.AddToUserAgent(userAgent)
+	err := kvClient.Client.AddToUserAgent(userAgent)
 	if err != nil {
 		return nil, re.ErrorCodeConfigInvalid.WithDetail("Failed to add user agent to keyvault client.").WithRemediation(re.AKVLink).WithError(err)
 	}
@@ -244,7 +308,7 @@ func initializeKvClient(ctx context.Context, keyVaultEndpoint, tenantID, clientI
 
 // Parse the secret bundle and return an array of certificates
 // In a certificate chain scenario, all certificates from root to leaf will be returned
-func getCertsFromSecretBundle(ctx context.Context, secretBundle kv.SecretBundle, certName string) ([]*x509.Certificate, []map[string]string, error) {
+func getCertsFromSecretBundle(ctx context.Context, secretBundle kv.SecretBundle, certName string, enabled bool) ([]*x509.Certificate, []map[string]string, error) {
 	if secretBundle.ContentType == nil || secretBundle.Value == nil || secretBundle.ID == nil {
 		return nil, nil, re.ErrorCodeCertInvalid.NewError(re.KeyManagementProvider, ProviderName, re.EmptyLink, nil, "found invalid secret bundle for certificate  %s, contentType, value, and id must not be nil", re.HideStackTrace)
 	}
@@ -297,7 +361,7 @@ func getCertsFromSecretBundle(ctx context.Context, secretBundle kv.SecretBundle,
 			}
 			for _, cert := range decodedCerts {
 				results = append(results, cert)
-				certProperty := getStatusProperty(certName, version, lastRefreshed)
+				certProperty := getStatusProperty(certName, version, lastRefreshed, enabled)
 				certsStatus = append(certsStatus, certProperty)
 			}
 		default:
@@ -352,6 +416,19 @@ func getObjectVersion(id string) string {
 	return splitID[len(splitID)-1]
 }
 
+func isSecretDisabledError(err error) bool {
+	var de autorest.DetailedError
+	if errors.As(err, &de) {
+		var re *azure.RequestError
+		if errors.As(de.Original, &re) {
+			if re.ServiceError.Code == "SecretDisabled" {
+				return true
+			}
+		}
+	}
+	return false
+}
+
 // validate checks vaultURI, tenantID, clientID are set and all certificates/keys have a name
 func (s *akvKMProvider) validate() error {
 	if s.vaultURI == "" {
diff --git a/pkg/keymanagementprovider/azurekeyvault/types/types.go b/pkg/keymanagementprovider/azurekeyvault/types/types.go
index 5cde595..cae8607 100644
--- a/pkg/keymanagementprovider/azurekeyvault/types/types.go
+++ b/pkg/keymanagementprovider/azurekeyvault/types/types.go
@@ -25,6 +25,8 @@ const (
 	StatusName = "Name"
 	// Certificate version string for the certificate status property
 	StatusVersion = "Version"
+	// Enabled string for the certificate status property
+	StatusEnabled = "True"
 	// Last refreshed string for the certificate status property
 	StatusLastRefreshed = "LastRefreshed"
 )
diff --git a/pkg/keymanagementprovider/keymanagementprovider.go b/pkg/keymanagementprovider/keymanagementprovider.go
index 584f508..8a656b6 100644
--- a/pkg/keymanagementprovider/keymanagementprovider.go
+++ b/pkg/keymanagementprovider/keymanagementprovider.go
@@ -41,6 +41,7 @@ type KeyManagementProviderStatus map[string]interface{}
 type KMPMapKey struct {
 	Name    string
 	Version string
+	Enabled bool
 }
 
 type PublicKey struct {
@@ -156,6 +157,30 @@ func DeleteResourceFromMap(resource string) {
 	keyErrMap.Delete(resource)
 }
 
+// DeleteKeyFromMap deletes the keys from the map
+func DeleteCertificateFromMap(resource string, certKey KMPMapKey) {
+	if certs, ok := certificatesMap.Load(resource); ok {
+		for k := range certs.(map[KMPMapKey][]*x509.Certificate) {
+			if k.Name == certKey.Name && k.Version == certKey.Version {
+				delete(certs.(map[KMPMapKey][]*x509.Certificate), k)
+				continue
+			}
+		}
+	}
+}
+
+// DeleteKeyFromMap deletes the keys from the map
+func DeleteKeyFromMap(resource string, key KMPMapKey) {
+	if keys, ok := keyMap.Load(resource); ok {
+		for k := range keys.(map[KMPMapKey]PublicKey) {
+			if k.Name == key.Name && k.Version == key.Version {
+				delete(keys.(map[KMPMapKey]PublicKey), k)
+				continue
+			}
+		}
+	}
+}
+
 // FlattenKMPMap flattens the map of certificates fetched for a single key management provider resource and returns a single array
 func FlattenKMPMap(certMap map[KMPMapKey][]*x509.Certificate) []*x509.Certificate {
 	var items []*x509.Certificate
diff --git a/pkg/keymanagementprovider/types/types.go b/pkg/keymanagementprovider/types/types.go
index c15354d..2e67b69 100644
--- a/pkg/keymanagementprovider/types/types.go
+++ b/pkg/keymanagementprovider/types/types.go
@@ -19,5 +19,6 @@ const (
 	SpecVersion string = "0.1.0"
 	Version     string = "version"
 	Type        string = "type"
+	Resource    string = "resource"
 	Source      string = "source"
 )
diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go
index e825db1..52fdcbd 100644
--- a/pkg/verifier/notation/notation.go
+++ b/pkg/verifier/notation/notation.go
@@ -36,6 +36,8 @@ import (
 	"github.com/ratify-project/ratify/pkg/verifier/factory"
 	"github.com/ratify-project/ratify/pkg/verifier/types"
 
+	"github.com/notaryproject/notation-core-go/revocation"
+	"github.com/notaryproject/notation-core-go/revocation/purpose"
 	_ "github.com/notaryproject/notation-core-go/signature/cose" // register COSE signature
 	_ "github.com/notaryproject/notation-core-go/signature/jws"  // register JWS signature
 	"github.com/notaryproject/notation-go"
@@ -103,8 +105,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(conf, pluginDirectory)
+	verifyService, err := getVerifierService(conf, pluginDirectory, NewRevocationFactoryImpl())
 	if err != nil {
 		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
 	}
@@ -176,12 +177,40 @@ func (v *notationPluginVerifier) Verify(ctx context.Context,
 	return verifier.NewVerifierResult("", v.name, v.verifierType, "Notation signature verification success", true, nil, extensions), nil
 }
 
-func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory string) (notation.Verifier, error) {
+func getVerifierService(conf *NotationPluginVerifierConfig, pluginDirectory string, revocationFactory RevocationFactory) (notation.Verifier, error) {
 	store, err := newTrustStore(conf.VerificationCerts, conf.VerificationCertStores)
 	if err != nil {
 		return nil, err
 	}
-	verifier, err := notationVerifier.New(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory))
+
+	// revocation check using corecrl from notation-core-go and crl from notation-go
+	// This is the implementation for revocation check from notation cli to support crl and cache configurations
+	// removed timeout
+	// Related PR: notaryproject/notation#1043
+	// Related File: https://github.com/notaryproject/notation/commits/main/cmd/notation/verify.go5
+	crlFetcher, err := revocationFactory.NewFetcher()
+	if err != nil {
+		return nil, err
+	}
+	revocationCodeSigningValidator, err := revocationFactory.NewValidator(revocation.Options{
+		CRLFetcher:       crlFetcher,
+		CertChainPurpose: purpose.CodeSigning,
+	})
+	if err != nil {
+		return nil, err
+	}
+	revocationTimestampingValidator, err := revocationFactory.NewValidator(revocation.Options{
+		CRLFetcher:       crlFetcher,
+		CertChainPurpose: purpose.Timestamping,
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	verifier, err := notationVerifier.NewWithOptions(&conf.TrustPolicyDoc, store, NewRatifyPluginManager(pluginDirectory), notationVerifier.VerifierOptions{
+		RevocationCodeSigningValidator:  revocationCodeSigningValidator,
+		RevocationTimestampingValidator: revocationTimestampingValidator,
+	})
 	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
new file mode 100644
index 0000000..47cc356
--- /dev/null
+++ b/pkg/verifier/notation/notationrevocationfactory.go
@@ -0,0 +1,63 @@
+// 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 notation
+
+import (
+	"net/http"
+
+	"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"
+)
+
+type RevocationFactoryImpl struct {
+	cacheRoot  string
+	httpClient *http.Client
+}
+
+// NewRevocationFactoryImpl returns a new NewRevocationFactoryImpl instance
+func NewRevocationFactoryImpl() RevocationFactory {
+	return &RevocationFactoryImpl{
+		cacheRoot:  dir.PathCRLCache,
+		httpClient: &http.Client{},
+	}
+}
+
+// NewFetcher returns a new fetcher instance
+func (f *RevocationFactoryImpl) NewFetcher() (corecrl.Fetcher, error) {
+	crlFetcher, err := corecrl.NewHTTPFetcher(f.httpClient)
+	if err != nil {
+		return nil, err
+	}
+	crlFetcher.Cache, err = newFileCache(f.cacheRoot)
+	if err != nil {
+		return nil, err
+	}
+	return crlFetcher, nil
+}
+
+// NewValidator returns a new validator instance
+func (f *RevocationFactoryImpl) NewValidator(opts revocation.Options) (revocation.Validator, error) {
+	return revocation.NewWithOptions(opts)
+}
+
+// newFileCache returns a new file cache instance
+func newFileCache(root string) (*crl.FileCache, error) {
+	cacheRoot, err := dir.CacheFS().SysPath(root)
+	if err != nil {
+		return nil, err
+	}
+	return crl.NewFileCache(cacheRoot)
+}
diff --git a/pkg/verifier/notation/revocationfactory.go b/pkg/verifier/notation/revocationfactory.go
new file mode 100644
index 0000000..7860ec2
--- /dev/null
+++ b/pkg/verifier/notation/revocationfactory.go
@@ -0,0 +1,27 @@
+// 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 notation
+
+import (
+	"github.com/notaryproject/notation-core-go/revocation"
+	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
+)
+
+type RevocationFactory interface {
+	// NewFetcher returns a new fetcher instance
+	NewFetcher() (corecrl.Fetcher, error)
+
+	// NewValidator returns a new validator instance
+	NewValidator(revocation.Options) (revocation.Validator, error)
+}


Test patch:
diff --git a/.github/workflows/e2e-aks.yml b/.github/workflows/e2e-aks.yml
index 8e28b48..2cb7fbd 100644
--- a/.github/workflows/e2e-aks.yml
+++ b/.github/workflows/e2e-aks.yml
@@ -52,6 +52,9 @@ jobs:
           # Container Registry:
           az account get-access-token --scope https://containerregistry.azure.net/.default --output none
 
+      - name: Restore Trivy cache
+        uses: ./.github/actions/restore_trivy_cache
+
       - name: Dependencies e2e
         run: |
           mkdir -p $GITHUB_WORKSPACE/bin
diff --git a/.github/workflows/e2e-cli.yml b/.github/workflows/e2e-cli.yml
index 8d1027b..5a2366f 100644
--- a/.github/workflows/e2e-cli.yml
+++ b/.github/workflows/e2e-cli.yml
@@ -75,6 +75,8 @@ jobs:
           go-version: "1.22"
       - name: Run tidy
         run: go mod tidy
+      - name: Restore Trivy cache
+        uses: ./.github/actions/restore_trivy_cache
       - name: Build CLI
         run: make
       - name: Check build
diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml
index e80b65f..2d911b5 100644
--- a/.github/workflows/e2e-k8s.yml
+++ b/.github/workflows/e2e-k8s.yml
@@ -36,7 +36,8 @@ jobs:
         uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
         with:
           go-version: "1.22"
-
+      - name: Restore Trivy cache
+        uses: ./.github/actions/restore_trivy_cache
       - name: Bootstrap e2e
         run: |
           mkdir -p $GITHUB_WORKSPACE/bin
diff --git a/pkg/controllers/utils/kmp_test.go b/pkg/controllers/utils/kmp_test.go
index e3223e4..bc3790f 100644
--- a/pkg/controllers/utils/kmp_test.go
+++ b/pkg/controllers/utils/kmp_test.go
@@ -26,6 +26,7 @@ func TestSpecToKeyManagementProviderProvider(t *testing.T) {
 		name      string
 		raw       []byte
 		kmpType   string
+		resource  string
 		expectErr bool
 	}{
 		{
@@ -36,19 +37,21 @@ func TestSpecToKeyManagementProviderProvider(t *testing.T) {
 			name:      "missing inline provider required fields",
 			raw:       []byte("{\"type\": \"inline\"}"),
 			kmpType:   "inline",
+			resource:  "test",
 			expectErr: true,
 		},
 		{
 			name:      "valid spec",
 			raw:       []byte(`{"type": "inline", "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"}`),
 			kmpType:   "inline",
+			resource:  "test",
 			expectErr: false,
 		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			_, err := SpecToKeyManagementProvider(tc.raw, tc.kmpType)
+			_, err := SpecToKeyManagementProvider(tc.raw, tc.kmpType, tc.resource)
 			if tc.expectErr != (err != nil) {
 				t.Fatalf("Expected error to be %t, got %t", tc.expectErr, err != nil)
 			}
@@ -60,6 +63,7 @@ func TestSpecToKeyManagementProviderProvider(t *testing.T) {
 func TestRawToKeyManagementProviderConfig(t *testing.T) {
 	testCases := []struct {
 		name         string
+		resource     string
 		raw          []byte
 		expectErr    bool
 		expectConfig config.KeyManagementProviderConfig
@@ -72,23 +76,26 @@ func TestRawToKeyManagementProviderConfig(t *testing.T) {
 		},
 		{
 			name:         "unmarshal failure",
+			resource:     "test",
 			raw:          []byte("invalid"),
 			expectErr:    true,
 			expectConfig: config.KeyManagementProviderConfig{},
 		},
 		{
 			name:      "valid Raw",
+			resource:  "test",
 			raw:       []byte("{\"type\": \"inline\"}"),
 			expectErr: false,
 			expectConfig: config.KeyManagementProviderConfig{
-				"type": "inline",
+				"type":     "inline",
+				"resource": "test",
 			},
 		},
 	}
 
 	for _, tc := range testCases {
 		t.Run(tc.name, func(t *testing.T) {
-			config, err := rawToKeyManagementProviderConfig(tc.raw, "inline")
+			config, err := rawToKeyManagementProviderConfig(tc.raw, "inline", "test")
 
 			if tc.expectErr != (err != nil) {
 				t.Fatalf("Expected error to be %t, got %t", tc.expectErr, err != nil)
diff --git a/pkg/keymanagementprovider/azurekeyvault/provider_test.go b/pkg/keymanagementprovider/azurekeyvault/provider_test.go
index 676a438..98effa5 100644
--- a/pkg/keymanagementprovider/azurekeyvault/provider_test.go
+++ b/pkg/keymanagementprovider/azurekeyvault/provider_test.go
@@ -20,12 +20,16 @@ package azurekeyvault
 import (
 	"context"
 	"crypto"
+	"encoding/base64"
+	"errors"
 	"strings"
 	"testing"
 	"time"
 
 	kv "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.1/keyvault"
+	"github.com/Azure/go-autorest/autorest"
 	"github.com/Azure/go-autorest/autorest/azure"
+	"github.com/Azure/go-autorest/autorest/to"
 	"github.com/ratify-project/ratify/internal/version"
 	"github.com/ratify-project/ratify/pkg/keymanagementprovider/azurekeyvault/types"
 	"github.com/ratify-project/ratify/pkg/keymanagementprovider/config"
@@ -185,58 +189,238 @@ func TestCreate(t *testing.T) {
 	}
 }
 
+type MockKvClient struct {
+	GetCertificateFunc func(ctx context.Context, certificateName string, certificateVersion string, arg string) (kv.CertificateBundle, error)
+	GetSecretFunc      func(ctx context.Context, secretName string, secretVersion string, arg string) (kv.SecretBundle, error)
+	GetKeyFunc         func(ctx context.Context, keyName string, keyVersion string, arg string) (kv.KeyBundle, error)
+}
+
+func (m *MockKvClient) GetCertificate(ctx context.Context, certificateName string, certificateVersion string, arg string) (kv.CertificateBundle, error) {
+	if m.GetCertificateFunc != nil {
+		return m.GetCertificateFunc(ctx, certificateName, certificateVersion, arg)
+	}
+	return kv.CertificateBundle{}, nil
+}
+func (m *MockKvClient) GetSecret(ctx context.Context, secretName string, secretVersion string, arg string) (kv.SecretBundle, error) {
+	if m.GetSecretFunc != nil {
+		return m.GetSecretFunc(ctx, secretName, secretVersion, arg)
+	}
+	return kv.SecretBundle{}, nil
+}
+func (m *MockKvClient) GetKey(ctx context.Context, keyName string, keyVersion string, arg string) (kv.KeyBundle, error) {
+	if m.GetKeyFunc != nil {
+		return m.GetKeyFunc(ctx, keyName, keyVersion, arg)
+	}
+	return kv.KeyBundle{}, nil
+}
+
 // TestGetCertificates tests the GetCertificates function
 func TestGetCertificates(t *testing.T) {
-	factory := &akvKMProviderFactory{}
-	config := config.KeyManagementProviderConfig{
-		"vaultUri": "https://testkv.vault.azure.net/",
-		"tenantID": "tid",
-		"clientID": "clientid",
-		"certificates": []map[string]interface{}{
-			{
-				"name":    "cert1",
-				"version": "",
+	testCases := []struct {
+		name         string
+		mockKvClient *MockKvClient
+		expectedErr  bool
+	}{
+		{
+			name: "GetSecret error",
+			mockKvClient: &MockKvClient{
+				GetSecretFunc: func(_ context.Context, _ string, _ string, _ string) (kv.SecretBundle, error) {
+					return kv.SecretBundle{}, errors.New("error")
+				},
 			},
+			expectedErr: true,
+		},
+		{
+			name: "Certificate disabled",
+			mockKvClient: &MockKvClient{
+				GetCertificateFunc: func(_ context.Context, _ string, _ string, _ string) (kv.CertificateBundle, error) {
+					return kv.CertificateBundle{
+						ID:  to.StringPtr("https://testkv.vault.azure.net/certificates/cert1"),
+						Kid: to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						Attributes: &kv.CertificateAttributes{
+							Enabled: to.BoolPtr(false),
+						},
+					}, nil
+				},
+				GetSecretFunc: func(_ context.Context, _ string, _ string, _ string) (kv.SecretBundle, error) {
+					err := autorest.DetailedError{
+						Original: &azure.RequestError{
+							ServiceError: &azure.ServiceError{Code: "SecretDisabled"},
+						},
+					}
+					return kv.SecretBundle{}, err
+				},
+			},
+			expectedErr: false,
+		},
+		{
+			name: "Certificate disabled error",
+			mockKvClient: &MockKvClient{
+				GetCertificateFunc: func(_ context.Context, _ string, _ string, _ string) (kv.CertificateBundle, error) {
+					return kv.CertificateBundle{}, errors.New("error")
+				},
+				GetSecretFunc: func(_ context.Context, _ string, _ string, _ string) (kv.SecretBundle, error) {
+					err := autorest.DetailedError{
+						Original: &azure.RequestError{
+							ServiceError: &azure.ServiceError{Code: "SecretDisabled"},
+						},
+					}
+					return kv.SecretBundle{}, err
+				},
+			},
+			expectedErr: true,
+		},
+		{
+			name: "Certificate enabled",
+			mockKvClient: &MockKvClient{
+				GetCertificateFunc: func(_ context.Context, _ string, _ string, _ string) (kv.CertificateBundle, error) {
+					return kv.CertificateBundle{
+						ID:  to.StringPtr("https://testkv.vault.azure.net/certificates/cert1"),
+						Kid: to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						Attributes: &kv.CertificateAttributes{
+							Enabled: to.BoolPtr(true),
+						},
+					}, nil
+				},
+				GetSecretFunc: func(_ context.Context, _ string, _ string, _ string) (kv.SecretBundle, error) {
+					return kv.SecretBundle{
+						ID:          to.StringPtr("https://testkv.vault.azure.net/secrets/secret1"),
+						Kid:         to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						ContentType: to.StringPtr("application/x-pem-file"),
+						Attributes: &kv.SecretAttributes{
+							Enabled: to.BoolPtr(true),
+						},
+						Value: to.StringPtr("-----BEGIN CERTIFICATE-----\nMIIC8TCCAdmgAwIBAgIUaNrwbhs/I1ecqUYdzD2xuAVNdmowDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzA2MjEwMTIyMzdaFw0yNDA2MjAwMTIyMzdaMBkxFzAVBgNVBAMMDnJhdGlm\neS5kZWZhdWx0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtskG1BUt\n4Fw2lbm53KbwZb1hnLmWdwRotZyznhhk/yrUDcq3uF6klwpk/E2IKfUKIo6doHSk\nXaEZXR68UtXygvA4wdg7xZ6kKpXy0gu+RxGE6CGtDHTyDDzITu+NBjo21ZSsyGpQ\nJeIKftUCHdwdygKf0CdJx8A29GBRpHGCmJadmt7tTzOnYjmbuPVLeqJo/Ex9qXcG\nZbxoxnxr5NCocFeKx+EbLo+k/KjdFB2PKnhgzxAaMMMP6eXPr8l5AlzkC83EmPvN\ntveuaBbamdlFkD+53TZeZlxt3GIdq93Iw/UpbQ/pvhbrztMT+UVEkm15sShfX8Xn\nL2st5A4n0V+66QIDAQABoyAwHjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIH\ngDANBgkqhkiG9w0BAQsFAAOCAQEAGpOqozyfDSBjoTepsRroxxcZ4sq65gw45Bme\nm36BS6FG0WHIg3cMy6KIIBefTDSKrPkKNTtuF25AeGn9jM+26cnfDM78ZH0+Lnn7\n7hs0MA64WMPQaWs9/+89aM9NADV9vp2zdG4xMi6B7DruvKWyhJaNoRqK/qP6LdSQ\nw8M+21sAHvXgrRkQtJlVOzVhgwt36NOb1hzRlQiZB+nhv2Wbw7fbtAaADk3JAumf\nvM+YdPS1KfAFaYefm4yFd+9/C0KOkHico3LTbELO5hG0Mo/EYvtjM+Fljb42EweF\n3nAx1GSPe5Tn8p3h6RyJW5HIKozEKyfDuLS0ccB/nqT3oNjcTw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIDRTCCAi2gAwIBAgIUcC33VfaMhOnsl7avNTRVQozoVtUwDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzA2MjEwMTIyMzZaFw0yMzA2MjIwMTIyMzZaMCoxDzANBgNVBAoMBlJhdGlm\neTEXMBUGA1UEAwwOUmF0aWZ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\nDwAwggEKAoIBAQDDFhDnyPrVDZaeRu6Tbg1a/iTwus+IuX+h8aKhKS1yHz4EF/Lz\nxCy7lNSQ9srGMMVumWuNom/ydIphff6PejZM1jFKPU6OQR/0JX5epcVIjbKa562T\nDguUxJ+h5V3EIyM4RqOWQ2g/xZo86x5TzyNJXiVdHHRvmDvUNwPpMeDjr/EHVAni\n5YQObxkJRiiZ7XOa5zz3YztVm8sSZAwPWroY1HIfvtP+KHpiNDIKSymmuJkH4SEr\nJn++iqN8na18a9DFBPTTrLPe3CxATGrMfosCMZ6LP3iFLLc/FaSpwcnugWdewsUK\nYs+sUY7jFWR7x7/1nyFWyRrQviM4f4TY+K7NAgMBAAGjYzBhMB0GA1UdDgQWBBQH\nYePW7QPP2p1utr3r6gqzEkKs+DAfBgNVHSMEGDAWgBQHYePW7QPP2p1utr3r6gqz\nEkKs+DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDANBgkqhkiG9w0B\nAQsFAAOCAQEAjKp4vx3bFaKVhAbQeTsDjWJgmXLK2vLgt74MiUwSF6t0wehlfszE\nIcJagGJsvs5wKFf91bnwiqwPjmpse/thPNBAxh1uEoh81tOklv0BN790vsVpq3t+\ncnUvWPiCZdRlAiGGFtRmKk3Keq4sM6UdiUki9s+wnxypHVb4wIpVxu5R271Lnp5I\n+rb2EQ48iblt4XZPczf/5QJdTgbItjBNbuO8WVPOqUIhCiFuAQziLtNUq3p81dHO\nQ2BPgmaitCpIUYHVYighLauBGCH8xOFzj4a4KbOxKdxyJTd0La/vRCKaUtJX67Lc\nfQYVR9HXQZ0YlmwPcmIG5v7wBfcW34NUvA==\n-----END CERTIFICATE-----\n"),
+					}, nil
+				},
+			},
+		},
+		{
+			name: "getCertsFromSecretBundle error",
+			mockKvClient: &MockKvClient{
+				GetSecretFunc: func(_ context.Context, _ string, _ string, _ string) (kv.SecretBundle, error) {
+					return kv.SecretBundle{
+						ContentType: to.StringPtr("test"),
+						ID:          to.StringPtr("https://testkv.vault.azure.net/secrets/secret1"),
+						Kid:         to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						Attributes: &kv.SecretAttributes{
+							Enabled: to.BoolPtr(true),
+						},
+						Value: to.StringPtr("-----BEGIN CERTIFICATE-----\nMIIC8TCCAdmgAwIBAgIUaNrwbhs/I1ecqUYdzD2xuAVNdmowDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzA2MjEwMTIyMzdaFw0yNDA2MjAwMTIyMzdaMBkxFzAVBgNVBAMMDnJhdGlm\neS5kZWZhdWx0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtskG1BUt\n4Fw2lbm53KbwZb1hnLmWdwRotZyznhhk/yrUDcq3uF6klwpk/E2IKfUKIo6doHSk\nXaEZXR68UtXygvA4wdg7xZ6kKpXy0gu+RxGE6CGtDHTyDDzITu+NBjo21ZSsyGpQ\nJeIKftUCHdwdygKf0CdJx8A29GBRpHGCmJadmt7tTzOnYjmbuPVLeqJo/Ex9qXcG\nZbxoxnxr5NCocFeKx+EbLo+k/KjdFB2PKnhgzxAaMMMP6eXPr8l5AlzkC83EmPvN\ntveuaBbamdlFkD+53TZeZlxt3GIdq93Iw/UpbQ/pvhbrztMT+UVEkm15sShfX8Xn\nL2st5A4n0V+66QIDAQABoyAwHjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIH\ngDANBgkqhkiG9w0BAQsFAAOCAQEAGpOqozyfDSBjoTepsRroxxcZ4sq65gw45Bme\nm36BS6FG0WHIg3cMy6KIIBefTDSKrPkKNTtuF25AeGn9jM+26cnfDM78ZH0+Lnn7\n7hs0MA64WMPQaWs9/+89aM9NADV9vp2zdG4xMi6B7DruvKWyhJaNoRqK/qP6LdSQ\nw8M+21sAHvXgrRkQtJlVOzVhgwt36NOb1hzRlQiZB+nhv2Wbw7fbtAaADk3JAumf\nvM+YdPS1KfAFaYefm4yFd+9/C0KOkHico3LTbELO5hG0Mo/EYvtjM+Fljb42EweF\n3nAx1GSPe5Tn8p3h6RyJW5HIKozEKyfDuLS0ccB/nqT3oNjcTw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIDRTCCAi2gAwIBAgIUcC33VfaMhOnsl7avNTRVQozoVtUwDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzA2MjEwMTIyMzZaFw0yMzA2MjIwMTIyMzZaMCoxDzANBgNVBAoMBlJhdGlm\neTEXMBUGA1UEAwwOUmF0aWZ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\nDwAwggEKAoIBAQDDFhDnyPrVDZaeRu6Tbg1a/iTwus+IuX+h8aKhKS1yHz4EF/Lz\nxCy7lNSQ9srGMMVumWuNom/ydIphff6PejZM1jFKPU6OQR/0JX5epcVIjbKa562T\nDguUxJ+h5V3EIyM4RqOWQ2g/xZo86x5TzyNJXiVdHHRvmDvUNwPpMeDjr/EHVAni\n5YQObxkJRiiZ7XOa5zz3YztVm8sSZAwPWroY1HIfvtP+KHpiNDIKSymmuJkH4SEr\nJn++iqN8na18a9DFBPTTrLPe3CxATGrMfosCMZ6LP3iFLLc/FaSpwcnugWdewsUK\nYs+sUY7jFWR7x7/1nyFWyRrQviM4f4TY+K7NAgMBAAGjYzBhMB0GA1UdDgQWBBQH\nYePW7QPP2p1utr3r6gqzEkKs+DAfBgNVHSMEGDAWgBQHYePW7QPP2p1utr3r6gqz\nEkKs+DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDANBgkqhkiG9w0B\nAQsFAAOCAQEAjKp4vx3bFaKVhAbQeTsDjWJgmXLK2vLgt74MiUwSF6t0wehlfszE\nIcJagGJsvs5wKFf91bnwiqwPjmpse/thPNBAxh1uEoh81tOklv0BN790vsVpq3t+\ncnUvWPiCZdRlAiGGFtRmKk3Keq4sM6UdiUki9s+wnxypHVb4wIpVxu5R271Lnp5I\n+rb2EQ48iblt4XZPczf/5QJdTgbItjBNbuO8WVPOqUIhCiFuAQziLtNUq3p81dHO\nQ2BPgmaitCpIUYHVYighLauBGCH8xOFzj4a4KbOxKdxyJTd0La/vRCKaUtJX67Lc\nfQYVR9HXQZ0YlmwPcmIG5v7wBfcW34NUvA==\n-----END CERTIFICATE-----\n"),
+					}, nil
+				},
+			},
+			expectedErr: true,
 		},
 	}
 
-	provider, err := factory.Create("v1", config, "")
-	if err != nil {
-		t.Fatalf("expected no err but got error = %v", err)
-	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			provider := &akvKMProvider{
+				certificates: []types.KeyVaultValue{
+					{
+						Name:    "cert1",
+						Version: "c1f03df1113d460491d970737dfdc35d",
+					},
+				},
+				kvClient: tc.mockKvClient,
+			}
 
-	certs, certStatus, err := provider.GetCertificates(context.Background())
-	assert.NotNil(t, err)
-	assert.Nil(t, certs)
-	assert.Nil(t, certStatus)
+			_, _, err := provider.GetCertificates(context.Background())
+			if tc.expectedErr != (err != nil) {
+				t.Fatalf("error = %v, expectedErr = %v", err, tc.expectedErr)
+			}
+		})
+	}
 }
 
 // TestGetKeys tests the GetKeys function
 func TestGetKeys(t *testing.T) {
-	factory := &akvKMProviderFactory{}
-	config := config.KeyManagementProviderConfig{
-		"vaultUri": "https://testkv.vault.azure.net/",
-		"tenantID": "tid",
-		"clientID": "clientid",
-		"keys": []map[string]interface{}{
-			{
-				"name": "key1",
+	testCases := []struct {
+		name         string
+		mockKvClient *MockKvClient
+		expectedErr  bool
+	}{
+		{
+			name: "GetKey error",
+			mockKvClient: &MockKvClient{
+				GetKeyFunc: func(_ context.Context, _ string, _ string, _ string) (kv.KeyBundle, error) {
+					return kv.KeyBundle{}, errors.New("error")
+				},
 			},
+			expectedErr: true,
+		},
+		{
+			name: "Key disabled",
+			mockKvClient: &MockKvClient{
+				GetKeyFunc: func(_ context.Context, _ string, _ string, _ string) (kv.KeyBundle, error) {
+					return kv.KeyBundle{
+						Key: &kv.JSONWebKey{
+							Kid: to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						},
+						Attributes: &kv.KeyAttributes{
+							Enabled: to.BoolPtr(false),
+						},
+					}, nil
+				},
+			},
+			expectedErr: false,
+		},
+		{
+			name: "getKeyFromKeyBundle error",
+			mockKvClient: &MockKvClient{
+				GetKeyFunc: func(_ context.Context, _ string, _ string, _ string) (kv.KeyBundle, error) {
+					return kv.KeyBundle{
+						Key: &kv.JSONWebKey{
+							Kid: to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+						},
+						Attributes: &kv.KeyAttributes{
+							Enabled: to.BoolPtr(true),
+						},
+					}, nil
+				},
+			},
+			expectedErr: true,
+		},
+		{
+			name: "Key enabled",
+			mockKvClient: &MockKvClient{
+				GetKeyFunc: func(_ context.Context, _ string, _ string, _ string) (kv.KeyBundle, error) {
+					return kv.KeyBundle{
+						Key: &kv.JSONWebKey{
+							Kid: to.StringPtr("https://testkv.vault.azure.net/keys/key1"),
+							Kty: kv.RSA,
+							N:   to.StringPtr(base64.StdEncoding.EncodeToString([]byte("n"))),
+							E:   to.StringPtr(base64.StdEncoding.EncodeToString([]byte("e"))),
+						},
+						Attributes: &kv.KeyAttributes{
+							Enabled: to.BoolPtr(true),
+						},
+					}, nil
+				},
+			},
+			expectedErr: false,
 		},
 	}
 
-	initKVClient = func(_ context.Context, _, _, _, _ string) (*kv.BaseClient, error) {
-		return &kv.BaseClient{}, nil
-	}
-	provider, err := factory.Create("v1", config, "")
-	if err != nil {
-		t.Fatalf("expected no err but got error = %v", err)
-	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			provider := &akvKMProvider{
+				keys: []types.KeyVaultValue{
+					{
+						Name:    "key1",
+						Version: "c1f03df1113d460491d970737dfdc35d",
+					},
+				},
+				kvClient: tc.mockKvClient,
+			}
 
-	keys, keyStatus, err := provider.GetKeys(context.Background())
-	assert.NotNil(t, err)
-	assert.Nil(t, keys)
-	assert.Nil(t, keyStatus)
+			_, _, err := provider.GetKeys(context.Background())
+			if tc.expectedErr != (err != nil) {
+				t.Fatalf("error = %v, expectedErr = %v", err, tc.expectedErr)
+			}
+		})
+	}
 }
 
 func TestIsRefreshable(t *testing.T) {
@@ -288,8 +472,9 @@ func TestGetStatusProperty(t *testing.T) {
 	timeNow := time.Now().String()
 	certName := "certName"
 	certVersion := "versionABC"
+	isEnabled := true
 
-	status := getStatusProperty(certName, certVersion, timeNow)
+	status := getStatusProperty(certName, certVersion, timeNow, isEnabled)
 	assert.Equal(t, certName, status[types.StatusName])
 	assert.Equal(t, timeNow, status[types.StatusLastRefreshed])
 	assert.Equal(t, certVersion, status[types.StatusVersion])
@@ -349,7 +534,7 @@ func TestGetCertsFromSecretBundle(t *testing.T) {
 				ContentType: &cases[i].contentType,
 			}
 
-			certs, status, err := getCertsFromSecretBundle(context.Background(), testdata, "certName")
+			certs, status, err := getCertsFromSecretBundle(context.Background(), testdata, "certName", true)
 			if tc.expectedErr {
 				assert.NotNil(t, err)
 				assert.Nil(t, certs)
diff --git a/pkg/keymanagementprovider/keymanagementprovider_test.go b/pkg/keymanagementprovider/keymanagementprovider_test.go
index 0441562..57a2828 100644
--- a/pkg/keymanagementprovider/keymanagementprovider_test.go
+++ b/pkg/keymanagementprovider/keymanagementprovider_test.go
@@ -176,11 +176,19 @@ func TestGetCertificatesFromMap_ErrorFromReconcile(t *testing.T) {
 
 // TestDeleteCertificatesFromMap checks if certificates are deleted from the map
 func TestDeleteCertificatesFromMap(t *testing.T) {
-	certificatesMap.Delete("test")
-	setCertificatesInMap("test", map[KMPMapKey][]*x509.Certificate{{}: {{Raw: []byte("testcert")}}})
-	DeleteResourceFromMap("test")
-	if _, ok := certificatesMap.Load("test"); ok {
-		t.Fatalf("certificatesMap should have been deleted for key")
+	resource := "test"
+	disabledCert := KMPMapKey{Name: "test", Version: "0", Enabled: false}
+	enabledCert := KMPMapKey{Name: "test", Version: "1", Enabled: true}
+	certsMap := map[KMPMapKey][]*x509.Certificate{}
+	certsMap[disabledCert] = []*x509.Certificate{{Raw: []byte("testcert")}}
+	certsMap[enabledCert] = []*x509.Certificate{{Raw: []byte("testcert")}}
+	setCertificatesInMap(resource, certsMap)
+	DeleteCertificateFromMap(resource, disabledCert)
+
+	certs, _ := GetCertificatesFromMap(context.Background(), resource)
+
+	if len(certs) != 1 {
+		t.Fatalf("certificates should have been deleted from the map")
 	}
 }
 
@@ -252,11 +260,17 @@ func TestGetKeysFromMap_AccessDifferentNamespace_ReturnsFalse(t *testing.T) {
 
 // TestDeleteKeysFromMap checks if key map entry is deleted from the map
 func TestDeleteKeysFromMap(t *testing.T) {
-	keyMap.Delete("test")
-	setKeysInMap("test", "", map[KMPMapKey]crypto.PublicKey{{}: &rsa.PublicKey{}})
-	DeleteResourceFromMap("test")
-	if _, ok := keyMap.Load("test"); ok {
-		t.Fatalf("keysMap should have been deleted for key")
+	resource := "test"
+	keysMap := map[KMPMapKey]crypto.PublicKey{}
+	keyMapKey0 := KMPMapKey{Name: "test", Version: "0", Enabled: false}
+	keyMapKey1 := KMPMapKey{Name: "test", Version: "1", Enabled: true}
+	keysMap[keyMapKey0] = crypto.PublicKey(&rsa.PublicKey{})
+	keysMap[keyMapKey1] = crypto.PublicKey(&rsa.PublicKey{})
+	setKeysInMap(resource, "", keysMap)
+	DeleteKeyFromMap(resource, keyMapKey1)
+	keys, _ := GetKeysFromMap(context.Background(), resource)
+	if len(keys) != 1 {
+		t.Fatalf("keys should have been deleted from the map")
 	}
 }
 
diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go
index dc34a1f..bf2fa4a 100644
--- a/pkg/verifier/notation/notation_test.go
+++ b/pkg/verifier/notation/notation_test.go
@@ -18,10 +18,14 @@ import (
 	"crypto/x509"
 	"crypto/x509/pkix"
 	"fmt"
+	"net/http"
 	paths "path/filepath"
 	"reflect"
 	"testing"
 
+	"github.com/notaryproject/notation-core-go/revocation"
+	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
+	"github.com/notaryproject/notation-core-go/revocation/purpose"
 	sig "github.com/notaryproject/notation-core-go/signature"
 	"github.com/notaryproject/notation-go"
 	"github.com/opencontainers/go-digest"
@@ -558,3 +562,102 @@ func TestNormalizeLegacyCertStore(t *testing.T) {
 		})
 	}
 }
+func TestGetVerifierService(t *testing.T) {
+	tests := []struct {
+		name              string
+		conf              *NotationPluginVerifierConfig
+		pluginDir         string
+		RevocationFactory RevocationFactory
+		expectErr         bool
+		errContent        error
+	}{
+		{
+			name: "failed to create CRL fetcher",
+			conf: &NotationPluginVerifierConfig{
+				VerificationCerts: []string{defaultCertDir},
+			},
+			pluginDir:         "",
+			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failFetcher: true},
+			expectErr:         true,
+			errContent:        nil,
+		},
+		{
+			name: "failed to create file cache",
+			conf: &NotationPluginVerifierConfig{
+				VerificationCerts: []string{defaultCertDir},
+			},
+			pluginDir:         "",
+			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failFileCache: true},
+			expectErr:         true,
+			errContent:        nil,
+		},
+		{
+			name: "failed to create code signing validator",
+			conf: &NotationPluginVerifierConfig{
+				VerificationCerts: []string{defaultCertDir},
+			},
+			pluginDir:         "",
+			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failCodeSigningValidator: true},
+			expectErr:         true,
+			errContent:        fmt.Errorf("failed to create code signing validator"),
+		},
+		{
+			name: "failed to create timestamping validator",
+			conf: &NotationPluginVerifierConfig{
+				VerificationCerts: []string{defaultCertDir},
+			},
+			pluginDir:         "",
+			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failTimestampingValidator: true},
+			expectErr:         true,
+			errContent:        fmt.Errorf("failed to create timestamping validator"),
+		},
+		{
+			name: "failed to create verifier",
+			conf: &NotationPluginVerifierConfig{
+				VerificationCerts: []string{defaultCertDir},
+			},
+			pluginDir:         "",
+			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}, failVerifier: true},
+			expectErr:         true,
+			errContent:        nil,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			_, err := getVerifierService(tt.conf, tt.pluginDir, tt.RevocationFactory)
+			if (err != nil) != tt.expectErr {
+				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
+			}
+			if tt.errContent != nil && err.Error() != tt.errContent.Error() {
+				t.Errorf("error = %v, expectErr = %v, content = %v", err, tt.expectErr, tt.errContent)
+			}
+		})
+	}
+}
+
+type mockRevocationFactory struct {
+	failFetcher               bool
+	failFileCache             bool
+	failCodeSigningValidator  bool
+	failTimestampingValidator bool
+	failVerifier              bool
+	httpClient                *http.Client
+}
+
+func (m mockRevocationFactory) NewFetcher() (corecrl.Fetcher, error) {
+	if m.failFetcher {
+		return nil, fmt.Errorf("failed to create fetcher")
+	}
+	return corecrl.NewHTTPFetcher(m.httpClient)
+}
+
+func (m mockRevocationFactory) NewValidator(opts revocation.Options) (revocation.Validator, error) {
+	if m.failCodeSigningValidator && opts.CertChainPurpose == purpose.CodeSigning {
+		return nil, fmt.Errorf("failed to create code signing validator")
+	}
+	if m.failTimestampingValidator && opts.CertChainPurpose == purpose.Timestamping {
+		return nil, fmt.Errorf("failed to create timestamping validator")
+	}
+	return revocation.NewWithOptions(opts)
+}
diff --git a/pkg/verifier/notation/notationrevocationfactory_test.go b/pkg/verifier/notation/notationrevocationfactory_test.go
new file mode 100644
index 0000000..b5355f8
--- /dev/null
+++ b/pkg/verifier/notation/notationrevocationfactory_test.go
@@ -0,0 +1,103 @@
+// 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 notation
+
+import (
+	"net/http"
+	"runtime"
+	"testing"
+
+	"github.com/notaryproject/notation-core-go/revocation"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewRevocationFactoryImpl(t *testing.T) {
+	factory := NewRevocationFactoryImpl()
+	assert.NotNil(t, factory)
+}
+
+func TestNewFetcher(t *testing.T) {
+	tests := []struct {
+		name       string
+		cacheRoot  string
+		httpClient *http.Client
+		wantErr    bool
+	}{
+		{
+			name:       "valid fetcher",
+			cacheRoot:  "/valid/path",
+			httpClient: &http.Client{},
+			wantErr:    false,
+		},
+		{
+			name:       "invalid fetcher with nil httpClient",
+			cacheRoot:  "/valid/path",
+			httpClient: nil,
+			wantErr:    true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			factory := &RevocationFactoryImpl{
+				cacheRoot:  tt.cacheRoot,
+				httpClient: tt.httpClient,
+			}
+
+			fetcher, err := factory.NewFetcher()
+			if tt.wantErr {
+				assert.Error(t, err)
+				assert.Nil(t, fetcher)
+			}
+		})
+	}
+}
+
+func TestNewValidator(t *testing.T) {
+	factory := &RevocationFactoryImpl{}
+	opts := revocation.Options{}
+
+	validator, err := factory.NewValidator(opts)
+	assert.NoError(t, err)
+	assert.NotNil(t, validator)
+}
+func TestNewFileCache(t *testing.T) {
+	tests := []struct {
+		name      string
+		cacheRoot string
+		wantErr   bool
+	}{
+		{
+			name:      "valid cache root",
+			cacheRoot: "/valid/path",
+			wantErr:   false,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if runtime.GOOS == "windows" {
+				t.Skip("skipping test on Windows")
+			}
+			cache, err := newFileCache(tt.cacheRoot)
+			if tt.wantErr {
+				assert.Error(t, err)
+				assert.Nil(t, cache)
+			} else {
+				assert.NoError(t, err)
+				assert.NotNil(t, cache)
+			}
+		})
+	}
+}