Repository: ratify-project/ratify
Pull request #2231 (2025-05-10 14:44:20)

feat!: add v2 verifier
# Description

## What this PR does / why we need it:
1. Add verifier factory to register V2 verifier plugins.
2. Add notation verifier based on v2 ratify-verifier-go implementation.
3. Define the `keyProvider` interface for fetching certs from given source, which will be used for verifiers. In this PR, this interface only supports fetching certs from local file system.
4. Remove v1 verifier.

## Which issue(s) this PR fixes *(optional, using `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when the PR gets merged)*:
Fixes #

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Helm Chart Change (any edit/addition/update that is necessary for changes merged to the `main` branch)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Please also list any relevant details for your test configuration
Added unit tests.


# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [ ] Do all new files have appropriate license header?

# Post Merge Requirements
- [ ] MAINTAINERS: manually trigger the "Publish Package" workflow after merging any PR that indicates `Helm Chart Change`


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) Report
Attention: Patch coverage is `94.88372%` with `11 lines` in your changes missing coverage. Please review.

| [Files with missing lines](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) | Patch % | Lines |
|---|---|---|
| [...erifier/keyprovider/filesystemprovider/register.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Fkeyprovider%2Ffilesystemprovider%2Fregister.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIva2V5cHJvdmlkZXIvZmlsZXN5c3RlbXByb3ZpZGVyL3JlZ2lzdGVyLmdv) | 87.69% | [6 Missing and 2 partials :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |
| [internal/verifier/factory/notation/register.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Ffactory%2Fnotation%2Fregister.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIvZmFjdG9yeS9ub3RhdGlvbi9yZWdpc3Rlci5nbw==) | 96.77% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) |

| [Files with missing lines](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project) | Coverage Δ | |
|---|---|---|
| [internal/verifier/factory/factory.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Ffactory%2Ffactory.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIvZmFjdG9yeS9mYWN0b3J5Lmdv) | `100.00% <100.00%> (ø)` | |
| [internal/verifier/factory/notation/truststore.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Ffactory%2Fnotation%2Ftruststore.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIvZmFjdG9yeS9ub3RhdGlvbi90cnVzdHN0b3JlLmdv) | `100.00% <100.00%> (ø)` | |
| [internal/verifier/keyprovider/api.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Fkeyprovider%2Fapi.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIva2V5cHJvdmlkZXIvYXBpLmdv) | `100.00% <100.00%> (ø)` | |
| [internal/verifier/verifier.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Fverifier.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIvdmVyaWZpZXIuZ28=) | `100.00% <100.00%> (ø)` | |
| [internal/verifier/factory/notation/register.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Ffactory%2Fnotation%2Fregister.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIvZmFjdG9yeS9ub3RhdGlvbi9yZWdpc3Rlci5nbw==) | `96.77% <96.77%> (ø)` | |
| [...erifier/keyprovider/filesystemprovider/register.go](https://app.codecov.io/gh/ratify-project/ratify/pull/2231?src=pr&el=tree&filepath=internal%2Fverifier%2Fkeyprovider%2Ffilesystemprovider%2Fregister.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=ratify-project#diff-aW50ZXJuYWwvdmVyaWZpZXIva2V5cHJvdmlkZXIvZmlsZXN5c3RlbXByb3ZpZGVyL3JlZ2lzdGVyLmdv) | `87.69% <87.69%> (ø)` | |

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/go.mod b/go.mod
index f71077e..9faeb50 100644
--- a/go.mod
+++ b/go.mod
@@ -110,6 +110,8 @@ require (
 	github.com/mozillazg/docker-credential-acr-helper v0.3.0 // indirect
 	github.com/notaryproject/tspclient-go v1.0.0 // indirect
 	github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
+	github.com/ratify-project/ratify-go v0.0.0-20250409071324-ecbad89bc5e1 // indirect
+	github.com/ratify-project/ratify-verifier-go/notation v0.0.0-20250411030115-011378ff3b1c // indirect
 	github.com/sagikazarmark/locafero v0.7.0 // indirect
 	github.com/segmentio/ksuid v1.0.4 // indirect
 	github.com/sigstore/fulcio v1.4.5 // indirect
diff --git a/go.sum b/go.sum
index 52b16d3..5d91f5d 100644
--- a/go.sum
+++ b/go.sum
@@ -631,6 +631,10 @@ github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf h1:014O62
 github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
 github.com/ratify-project/ratify v1.4.0 h1:G6rfBjvuTDGiIDrFnooTVh5KClI7NLze0D6yRKk16yI=
 github.com/ratify-project/ratify v1.4.0/go.mod h1:Xge1uKFYyy9asKFxI5rr6rnFfb4NNIsOGGX4j7n2CcE=
+github.com/ratify-project/ratify-go v0.0.0-20250409071324-ecbad89bc5e1 h1:aGYLDSvB5R7P5qoRCusgsc0YqymTLLfWL3HlKMaL714=
+github.com/ratify-project/ratify-go v0.0.0-20250409071324-ecbad89bc5e1/go.mod h1:UeSnXpHhlaQCWU+sMBQng7gj54Y39dn1nG89OXVk+ec=
+github.com/ratify-project/ratify-verifier-go/notation v0.0.0-20250411030115-011378ff3b1c h1:rK0nLxnwXfp7geKZoz+L+v7Qgmj7tHrVIzs8RYcaqPI=
+github.com/ratify-project/ratify-verifier-go/notation v0.0.0-20250411030115-011378ff3b1c/go.mod h1:4yM27kKLcc5k627/LmpoeFR99i+76kopa/7joMzxDPk=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
diff --git a/internal/verifier/factory/factory.go b/internal/verifier/factory/factory.go
new file mode 100644
index 0000000..f68bd3d
--- /dev/null
+++ b/internal/verifier/factory/factory.go
@@ -0,0 +1,68 @@
+/*
+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 factory
+
+import (
+	"fmt"
+
+	"github.com/ratify-project/ratify-go"
+)
+
+// NewVerifierOptions holds the options to create a verifier.
+type NewVerifierOptions struct {
+	// Name is the unique identifier of a verifier instance. Required.
+	Name string `json:"name"`
+
+	// Type represents a specific implementation of a verifier. Required.
+	// Note: there could be multiple verifiers of the same type with different
+	//       names.
+	Type string `json:"type"`
+
+	// Parameters is additional parameters of the verifier. Optional.
+	Parameters any `json:"parameters,omitempty"`
+}
+
+// registeredVerifiers saves the registered verifier factories.
+var registeredVerifiers map[string]func(NewVerifierOptions) (ratify.Verifier, error)
+
+// RegisterVerifierFactory registers a verifier factory to the system.
+func RegisterVerifierFactory(verifierType string, create func(NewVerifierOptions) (ratify.Verifier, error)) {
+	if verifierType == "" {
+		panic("verifier type cannot be empty. Please provide a non-empty string representing a valid verifier.")
+	}
+	if create == nil {
+		panic("verifier factory cannot be nil")
+	}
+	if registeredVerifiers == nil {
+		registeredVerifiers = make(map[string]func(NewVerifierOptions) (ratify.Verifier, error))
+	}
+	if _, registered := registeredVerifiers[verifierType]; registered {
+		panic(fmt.Sprintf("verifier factory named %s already registered", verifierType))
+	}
+	registeredVerifiers[verifierType] = create
+}
+
+// NewVerifier creates a verifier instance if it belongs to a registered type.
+func NewVerifier(opts NewVerifierOptions) (ratify.Verifier, error) {
+	if opts.Name == "" || opts.Type == "" {
+		return nil, fmt.Errorf("name or type is not provided in the verifier options")
+	}
+	verifierFactory, ok := registeredVerifiers[opts.Type]
+	if !ok {
+		return nil, fmt.Errorf("verifier factory of type %s is not registered", opts.Type)
+	}
+	return verifierFactory(opts)
+}
diff --git a/internal/verifier/factory/notation/register.go b/internal/verifier/factory/notation/register.go
new file mode 100644
index 0000000..2d32323
--- /dev/null
+++ b/internal/verifier/factory/notation/register.go
@@ -0,0 +1,170 @@
+/*
+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 (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	"github.com/notaryproject/notation-go/verifier/trustpolicy"
+	"github.com/notaryproject/notation-go/verifier/truststore"
+	"github.com/ratify-project/ratify-go"
+	"github.com/ratify-project/ratify-verifier-go/notation"
+	"github.com/ratify-project/ratify/v2/internal/verifier/factory"
+	"github.com/ratify-project/ratify/v2/internal/verifier/keyprovider"
+	_ "github.com/ratify-project/ratify/v2/internal/verifier/keyprovider/filesystemprovider" // Register the filesystem key provider
+	"github.com/sirupsen/logrus"
+)
+
+const (
+	notationType   = "notation"
+	trustStoreName = "ratify"
+	typeKey        = "type"
+)
+
+// trustStoreOptions is a map of options for the trust stores. The value of the
+// "type" key must be one of the following: "ca", "tsa", or "signingAuthority".
+// If the "type" key is not present, the default type is "ca".
+// Other keys in the map are used to create key providers. Each trust store can
+// have multiple key providers.
+type trustStoreOptions map[string]any
+
+type options struct {
+	// Scope is a list of registry scopes to be used by the Notation
+	// verifier. Optional. If not provided, the default scope is "*".
+	Scope []string `json:"scope"`
+
+	// TrustedIdentities is a list of trusted identities to be used by the
+	// Notation verifier. Optional. If not provided, default identity is "*".
+	TrustedIdentities []string `json:"trustedIdentities"`
+
+	// Certificates is a list of certificates to be used by the Notation
+	// verifier. Certificates would be loaded into trust store for Notation
+	// verifier to access. Required.
+	Certificates []trustStoreOptions `json:"certificates"`
+}
+
+func init() {
+	factory.RegisterVerifierFactory(notationType, func(opts factory.NewVerifierOptions) (ratify.Verifier, error) {
+		raw, err := json.Marshal(opts.Parameters)
+		if err != nil {
+			return nil, fmt.Errorf("failed to marshal verifier parameters: %w", err)
+		}
+
+		var params options
+		if err := json.Unmarshal(raw, &params); err != nil {
+			return nil, fmt.Errorf("failed to unmarshal verifier parameters: %w", err)
+		}
+
+		trustStore, types, err := initTrustStore(params.Certificates)
+		if err != nil {
+			return nil, fmt.Errorf("failed to initialize trust store: %w", err)
+		}
+
+		logrus.Infof("trust policy: %+v", initTrustPolicyDocument(params.Scope, params.TrustedIdentities, types))
+
+		notationOpts := &notation.VerifierOptions{
+			Name:           opts.Name,
+			TrustPolicyDoc: initTrustPolicyDocument(params.Scope, params.TrustedIdentities, types),
+			TrustStore:     trustStore,
+		}
+
+		return notation.NewVerifier(notationOpts)
+	})
+}
+
+func initTrustStore(opts []trustStoreOptions) (truststore.X509TrustStore, []truststore.Type, error) {
+	if len(opts) == 0 {
+		return nil, nil, fmt.Errorf("no trust store options provided")
+	}
+
+	trustStore := newTrustStore()
+	types := make(map[truststore.Type]struct{})
+	for _, opt := range opts {
+		var err error
+		storeType := truststore.TypeCA
+		if typeVal, ok := opt[typeKey]; ok {
+			if storeType, err = getTrustStoreType(typeVal); err != nil {
+				return nil, nil, fmt.Errorf("failed to get trust store type: %w", err)
+			}
+		}
+		if _, exists := types[storeType]; exists {
+			return nil, nil, fmt.Errorf("duplicate trust store type %s detected. Please check your configuration to ensure each trust store type is unique", storeType)
+		}
+		types[storeType] = struct{}{}
+
+		for key, val := range opt {
+			if key == typeKey {
+				continue
+			}
+			provider, err := keyprovider.CreateKeyProvider(key, val)
+			if err != nil {
+				return nil, nil, fmt.Errorf("failed to get key provider %s: %w", key, err)
+			}
+			certs, err := provider.GetCertificates(context.Background())
+			if err != nil {
+				return nil, nil, fmt.Errorf("failed to get certificates from provider %s: %w", key, err)
+			}
+
+			trustStore.addCertificates(storeType, trustStoreName, certs)
+		}
+	}
+	names := make([]truststore.Type, 0, len(types))
+	for storeType := range types {
+		names = append(names, storeType)
+	}
+	return trustStore, names, nil
+}
+
+func getTrustStoreType(val any) (truststore.Type, error) {
+	t, ok := val.(string)
+	if !ok {
+		return "", fmt.Errorf("trust store type must be a string")
+	}
+	storeType := truststore.Type(t)
+	if storeType != truststore.TypeCA && storeType != truststore.TypeTSA && storeType != truststore.TypeSigningAuthority {
+		return "", fmt.Errorf("invalid trust store type %s", storeType)
+	}
+	return storeType, nil
+}
+
+func initTrustPolicyDocument(scopes, trustedIdentities []string, storeTypes []truststore.Type) *trustpolicy.Document {
+	if len(scopes) == 0 {
+		scopes = []string{"*"}
+	}
+	if len(trustedIdentities) == 0 {
+		trustedIdentities = []string{"*"}
+	}
+	trustStoreNames := make([]string, len(storeTypes))
+	for i, storeType := range storeTypes {
+		trustStoreNames[i] = fmt.Sprintf("%s:%s", storeType, trustStoreName)
+	}
+	return &trustpolicy.Document{
+		Version: "1.0",
+		TrustPolicies: []trustpolicy.TrustPolicy{
+			{
+				Name:           "default",
+				RegistryScopes: scopes,
+				SignatureVerification: trustpolicy.SignatureVerification{
+					VerificationLevel: "strict",
+				},
+				TrustStores:       trustStoreNames,
+				TrustedIdentities: trustedIdentities,
+			},
+		},
+	}
+}
diff --git a/internal/verifier/factory/notation/truststore.go b/internal/verifier/factory/notation/truststore.go
new file mode 100644
index 0000000..2ac9f02
--- /dev/null
+++ b/internal/verifier/factory/notation/truststore.go
@@ -0,0 +1,54 @@
+/*
+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 (
+	"context"
+	"crypto/x509"
+
+	"github.com/notaryproject/notation-go/verifier/truststore"
+	"github.com/sirupsen/logrus"
+)
+
+type trustStore struct {
+	stores map[truststore.Type]map[string][]*x509.Certificate
+}
+
+func newTrustStore() *trustStore {
+	return &trustStore{
+		stores: make(map[truststore.Type]map[string][]*x509.Certificate),
+	}
+}
+
+// GetCertificates implements [truststore.X509TrustStore] interface.
+func (s *trustStore) GetCertificates(_ context.Context, storeType truststore.Type, namedStore string) ([]*x509.Certificate, error) {
+	logrus.Infof("Getting certificates from trust store %s", namedStore)
+	if namedStores, ok := s.stores[storeType]; ok {
+		if certs, ok := namedStores[namedStore]; ok {
+			logrus.Infof("Found %d certificates in trust store %s", len(certs), namedStore)
+			return certs, nil
+		}
+	}
+	return nil, nil
+}
+
+// addCertificates adds provided certificates to the trust store.
+func (s *trustStore) addCertificates(storeType truststore.Type, namedStore string, certs []*x509.Certificate) {
+	if s.stores[storeType] == nil {
+		s.stores[storeType] = make(map[string][]*x509.Certificate)
+	}
+	s.stores[storeType][namedStore] = append(s.stores[storeType][namedStore], certs...)
+}
diff --git a/internal/verifier/keyprovider/api.go b/internal/verifier/keyprovider/api.go
new file mode 100644
index 0000000..24a1346
--- /dev/null
+++ b/internal/verifier/keyprovider/api.go
@@ -0,0 +1,46 @@
+/*
+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 keyprovider
+
+import (
+	"context"
+	"crypto/x509"
+	"fmt"
+)
+
+// KeyProvider defines methods to fetch crypto material for signature
+// verification.
+type KeyProvider interface {
+	GetCertificates(ctx context.Context) ([]*x509.Certificate, error)
+}
+
+type keyProviderFactory func(options any) (KeyProvider, error)
+
+var keyProviderFactories = make(map[string]keyProviderFactory)
+
+// RegisterKeyProvider registers a key provider factory with the given name.
+func RegisterKeyProvider(name string, factory keyProviderFactory) {
+	keyProviderFactories[name] = factory
+}
+
+// CreateKeyProvider creates a new key provider instance.
+func CreateKeyProvider(name string, options any) (KeyProvider, error) {
+	factory, exists := keyProviderFactories[name]
+	if !exists {
+		return nil, fmt.Errorf("key provider %s not registered", name)
+	}
+	return factory(options)
+}
diff --git a/internal/verifier/keyprovider/filesystemprovider/register.go b/internal/verifier/keyprovider/filesystemprovider/register.go
new file mode 100644
index 0000000..c80f896
--- /dev/null
+++ b/internal/verifier/keyprovider/filesystemprovider/register.go
@@ -0,0 +1,128 @@
+/*
+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 filesystemprovider
+
+import (
+	"context"
+	"crypto/x509"
+	"encoding/json"
+	"fmt"
+	"io/fs"
+	"os"
+	"path/filepath"
+
+	notationx509 "github.com/notaryproject/notation-core-go/x509"
+	"github.com/ratify-project/ratify/v2/internal/verifier/keyprovider"
+	"github.com/sirupsen/logrus"
+)
+
+const fileSystemProviderName = "files"
+
+// FileSystemProvider is a key provider that loads certificates from the file
+// system.
+type FileSystemProvider struct {
+	certPaths []string
+}
+
+func init() {
+	keyprovider.RegisterKeyProvider(fileSystemProviderName, func(options any) (keyprovider.KeyProvider, error) {
+		raw, err := json.Marshal(options)
+		if err != nil {
+			return nil, fmt.Errorf("failed to marshal options: %w", err)
+		}
+		var paths []string
+		if err := json.Unmarshal(raw, &paths); err != nil {
+			return nil, fmt.Errorf("failed to unmarshal options: %w", err)
+		}
+
+		if len(paths) == 0 {
+			return nil, fmt.Errorf("no file paths provided")
+		}
+
+		return &FileSystemProvider{certPaths: paths}, nil
+	})
+}
+
+// FileSystemProvider implements GetCertificates of [truststore.X509TrustStore]
+// interface.
+func (f *FileSystemProvider) GetCertificates(_ context.Context) ([]*x509.Certificate, error) {
+	var certs []*x509.Certificate
+
+	for _, certPath := range f.certPaths {
+		certificates, err := loadCertificatesFromPath(certPath)
+		if err != nil {
+			return nil, fmt.Errorf("failed to load certificates from path %s: %w", certPath, err)
+		}
+		certs = append(certs, certificates...)
+	}
+
+	return certs, nil
+}
+
+func loadCertificatesFromPath(path string) ([]*x509.Certificate, error) {
+	logrus.Infof("Loading certificates from path: %s", path)
+	var certificates []*x509.Certificate
+	fileMap := map[string]struct{}{} //a map to track path of physical files
+
+	err := filepath.Walk(path, func(file string, info os.FileInfo, err error) error {
+		targetFileInfo := info
+		targetFilePath := file
+
+		if info == nil || err != nil {
+			logrus.Warnf("Invalid path '%v' skipped, error %v", file, err)
+			return nil
+		}
+
+		// In a cluster environment, each mounted file results in a physical file and a symlink
+		// check if file is a link and get the actual file path
+		if isSymbolicLink(info) {
+			targetFilePath, err = filepath.EvalSymlinks(file)
+			if err != nil || len(targetFilePath) == 0 {
+				logrus.Errorf("Unable to resolve symbolic link %v , error '%v'", file, err)
+				return nil
+			}
+
+			targetFileInfo, err = os.Lstat(targetFilePath)
+			if err != nil {
+				logrus.Errorf("error getting file info for path '%v', error '%v'", targetFilePath, err)
+				return nil
+			}
+		}
+
+		// if filepath.EvalSymlinks fails to resolve multi level sym link, skip this file
+		if targetFileInfo != nil && !targetFileInfo.IsDir() && !isSymbolicLink(targetFileInfo) {
+			if _, ok := fileMap[targetFilePath]; ok {
+				return nil
+			}
+			certs, err := notationx509.ReadCertificateFile(targetFilePath)
+			if err != nil {
+				return fmt.Errorf("error reading certificate file %s: %w", targetFilePath, err)
+			}
+			certificates = append(certificates, certs...)
+			fileMap[targetFilePath] = struct{}{}
+		}
+		return nil
+	})
+
+	if err != nil {
+		return nil, fmt.Errorf("error walking the path %s: %w", path, err)
+	}
+	return certificates, nil
+}
+
+func isSymbolicLink(info fs.FileInfo) bool {
+	return info.Mode()&os.ModeSymlink != 0
+}
diff --git a/internal/verifier/verifier.go b/internal/verifier/verifier.go
new file mode 100644
index 0000000..7ae6d3f
--- /dev/null
+++ b/internal/verifier/verifier.go
@@ -0,0 +1,41 @@
+/*
+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 verifier
+
+import (
+	"fmt"
+
+	"github.com/ratify-project/ratify-go"
+	"github.com/ratify-project/ratify/v2/internal/verifier/factory"
+	_ "github.com/ratify-project/ratify/v2/internal/verifier/factory/notation" // Register the Notation verifier factory
+)
+
+// NewVerifiers creates a slice of ratify.Verifier instances based on the
+// provided options.
+func NewVerifiers(opts []factory.NewVerifierOptions) ([]ratify.Verifier, error) {
+	if len(opts) == 0 {
+		return nil, fmt.Errorf("no verifier options provided")
+	}
+	verifiers := make([]ratify.Verifier, len(opts))
+	for idx, opt := range opts {
+		verifier, err := factory.NewVerifier(opt)
+		if err != nil {
+			return nil, err
+		}
+		verifiers[idx] = verifier
+	}
+	return verifiers, nil
+}
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh.go b/pkg/keymanagementprovider/refresh/kubeRefresh.go
deleted file mode 100644
index aaa1ef3..0000000
--- a/pkg/keymanagementprovider/refresh/kubeRefresh.go
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-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 refresh
-
-import (
-	"context"
-	"fmt"
-	"maps"
-	"time"
-
-	re "github.com/ratify-project/ratify/errors"
-	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
-	nv "github.com/ratify-project/ratify/v2/pkg/verifier/notation"
-	"github.com/sirupsen/logrus"
-	ctrl "sigs.k8s.io/controller-runtime"
-)
-
-type KubeRefresher struct {
-	Provider                kmp.KeyManagementProvider
-	ProviderType            string
-	ProviderRefreshInterval string
-	Resource                string
-	Result                  ctrl.Result
-	Status                  kmp.KeyManagementProviderStatus
-	CRLHandler              nv.RevocationFactory
-}
-
-// Register registers the kubeRefresher factory
-func init() {
-	Register(KubeRefresherType, &KubeRefresher{})
-}
-
-// Refresh the certificates/keys for the key management provider by calling the GetCertificates and GetKeys methods
-func (kr *KubeRefresher) Refresh(ctx context.Context) error {
-	logger := logrus.WithContext(ctx)
-
-	// fetch certificates and store in map
-	certificates, certAttributes, err := kr.Provider.GetCertificates(ctx)
-	if err != nil {
-		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail(fmt.Sprintf("Unable to fetch certificates from key management provider [%s] of type [%s]", kr.Resource, kr.ProviderType))
-		kmp.SetCertificateError(kr.Resource, err)
-		return kmpErr
-	}
-
-	// fetch CRLs and cache them
-	crlFetcher, err := kr.CRLHandler.NewFetcher()
-	if err != nil {
-		// log error and continue
-		logger.Warnf("Unable to create CRL fetcher for key management provider %s of type %s with error: %v", kr.Resource, kr.ProviderType, err)
-	}
-	for _, cert := range certificates {
-		nv.CacheCRL(ctx, cert, crlFetcher)
-	}
-	// fetch keys and store in map
-	keys, keyAttributes, err := kr.Provider.GetKeys(ctx)
-	if err != nil {
-		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail(fmt.Sprintf("Unable to fetch keys from key management provider [%s] of type [%s]", kr.Resource, kr.ProviderType))
-		kmp.SetKeyError(kr.Resource, err)
-		return kmpErr
-	}
-
-	kmp.SaveSecrets(kr.Resource, kr.ProviderType, keys, certificates)
-	// merge certificates and keys status into one
-	maps.Copy(keyAttributes, certAttributes)
-	kr.Status = keyAttributes
-
-	logger.Infof("%v certificate(s) & %v key(s) fetched for key management provider %v", len(certificates), len(keys), kr.Resource)
-
-	// Resource is not refreshable, returning empty result and no error to indicate we’ve successfully reconciled this object
-	// will not reconcile again unless resource is recreated
-	if !kr.Provider.IsRefreshable() {
-		return nil
-	}
-
-	// if interval is not set, disable refresh
-	if kr.ProviderRefreshInterval == "" {
-		return nil
-	}
-
-	// resource is refreshable, requeue after interval
-	intervalDuration, err := time.ParseDuration(kr.ProviderRefreshInterval)
-	if err != nil {
-		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail(fmt.Sprintf("Unable to parse interval duration for key management provider [%s] of type [%s]", kr.Resource, kr.ProviderType))
-		return kmpErr
-	}
-
-	logger.Info("Reconciled KeyManagementProvider", "intervalDuration", intervalDuration)
-	kr.Result = ctrl.Result{RequeueAfter: intervalDuration}
-
-	return nil
-}
-
-// GetResult returns the result of the refresh as a ctrl.Result
-func (kr *KubeRefresher) GetResult() interface{} {
-	return kr.Result
-}
-
-func (kr *KubeRefresher) GetStatus() interface{} {
-	return kr.Status
-}
-
-// Create creates a new KubeRefresher instance
-func (kr *KubeRefresher) Create(config RefresherConfig) (Refresher, error) {
-	return &KubeRefresher{
-		Provider:                config.Provider,
-		ProviderType:            config.ProviderType,
-		ProviderRefreshInterval: config.ProviderRefreshInterval,
-		Resource:                config.Resource,
-		CRLHandler:              nv.CreateCRLHandlerFromConfig(),
-	}, nil
-}
diff --git a/pkg/verifier/notation/certStores.go b/pkg/verifier/notation/certStores.go
deleted file mode 100644
index 495e26b..0000000
--- a/pkg/verifier/notation/certStores.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-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 (
-	"context"
-
-	"github.com/notaryproject/notation-go/verifier/truststore"
-)
-
-// certStores is an interface that defines the methods for managing certificate stores.
-type certStores interface {
-	// GetCertGroup returns certain type of cert group from namedStore
-	GetCertGroup(ctx context.Context, storeType truststore.Type, namedStore string) (certGroup []string)
-}
diff --git a/pkg/verifier/notation/certstoresbytype.go b/pkg/verifier/notation/certstoresbytype.go
deleted file mode 100644
index a5a9228..0000000
--- a/pkg/verifier/notation/certstoresbytype.go
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-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 (
-	"context"
-	"fmt"
-
-	"github.com/notaryproject/notation-go/verifier/truststore"
-	"github.com/ratify-project/ratify/internal/logger"
-)
-
-type certStoreType string
-
-const (
-	CA               certStoreType = "ca"
-	SigningAuthority certStoreType = "signingAuthority"
-	TSA              certStoreType = "tsa"
-)
-
-func (certstoretype certStoreType) String() string {
-	return string(certstoretype)
-}
-
-// verificationCertStores describes the configuration of verification certStores
-// type verificationCertStores supports new format map[string]map[string][]string
-//
-//	{
-//	  "ca": {
-//	    "certs": {"kv1", "kv2"},
-//	  },
-//	  "signingauthority": {
-//	    "certs": {"kv3"}
-//	  },
-//	}
-//
-// type verificationCertStores supports legacy format map[string][]string as well.
-//
-//	{
-//	  "certs": {"kv1", "kv2"},
-//	},
-type verificationCertStores map[string]interface{}
-
-// certStoresByType implements certStores interface and place certs under the trustStoreType
-//
-//	{
-//	  "ca": {
-//	    "certs": {"kv1", "kv2"},
-//	  },
-//	  "signingauthority": {
-//	    "certs": {"kv3"}
-//	  },
-//	}
-type certStoresByType map[certStoreType]map[string][]string
-
-// newCertStoreByType performs type assertion and converts certificate stores configuration into certStoresByType
-func newCertStoreByType(confInNewFormat verificationCertStores) (certStores, error) {
-	s := make(certStoresByType)
-	for certstoretype, storeData := range confInNewFormat {
-		s[certStoreType(certstoretype)] = make(map[string][]string)
-		parsedStoreData, ok := storeData.(map[string]interface{})
-		if !ok {
-			return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
-		}
-		for storeName, certProviderList := range parsedStoreData {
-			var certProviderNames []string
-			parsedCertProviders, ok := certProviderList.([]interface{})
-			if !ok {
-				return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
-			}
-			for _, certProvider := range parsedCertProviders {
-				certProviderName, ok := certProvider.(string)
-				if !ok {
-					return nil, fmt.Errorf("the verificationCertStores configuration is invalid: %+v", confInNewFormat)
-				}
-				certProviderNames = append(certProviderNames, certProviderName)
-			}
-			s[certStoreType(certstoretype)][storeName] = certProviderNames
-		}
-	}
-	return s, nil
-}
-
-// GetCertGroup returns certain type of certs from namedStore
-func (s certStoresByType) GetCertGroup(ctx context.Context, storeType truststore.Type, namedStore string) (certGroup []string) {
-	if certStores, ok := s[certStoreType(storeType)]; ok {
-		if certGroup, ok = certStores[namedStore]; ok {
-			return
-		}
-	}
-	logger.GetLogger(ctx, logOpt).Warnf("unable to fetch certGroup from namedStore: %+v in type: %v", namedStore, storeType)
-	return
-}
diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go
deleted file mode 100644
index 625a539..0000000
--- a/pkg/verifier/notation/notation.go
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
-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 (
-	"context"
-	"encoding/json"
-	"fmt"
-	paths "path/filepath"
-	"strings"
-
-	ratifyconfig "github.com/ratify-project/ratify/config"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/internal/logger"
-	"github.com/ratify-project/ratify/pkg/common"
-	"github.com/ratify-project/ratify/pkg/homedir"
-
-	"github.com/notaryproject/notation-go/log"
-	"github.com/ratify-project/ratify/pkg/ocispecs"
-	"github.com/ratify-project/ratify/pkg/referrerstore"
-	"github.com/ratify-project/ratify/pkg/verifier"
-	"github.com/ratify-project/ratify/pkg/verifier/config"
-	"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"
-	notationVerifier "github.com/notaryproject/notation-go/verifier"
-	"github.com/notaryproject/notation-go/verifier/trustpolicy"
-	"github.com/notaryproject/notation-go/verifier/truststore"
-	oci "github.com/opencontainers/image-spec/specs-go/v1"
-)
-
-const (
-	verifierType                   = "notation"
-	defaultCertPath                = "ratify-certs/notation/truststore"
-	trustStoreTypeCA               = string(truststore.TypeCA)
-	trustStoreTypeSigningAuthority = string(truststore.TypeSigningAuthority)
-	trustStoreTypeTSA              = string(truststore.TypeTSA)
-)
-
-// NotationPluginVerifierConfig describes the configuration of notation verifier
-type NotationPluginVerifierConfig struct { //nolint:revive // ignore linter to have unique type name
-	Name          string `json:"name"`
-	ArtifactTypes string `json:"artifactTypes"`
-
-	// VerificationCerts is array of directories containing certificates.
-	VerificationCerts []string `json:"verificationCerts"`
-	// VerificationCertStores defines a collection of Notary Project Trust Stores.
-	// VerificationCertStores accepts new format map[string]map[string][]string
-	// {
-	//   "ca": {
-	//     "certs": {"kv1", "kv2"},
-	//   },
-	//   "signingauthority": {
-	//     "certs": {"kv3"}
-	//   },
-	// }
-	// VerificationCertStores accepts legacy format map[string][]string as well.
-	// {
-	//   "certs": {"kv1", "kv2"},
-	// },
-	VerificationCertStores verificationCertStores `json:"verificationCertStores"`
-	// TrustPolicyDoc represents a trustpolicy.json document. Reference: https://pkg.go.dev/github.com/notaryproject/notation-go@v0.12.0-beta.1.0.20221125022016-ab113ebd2a6c/verifier/trustpolicy#Document
-	TrustPolicyDoc trustpolicy.Document `json:"trustPolicyDoc"`
-}
-
-type notationPluginVerifier struct {
-	name             string
-	verifierType     string
-	artifactTypes    []string
-	notationVerifier *notation.Verifier
-}
-
-type notationPluginVerifierFactory struct{}
-
-func init() {
-	factory.Register(verifierType, &notationPluginVerifierFactory{})
-}
-
-func (f *notationPluginVerifierFactory) Create(_ string, verifierConfig config.VerifierConfig, pluginDirectory string, namespace string) (verifier.ReferenceVerifier, error) {
-	ctx := context.Background()
-	logger.GetLogger(ctx, logOpt).Debugf("creating Notation verifier with config %v, namespace '%v'", verifierConfig, namespace)
-	verifierName := fmt.Sprintf("%s", verifierConfig[types.Name])
-	verifierTypeStr := ""
-	if _, ok := verifierConfig[types.Type]; ok {
-		verifierTypeStr = fmt.Sprintf("%s", verifierConfig[types.Type])
-	}
-	conf, err := parseVerifierConfig(verifierConfig, namespace)
-	if err != nil {
-		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
-	}
-	verifyService, err := getVerifierService(ctx, conf, pluginDirectory, CreateCRLHandlerFromConfig())
-	if err != nil {
-		return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Notation Verifier").WithError(err)
-	}
-
-	artifactTypes := strings.Split(conf.ArtifactTypes, ",")
-	return &notationPluginVerifier{
-		name:             verifierName,
-		verifierType:     verifierTypeStr,
-		artifactTypes:    artifactTypes,
-		notationVerifier: &verifyService,
-	}, nil
-}
-
-func (v *notationPluginVerifier) Name() string {
-	return v.name
-}
-
-func (v *notationPluginVerifier) Type() string {
-	return v.verifierType
-}
-
-func (v *notationPluginVerifier) CanVerify(_ context.Context, referenceDescriptor ocispecs.ReferenceDescriptor) bool {
-	for _, at := range v.artifactTypes {
-		if at == "*" || at == referenceDescriptor.ArtifactType {
-			return true
-		}
-	}
-	return false
-}
-
-func (v *notationPluginVerifier) Verify(ctx context.Context,
-	subjectReference common.Reference,
-	referenceDescriptor ocispecs.ReferenceDescriptor,
-	store referrerstore.ReferrerStore) (verifier.VerifierResult, error) {
-	extensions := make(map[string]string)
-
-	subjectDesc, err := store.GetSubjectDescriptor(ctx, subjectReference)
-	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature of the artifact: %+v", subjectReference)).WithError(err)
-	}
-
-	referenceManifest, err := store.GetReferenceManifest(ctx, subjectReference, referenceDescriptor)
-	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature: %+v", referenceDescriptor)).WithError(err)
-	}
-
-	if len(referenceManifest.Blobs) != 1 {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Notation signature manifest requires exactly one signature envelope blob, got %d", len(referenceManifest.Blobs))).WithRemediation(fmt.Sprintf("Please inspect the artifact [%s@%s] is correctly signed by Notation signer", subjectReference.Path, referenceDescriptor.Digest.String()))
-	}
-	blobDesc := referenceManifest.Blobs[0]
-	refBlob, err := store.GetBlobContent(ctx, subjectReference, blobDesc.Digest)
-	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature of the artifact: %+v", subjectReference)).WithError(err)
-	}
-
-	// TODO: notation verify API only accepts digested reference now.
-	// Pass in tagged reference instead once notation-go supports it.
-	subjectRef := fmt.Sprintf("%s@%s", subjectReference.Path, subjectReference.Digest.String())
-	outcome, err := v.verifySignature(ctx, subjectRef, blobDesc.MediaType, subjectDesc.Descriptor, refBlob)
-	if err != nil {
-		return verifier.VerifierResult{IsSuccess: false, Extensions: extensions}, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Notation signature: %+v", referenceDescriptor)).WithError(err)
-	}
-
-	// Note: notation verifier already validates certificate chain is not empty.
-	cert := outcome.EnvelopeContent.SignerInfo.CertificateChain[0]
-	extensions["Issuer"] = cert.Issuer.String()
-	extensions["SN"] = cert.Subject.String()
-
-	return verifier.NewVerifierResult("", v.name, v.verifierType, "Notation signature verification success", true, nil, extensions), nil
-}
-
-func getVerifierService(ctx context.Context, conf *NotationPluginVerifierConfig, pluginDirectory string, revocationFactory RevocationFactory) (notation.Verifier, error) {
-	store, err := newTrustStore(conf.VerificationCerts, conf.VerificationCertStores)
-	if err != nil {
-		return nil, err
-	}
-
-	// 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 {
-		logger.GetLogger(ctx, logOpt).Warnf("Unable to create CRL fetcher for notation verifier %s with error: %s", conf.Name, err)
-	}
-	revocationCodeSigningValidator, err := revocation.NewWithOptions(revocation.Options{
-		CRLFetcher:       crlFetcher,
-		CertChainPurpose: purpose.CodeSigning,
-	})
-	if err != nil {
-		return nil, err
-	}
-	revocationTimestampingValidator, err := revocation.NewWithOptions(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)
-	}
-	return verifier, nil
-}
-
-func (v *notationPluginVerifier) verifySignature(ctx context.Context, subjectRef, mediaType string, subjectDesc oci.Descriptor, refBlob []byte) (*notation.VerificationOutcome, error) {
-	opts := notation.VerifierVerifyOptions{
-		SignatureMediaType: mediaType,
-		ArtifactReference:  subjectRef,
-	}
-	ctx = log.WithLogger(ctx, logger.GetLogger(ctx, logOpt))
-
-	return (*v.notationVerifier).Verify(ctx, subjectDesc, refBlob, opts)
-}
-
-func parseVerifierConfig(verifierConfig config.VerifierConfig, _ string) (*NotationPluginVerifierConfig, error) {
-	conf := &NotationPluginVerifierConfig{}
-
-	verifierConfigBytes, err := json.Marshal(verifierConfig)
-	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to parse the Notation Verifier configuration: %+v", verifierConfig)).WithError(err)
-	}
-
-	if err := json.Unmarshal(verifierConfigBytes, &conf); err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to parse the Notation Verifier configuration: %+v", verifierConfig)).WithError(err)
-	}
-
-	defaultCertsDir := paths.Join(homedir.Get(), ratifyconfig.ConfigFileDir, defaultCertPath)
-	conf.VerificationCerts = append(conf.VerificationCerts, defaultCertsDir)
-	if len(conf.VerificationCertStores) > 0 {
-		if err := normalizeVerificationCertsStores(conf); err != nil {
-			return nil, err
-		}
-	}
-	return conf, nil
-}
-
-// signatures should not have nested references
-func (v *notationPluginVerifier) GetNestedReferences() []string {
-	return []string{}
-}
-
-// normalizeVerificationCertsStores normalize the structure does not match the latest spec
-func normalizeVerificationCertsStores(conf *NotationPluginVerifierConfig) error {
-	isCertStoresByType, isLegacyCertStore := false, false
-	for key := range conf.VerificationCertStores {
-		if key != trustStoreTypeCA && key != trustStoreTypeSigningAuthority && key != trustStoreTypeTSA {
-			isLegacyCertStore = true
-			logger.GetLogger(context.Background(), logOpt).Debugf("Get VerificationCertStores in legacy format")
-		} else {
-			isCertStoresByType = true
-		}
-	}
-	if isCertStoresByType && isLegacyCertStore {
-		// showing configuration content in the log with error details for better user experience
-		err := re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("The verificationCertStores is misconfigured with both legacy and new formats: %+v", conf)).WithRemediation("Please provide only one format for the VerificationCertStores. Refer to the Notation Verifier configuration guide: https://ratify.dev/docs/plugins/verifier/notation#configuration")
-		logger.GetLogger(context.Background(), logOpt).Error(err)
-		return err
-	} else if !isCertStoresByType && isLegacyCertStore {
-		legacyCertStore, err := normalizeLegacyCertStore(conf)
-		if err != nil {
-			return err
-		}
-		// support legacy verfier config format for backward compatibility
-		// normalize <store>:<certs> to ca:<store><certs> if no store type is provided
-		conf.VerificationCertStores = verificationCertStores{
-			trustStoreTypeCA: legacyCertStore,
-		}
-	}
-	return nil
-}
-
-// TODO: remove this function once the refactor is done [refactore tracking issue](https://github.com/ratify-project/ratify/issues/1752)
-func normalizeLegacyCertStore(conf *NotationPluginVerifierConfig) (map[string]interface{}, error) {
-	legacyCertStoreBytes, err := json.Marshal(conf.VerificationCertStores)
-	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to recognize `verificationCertStores` value of Notation Verifier configuration: %+v", conf.VerificationCertStores)).WithError(err)
-	}
-	var legacyCertStore map[string]interface{}
-	if err := json.Unmarshal(legacyCertStoreBytes, &legacyCertStore); err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to recognize `verificationCertStores` value of Notation Verifier configuration: %+v", conf.VerificationCertStores)).WithError(err)
-	}
-	return legacyCertStore, nil
-}
diff --git a/pkg/verifier/notation/notationrevocationfactory.go b/pkg/verifier/notation/notationrevocationfactory.go
deleted file mode 100644
index b1a0898..0000000
--- a/pkg/verifier/notation/notationrevocationfactory.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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"
-	"sync"
-
-	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
-	httpClient   *http.Client
-}
-
-var (
-	fetcherOnce   sync.Once
-	globalFetcher corecrl.Fetcher
-)
-
-// 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.
-// If a Fetcher instance is already present, it returns the existing instance.
-// The method also configures the cache for the Fetcher.
-// Returns an instance of corecrl.Fetcher or an error if the Fetcher creation fails.
-func (h *CRLHandler) NewFetcher() (corecrl.Fetcher, error) {
-	var err error
-	fetcherOnce.Do(func() {
-		globalFetcher, err = CreateCRLFetcher(h.httpClient, dir.PathCRLCache)
-	})
-	if err != nil {
-		return nil, err
-	}
-	// 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 globalFetcher == nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail("failed to create CRL fetcher")
-	}
-	return globalFetcher, nil
-}
diff --git a/pkg/verifier/notation/pluginmanager.go b/pkg/verifier/notation/pluginmanager.go
deleted file mode 100644
index 0ab8c4d..0000000
--- a/pkg/verifier/notation/pluginmanager.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-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 (
-	"context"
-	"io/fs"
-	"strings"
-
-	"github.com/notaryproject/notation-go/dir"
-	"github.com/notaryproject/notation-go/plugin"
-	pl "github.com/notaryproject/notation-plugin-framework-go/plugin"
-)
-
-const (
-	notationPluginPrefix   = "notation-"
-	defaultPluginDirectory = "/.ratify/plugins"
-)
-
-// Implements interface defined in https://github.com/notaryproject/notation-go/blob/main/plugin/manager.go#L20
-type RatifyPluginManager struct {
-	pluginFS dir.SysFS
-}
-
-func NewRatifyPluginManager(directory string) *RatifyPluginManager {
-	return &RatifyPluginManager{pluginFS: dir.NewSysFS(directory)}
-}
-
-// Returns a notation Plugin for the given name if present in the target directory
-func (m *RatifyPluginManager) Get(ctx context.Context, name string) (pl.Plugin, error) {
-	path, err := m.pluginFS.SysPath(notationPluginPrefix + name)
-	if err != nil {
-		return nil, err
-	}
-
-	// validate and create plugin
-	return plugin.NewCLIPlugin(ctx, name, path)
-}
-
-// Lists available notation plugins in the target directory
-func (m *RatifyPluginManager) List(_ context.Context) ([]string, error) {
-	var plugins []string
-	err := fs.WalkDir(m.pluginFS, ".", func(_ string, d fs.DirEntry, err error) error {
-		if err != nil {
-			return err
-		}
-
-		typ := d.Type()
-		if typ.IsDir() || !strings.HasPrefix(d.Name(), notationPluginPrefix) {
-			// Ignore directories and files that don't start with "notation-"
-			return nil
-		}
-
-		// add plugin name
-		name := strings.ReplaceAll(d.Name(), notationPluginPrefix, "")
-		plugins = append(plugins, name)
-		return fs.SkipDir
-	})
-
-	if err != nil {
-		return nil, err
-	}
-
-	return plugins, nil
-}
diff --git a/pkg/verifier/notation/revocationfactory.go b/pkg/verifier/notation/revocationfactory.go
deleted file mode 100644
index 0155985..0000000
--- a/pkg/verifier/notation/revocationfactory.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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 (
-	"context"
-	"crypto/x509"
-	"net/http"
-	"sync"
-
-	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"
-)
-
-// RevocationFactory is an interface that defines methods for creating instances
-// related to revocation. It provides methods to create a new fetcher and a new
-// validator.
-type RevocationFactory interface {
-	// NewFetcher returns a new fetcher instance
-	NewFetcher() (corecrl.Fetcher, error)
-}
-
-// CreateCRLFetcher returns a new fetcher instance
-func CreateCRLFetcher(httpClient *http.Client, cacheRoot string) (corecrl.Fetcher, error) {
-	crlFetcher, err := corecrl.NewHTTPFetcher(httpClient)
-	if err != nil {
-		return nil, err
-	}
-	if !config.CRLConf.Cache.Enabled {
-		return crlFetcher, nil
-	}
-	cache, err := newFileCache(cacheRoot)
-	if err != nil {
-		return nil, err
-	}
-	crlFetcher.Cache = cache
-	return crlFetcher, nil
-}
-
-// SupportCRL checks if the certificate supports CRL
-func SupportCRL(cert *x509.Certificate) bool {
-	return cert != nil && len(cert.CRLDistributionPoints) > 0
-}
-
-// cacheCRL caches the Certificate Revocation Lists (CRLs) for the given certificates using the provided CRL fetcher.
-// It logs a warning if fetching the CRL fails but does not return an error to ensure the process is not blocked.
-func CacheCRL(ctx context.Context, certs []*x509.Certificate, fetcher corecrl.Fetcher) {
-	if fetcher == nil {
-		logger.GetLogger(ctx, logOpt).Warn("CRL fetcher is nil")
-		return
-	}
-	var wg sync.WaitGroup
-	for _, cert := range certs {
-		if !SupportCRL(cert) {
-			continue
-		}
-		cacheCertificateCRL(ctx, cert.CRLDistributionPoints, fetcher, &wg)
-	}
-	wg.Wait()
-}
-
-func cacheCertificateCRL(ctx context.Context, crlURLs []string, crlFetcher corecrl.Fetcher, wg *sync.WaitGroup) {
-	for _, crlURL := range crlURLs {
-		crlURL := crlURL // capture loop variable
-		wg.Add(1)
-		go fetchCRL(ctx, crlURL, crlFetcher, wg)
-	}
-}
-
-func fetchCRL(ctx context.Context, url string, crlFetcher corecrl.Fetcher, wg *sync.WaitGroup) {
-	defer wg.Done()
-	if _, err := crlFetcher.Fetch(ctx, url); err != nil {
-		logger.GetLogger(ctx, logOpt).Errorf("failed to download CRL from %s : %v", url, err)
-	}
-}
-
-// 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/truststore.go b/pkg/verifier/notation/truststore.go
deleted file mode 100644
index af9bb33..0000000
--- a/pkg/verifier/notation/truststore.go
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-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 (
-	"context"
-	"crypto/x509"
-	"errors"
-	"fmt"
-
-	"github.com/notaryproject/notation-go/verifier/truststore"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/internal/logger"
-	"github.com/ratify-project/ratify/pkg/controllers"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
-	"github.com/ratify-project/ratify/pkg/utils"
-)
-
-var logOpt = logger.Option{
-	ComponentType: logger.Verifier,
-}
-
-type trustStore struct {
-	certPaths  []string
-	certStores certStores
-}
-
-func newTrustStore(certPaths []string, verificationCertStores verificationCertStores) (*trustStore, error) {
-	certStores, err := newCertStoreByType(verificationCertStores)
-	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create the trust store from the verificationCertStores parameter in Notation Verifier configuration: %+v", verificationCertStores)).WithError(err).WithRemediation("Please check the value of the verificationCertStores parameter according to the Notation Verifier configuration guide: https://ratify.dev/docs/plugins/verifier/notation#configuration")
-	}
-	store := &trustStore{
-		certPaths:  certPaths,
-		certStores: certStores,
-	}
-	return store, nil
-}
-
-// trustStore implements GetCertificates API of X509TrustStore interface: [https://pkg.go.dev/github.com/notaryproject/notation-go@v1.0.0-rc.3/verifier/truststore#X509TrustStore]
-// Note: this api gets invoked when Ratify calls verify API, so the certificates
-// will be loaded for each signature verification.
-// And this API must follow the Notation Trust Store spec: https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md#trust-store
-func (s *trustStore) GetCertificates(ctx context.Context, trustStoreType truststore.Type, namedStore string) ([]*x509.Certificate, error) {
-	certs, err := s.getCertificatesInternal(ctx, trustStoreType, namedStore)
-	if err != nil {
-		return nil, err
-	}
-	return s.filterValidCerts(certs)
-}
-
-func (s *trustStore) getCertificatesInternal(ctx context.Context, storeType truststore.Type, namedStore string) ([]*x509.Certificate, error) {
-	certs := make([]*x509.Certificate, 0)
-
-	certGroup := s.certStores.GetCertGroup(ctx, storeType, namedStore)
-	// certs configured for this namedStore overrides cert path
-	if len(certGroup) > 0 {
-		for _, certStore := range certGroup {
-			logger.GetLogger(ctx, logOpt).Debugf("truststore getting certStore %v", certStore)
-			certMap, kmpErr := keymanagementprovider.GetCertificatesFromMap(ctx, certStore)
-			if kmpErr != nil {
-				logger.GetLogger(ctx, logOpt).Infof("unable to fetch certificates for Key Management Provider %+v: %v", certStore, kmpErr)
-			}
-			result := keymanagementprovider.FlattenKMPMap(certMap)
-			var certStoreErr error
-			// notation verifier does not consider specific named/versioned certificates within a key management provider resource
-			if len(result) == 0 {
-				logger.GetLogger(ctx, logOpt).Infof("no certificate fetched for Key Management Provider %+v", certStore)
-				// check certificate store if key management provider does not have certificates.
-				// NOTE: certificate store and key management provider should not be configured together.
-				// User will be warned by the controller/CLI
-				if result, certStoreErr = controllers.NamespacedCertStores.GetCertsFromStore(ctx, certStore); certStoreErr != nil {
-					logger.GetLogger(ctx, logOpt).Warnf("unable to fetch certificates for Certificate Store %+v: %v", certStore, certStoreErr)
-				}
-				if len(result) == 0 {
-					logger.GetLogger(ctx, logOpt).Warnf("no certificate fetched for Certificate Store %+v", certStore)
-				} else {
-					logger.GetLogger(ctx, logOpt).Info("Certificate Store has been deprecated since v1.2.0, please migrate to Key Management Provider following: https://ratify.dev/docs/reference/custom%20resources/key-management-providers#migrating-from-certificatestore-to-kmp")
-				}
-			}
-			if err := parseErrFromKmpAndCertStore(kmpErr, certStoreErr); err != nil {
-				return []*x509.Certificate{}, re.ErrorCodeCertInvalid.WithError(err).WithDetail(fmt.Sprintf("unable to fetch certificates from Key Management Provider and Certificate Store: %s", certStore))
-			}
-			certs = append(certs, result...)
-		}
-		if len(certs) == 0 {
-			return certs, fmt.Errorf("no certificates fetched in namedStore: %+v", namedStore)
-		}
-	} else {
-		for _, path := range s.certPaths {
-			bundledCerts, err := utils.GetCertificatesFromPath(path)
-			if err != nil {
-				return nil, err
-			}
-			certs = append(certs, bundledCerts...)
-		}
-	}
-	logger.GetLogger(ctx, logOpt).Debugf("Trust store getCertificatesInternal , %v certs retrieved", len(certs))
-	return certs, nil
-}
-
-// filterValidCerts keeps CA certificates and self-signed certs.
-func (s *trustStore) filterValidCerts(certs []*x509.Certificate) ([]*x509.Certificate, error) {
-	filteredCerts := make([]*x509.Certificate, 0)
-	for _, cert := range certs {
-		if !cert.IsCA {
-			// check if it's a self-signed certificate.
-			if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
-				continue
-			}
-		}
-		filteredCerts = append(filteredCerts, cert)
-	}
-	if len(filteredCerts) == 0 {
-		return nil, errors.New("valid certificates must be provided, only CA certificates or self-signed signing certificates are supported")
-	}
-	return filteredCerts, nil
-}
-
-// parseErrFromKmpAndCertStore prioritizes and returns the appropriate error from either KMP or CertStore.
-// If the certStoreErr is a reconcile error while kmpErr is not, it returns certStoreErr,
-// otherwise it returns kmpErr.
-// A reconcile error occurs during CR reconciliation, indicating that the resource
-// was applied by users.
-// Since key management provider and certificate store are mutually exclusive,
-// a reconcile error will only originate from one of them.
-// Consequently, the reconcile error from one resource takes precedence over
-// errors from the other.
-// Note: this method should be deleted once certificate store is completely removed.
-func parseErrFromKmpAndCertStore(kmpErr, certStoreErr error) error {
-	if kmpErr == nil || certStoreErr == nil {
-		return nil
-	}
-	if isReconcileError(certStoreErr) && !isReconcileError(kmpErr) {
-		return certStoreErr
-	}
-	return kmpErr
-}
-
-// isReconcileError checks if the error is a reconcile error.
-// If the error is not NotFound or Forbidden, it is considered as an error from KMP/CertStore reconciliation.
-func isReconcileError(err error) bool {
-	ratifyErr := &re.Error{}
-	if errors.As(err, ratifyErr) {
-		return ratifyErr.ErrorCode() != re.ErrorCodeNotFound && ratifyErr.ErrorCode() != re.ErrorCodeForbidden
-	}
-	return true
-}


Test patch:
diff --git a/internal/verifier/factory/factory_test.go b/internal/verifier/factory/factory_test.go
new file mode 100644
index 0000000..f5a5ced
--- /dev/null
+++ b/internal/verifier/factory/factory_test.go
@@ -0,0 +1,105 @@
+/*
+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 factory
+
+import (
+	"testing"
+
+	"github.com/ratify-project/ratify-go"
+)
+
+const (
+	testType = "test-type"
+	testName = "test-name"
+)
+
+func createVerifier(_ NewVerifierOptions) (ratify.Verifier, error) {
+	return nil, nil
+}
+func TestRegisterVerifierFactory(t *testing.T) {
+	t.Run("Registering an empty type", func(t *testing.T) {
+		defer func() {
+			if r := recover(); r == nil {
+				t.Errorf("Expected panic when registering an empty type, but did not panic")
+			}
+		}()
+		RegisterVerifierFactory("", createVerifier)
+	})
+
+	t.Run("Registering a nil factory function", func(t *testing.T) {
+		defer func() {
+			if r := recover(); r == nil {
+				t.Errorf("Expected panic when registering a nil factory function, but did not panic")
+			}
+		}()
+		RegisterVerifierFactory(testType, nil)
+	})
+
+	t.Run("Registering a valid factory function", func(t *testing.T) {
+		defer func() {
+			if r := recover(); r != nil {
+				t.Errorf("Did not expect panic when registering a valid factory function, but got: %v", r)
+			}
+			delete(registeredVerifiers, "test-type")
+		}()
+		RegisterVerifierFactory(testType, createVerifier)
+	})
+
+	t.Run("Registering a duplicate type", func(t *testing.T) {
+		defer func() {
+			if r := recover(); r == nil {
+				t.Errorf("Expected panic when registering a duplicate type, but did not panic")
+			}
+			delete(registeredVerifiers, testType)
+		}()
+		RegisterVerifierFactory(testType, createVerifier)
+		RegisterVerifierFactory(testType, createVerifier)
+	})
+}
+
+func TestNewVerifier(t *testing.T) {
+	t.Run("Creating a verifier with empty name or type", func(t *testing.T) {
+		_, err := NewVerifier(NewVerifierOptions{Name: "", Type: testType})
+		if err == nil {
+			t.Errorf("Expected error when creating a verifier with empty name, but got none")
+		}
+
+		_, err = NewVerifier(NewVerifierOptions{Name: testName, Type: ""})
+		if err == nil {
+			t.Errorf("Expected error when creating a verifier with empty type, but got none")
+		}
+	})
+
+	t.Run("Creating a verifier with unregistered type", func(t *testing.T) {
+		_, err := NewVerifier(NewVerifierOptions{Name: testName, Type: "unregistered-type"})
+		if err == nil {
+			t.Errorf("Expected error when creating a verifier with unregistered type, but got none")
+		}
+	})
+
+	t.Run("Creating a verifier with registered type", func(t *testing.T) {
+		RegisterVerifierFactory(testType, createVerifier)
+		defer func() {
+			delete(registeredVerifiers, testType)
+		}()
+
+		opts := NewVerifierOptions{Name: testName, Type: testType}
+		_, err := NewVerifier(opts)
+		if err != nil {
+			t.Errorf("Did not expect error when creating a verifier with registered type, but got: %v", err)
+		}
+	})
+}
diff --git a/internal/verifier/factory/notation/register_test.go b/internal/verifier/factory/notation/register_test.go
new file mode 100644
index 0000000..f6a632d
--- /dev/null
+++ b/internal/verifier/factory/notation/register_test.go
@@ -0,0 +1,193 @@
+/*
+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 (
+	"context"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"fmt"
+	"testing"
+
+	"github.com/ratify-project/ratify/v2/internal/verifier/factory"
+	"github.com/ratify-project/ratify/v2/internal/verifier/keyprovider"
+)
+
+const testName = "notation-test"
+const mockKeyProviderName = "mock-key-provider"
+
+type mockKeyProvider struct {
+	returnErr bool
+}
+
+func (m *mockKeyProvider) GetCertificates(_ context.Context) ([]*x509.Certificate, error) {
+	if m.returnErr {
+		return nil, fmt.Errorf("mock error")
+	}
+	return []*x509.Certificate{
+		{
+			Subject: pkix.Name{
+				CommonName: "test-cert",
+			},
+		}}, nil
+}
+
+func createMockKeyProvider(options any) (keyprovider.KeyProvider, error) {
+	if options == nil {
+		return &mockKeyProvider{}, nil
+	}
+	val, ok := options.(map[string]any)
+	if !ok {
+		return nil, fmt.Errorf("invalid options type")
+	}
+	_, ok = val["returnErr"]
+	return &mockKeyProvider{
+		returnErr: ok,
+	}, nil
+}
+
+func TestNewVerifier(t *testing.T) {
+	// Register the mock key provider
+	keyprovider.RegisterKeyProvider(mockKeyProviderName, createMockKeyProvider)
+
+	tests := []struct {
+		name      string
+		opts      factory.NewVerifierOptions
+		expectErr bool
+	}{
+		{
+			name: "Unsupported params",
+			opts: factory.NewVerifierOptions{
+				Type:       notationType,
+				Name:       testName,
+				Parameters: make(chan int),
+			},
+			expectErr: true,
+		},
+		{
+			name: "Malformed params",
+			opts: factory.NewVerifierOptions{
+				Type:       notationType,
+				Name:       testName,
+				Parameters: "{",
+			},
+			expectErr: true,
+		},
+		{
+			name: "Missing trust store options",
+			opts: factory.NewVerifierOptions{
+				Type:       notationType,
+				Name:       testName,
+				Parameters: options{},
+			},
+			expectErr: true,
+		},
+		{
+			name: "Invalid trust store type",
+			opts: factory.NewVerifierOptions{
+				Type: notationType,
+				Name: testName,
+				Parameters: options{
+					Certificates: []trustStoreOptions{
+						{
+							"type": "invalid",
+						},
+					},
+				},
+			},
+			expectErr: true,
+		},
+		{
+			name: "Duplicate trust store type",
+			opts: factory.NewVerifierOptions{
+				Type: notationType,
+				Name: testName,
+				Parameters: options{
+					Certificates: []trustStoreOptions{
+						{
+							"type":              "ca",
+							mockKeyProviderName: nil,
+						},
+						{
+							"type":              "ca",
+							mockKeyProviderName: nil,
+						},
+					},
+				},
+			},
+			expectErr: true,
+		},
+		{
+			name: "Non-registered key provider",
+			opts: factory.NewVerifierOptions{
+				Type: notationType,
+				Name: testName,
+				Parameters: options{
+					Certificates: []trustStoreOptions{
+						{
+							"type":           "ca",
+							"non-registered": nil,
+						},
+					},
+				},
+			},
+			expectErr: true,
+		},
+		{
+			name: "Failed to get certificates from key provider",
+			opts: factory.NewVerifierOptions{
+				Type: notationType,
+				Name: testName,
+				Parameters: options{
+					Certificates: []trustStoreOptions{
+						{
+							"type": "ca",
+							mockKeyProviderName: map[string]any{
+								"returnErr": true,
+							},
+						},
+					},
+				},
+			},
+			expectErr: true,
+		},
+		{
+			name: "Valid notation options",
+			opts: factory.NewVerifierOptions{
+				Type: notationType,
+				Name: testName,
+				Parameters: options{
+					Certificates: []trustStoreOptions{
+						{
+							"type":              "ca",
+							mockKeyProviderName: nil,
+						},
+					},
+				},
+			},
+			expectErr: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			_, err := factory.NewVerifier(test.opts)
+			if test.expectErr != (err != nil) {
+				t.Fatalf("Expected error: %v, got: %v", test.expectErr, err)
+			}
+		})
+	}
+}
diff --git a/internal/verifier/factory/notation/truststore_test.go b/internal/verifier/factory/notation/truststore_test.go
new file mode 100644
index 0000000..7a6a897
--- /dev/null
+++ b/internal/verifier/factory/notation/truststore_test.go
@@ -0,0 +1,55 @@
+/*
+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 (
+	"context"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"testing"
+
+	"github.com/notaryproject/notation-go/verifier/truststore"
+)
+
+const (
+	storeName1 = "store1"
+	storeName2 = "store2"
+)
+
+func TestTrustStore(t *testing.T) {
+	trustStore := newTrustStore()
+
+	cert1 := &x509.Certificate{Subject: pkix.Name{CommonName: "cert1"}}
+	cert2 := &x509.Certificate{Subject: pkix.Name{CommonName: "cert2"}}
+
+	trustStore.addCertificates(truststore.TypeCA, storeName1, []*x509.Certificate{cert1, cert2})
+
+	certs, err := trustStore.GetCertificates(context.Background(), truststore.TypeCA, storeName1)
+	if err != nil {
+		t.Fatalf("failed to get certificates: %v", err)
+	}
+	if len(certs) != 2 {
+		t.Fatalf("expected 2 certificates, got %d", len(certs))
+	}
+
+	certs, err = trustStore.GetCertificates(context.Background(), truststore.TypeCA, storeName2)
+	if err != nil {
+		t.Fatalf("failed to get certificates: %v", err)
+	}
+	if certs != nil {
+		t.Fatalf("expected no certificates, got %d", len(certs))
+	}
+}
diff --git a/internal/verifier/keyprovider/api_test.go b/internal/verifier/keyprovider/api_test.go
new file mode 100644
index 0000000..60eb910
--- /dev/null
+++ b/internal/verifier/keyprovider/api_test.go
@@ -0,0 +1,48 @@
+/*
+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 keyprovider
+
+import (
+	"context"
+	"crypto/x509"
+	"testing"
+)
+
+const mockProvider = "mock-provider"
+
+type mockKeyProvider struct{}
+
+func (m *mockKeyProvider) GetCertificates(_ context.Context) ([]*x509.Certificate, error) {
+	return nil, nil
+}
+
+func TestCreateKeyProvider(t *testing.T) {
+	RegisterKeyProvider(mockProvider, func(_ any) (KeyProvider, error) {
+		return &mockKeyProvider{}, nil
+	})
+
+	provider, err := CreateKeyProvider(mockProvider, nil)
+	if err != nil {
+		t.Fatalf("expected no error, got %v", err)
+	}
+	if provider == nil {
+		t.Fatal("expected non-nil key provider")
+	}
+
+	if _, err = CreateKeyProvider("unknown-provider", nil); err == nil {
+		t.Fatal("expected error, got nil")
+	}
+}
diff --git a/internal/verifier/keyprovider/filesystemprovider/register_test.go b/internal/verifier/keyprovider/filesystemprovider/register_test.go
new file mode 100644
index 0000000..06e9bdf
--- /dev/null
+++ b/internal/verifier/keyprovider/filesystemprovider/register_test.go
@@ -0,0 +1,144 @@
+/*
+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 filesystemprovider
+
+import (
+	"context"
+	"crypto/rand"
+	"crypto/rsa"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"math/big"
+	"os"
+	"path/filepath"
+	"testing"
+	"time"
+
+	"github.com/ratify-project/ratify/v2/internal/verifier/keyprovider"
+)
+
+const (
+	symDataPath  = "..data"
+	realDataPath = "..real-data"
+	certFileName = "cert.pem"
+)
+
+func TestInit(t *testing.T) {
+	if _, err := keyprovider.CreateKeyProvider(fileSystemProviderName, make(chan int)); err == nil {
+		t.Fatalf("expected error, got nil")
+	}
+
+	if _, err := keyprovider.CreateKeyProvider(fileSystemProviderName, "{"); err == nil {
+		t.Fatalf("expected error, got nil")
+	}
+
+	if _, err := keyprovider.CreateKeyProvider(fileSystemProviderName, []string{}); err == nil {
+		t.Fatalf("expected error, got nil")
+	}
+}
+
+func TestGetCertificates(t *testing.T) {
+	tempDir := t.TempDir()
+
+	if err := os.Mkdir(filepath.Join(tempDir, realDataPath), 0755); err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	if err := os.Symlink(filepath.Join(tempDir, realDataPath), filepath.Join(tempDir, symDataPath)); err != nil {
+		t.Fatalf("failed to create symlink: %v", err)
+	}
+
+	// Create a temporary certificate file.
+	certFile := filepath.Join(tempDir, realDataPath, certFileName)
+	certContent, err := createCert()
+	if err != nil {
+		t.Fatalf("failed to create certificate: %v", err)
+	}
+	if err := os.WriteFile(certFile, certContent, 0600); err != nil {
+		t.Fatalf("failed to create temp cert file: %v", err)
+	}
+
+	// Create a symlink to the certificate file.
+	certFileSymLink := filepath.Join(tempDir, certFileName)
+	if err := os.Symlink(certFile, certFileSymLink); err != nil {
+		t.Fatalf("failed to create symlink for cert file: %v", err)
+	}
+
+	// Successfully create a key provider with the symlinked directory.
+	opts := []string{tempDir}
+	provider, err := keyprovider.CreateKeyProvider(fileSystemProviderName, opts)
+	if err != nil {
+		t.Fatalf("failed to create key provider: %v", err)
+	}
+	certs, err := provider.GetCertificates(context.Background())
+	if err != nil {
+		t.Fatalf("failed to get certificates: %v", err)
+	}
+	if len(certs) != 1 {
+		t.Fatalf("expected at least one certificate, got %d", len(certs))
+	}
+
+	// Create a broken symlink.
+	brokenSymlink := filepath.Join(tempDir, "broken-symlink")
+	if err := os.Symlink("nonexistent-file", brokenSymlink); err != nil {
+		t.Fatalf("failed to create broken symlink: %v", err)
+	}
+	certs, err = provider.GetCertificates(context.Background())
+	if err != nil {
+		t.Fatalf("failed to get certificates: %v", err)
+	}
+	if len(certs) != 1 {
+		t.Fatalf("expected at least one certificate, got %d", len(certs))
+	}
+
+	// Loading an invalid certificate.
+	invalidCertFile := filepath.Join(tempDir, realDataPath, "invalid-cert.pem")
+	if err := os.WriteFile(invalidCertFile, []byte("invalid cert content"), 0600); err != nil {
+		t.Fatalf("failed to create invalid cert file: %v", err)
+	}
+	if _, err = provider.GetCertificates(context.Background()); err == nil {
+		t.Fatalf("expected error while loading invalid certificate, got nil")
+	}
+}
+
+func createCert() ([]byte, error) {
+	// Generate a private key first (needed for signing)
+	priv, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		return nil, err
+	}
+
+	// Create a certificate template
+	certTemplate := x509.Certificate{
+		SerialNumber: big.NewInt(1),
+		Subject: pkix.Name{
+			Organization:  []string{"My Company, Inc."},
+			Country:       []string{"US"},
+			Province:      []string{"California"},
+			Locality:      []string{"San Francisco"},
+			StreetAddress: []string{"Market Street"},
+			PostalCode:    []string{"94103"},
+			CommonName:    "example.com",
+		},
+		NotBefore:             time.Now(),
+		NotAfter:              time.Now().Add(1 * time.Hour),
+		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	// Self-sign the certificate (for demonstration)
+	return x509.CreateCertificate(rand.Reader, &certTemplate, &certTemplate, &priv.PublicKey, priv)
+}
diff --git a/internal/verifier/verifier_test.go b/internal/verifier/verifier_test.go
new file mode 100644
index 0000000..7c26198
--- /dev/null
+++ b/internal/verifier/verifier_test.go
@@ -0,0 +1,107 @@
+/*
+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 verifier
+
+import (
+	"context"
+	"testing"
+
+	"github.com/ratify-project/ratify-go"
+	"github.com/ratify-project/ratify/v2/internal/verifier/factory"
+	"github.com/stretchr/testify/assert"
+
+	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
+)
+
+const (
+	mockName = "mock-name"
+	mockType = "mock-type"
+)
+
+type mockVerifier struct{}
+
+func (m *mockVerifier) Name() string {
+	return mockName
+}
+func (m *mockVerifier) Type() string {
+	return mockType
+}
+func (m *mockVerifier) Verifiable(_ ocispec.Descriptor) bool {
+	return true
+}
+
+func (m *mockVerifier) Verify(_ context.Context, _ *ratify.VerifyOptions) (*ratify.VerificationResult, error) {
+	return &ratify.VerificationResult{}, nil
+}
+
+func createMockVerifier(_ factory.NewVerifierOptions) (ratify.Verifier, error) {
+	return &mockVerifier{}, nil
+}
+
+func TestNewVerifiers(t *testing.T) {
+	factory.RegisterVerifierFactory("mock-type", createMockVerifier)
+	tests := []struct {
+		name          string
+		opts          []factory.NewVerifierOptions
+		expectErr     bool
+		expectedCount int
+	}{
+		{
+			name:          "no options provided",
+			opts:          []factory.NewVerifierOptions{},
+			expectErr:     true,
+			expectedCount: 0,
+		},
+		{
+			name: "error during NewVerifier",
+			opts: []factory.NewVerifierOptions{
+				{
+					Name:       "notation-1",
+					Type:       "notation",
+					Parameters: map[string]interface{}{},
+				},
+			},
+			expectErr: true,
+		},
+		{
+			name: "single valid option",
+			opts: []factory.NewVerifierOptions{
+				{
+					Name: mockName,
+					Type: mockType,
+				},
+			},
+			expectErr:     false,
+			expectedCount: 1,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			verifiers, err := NewVerifiers(tt.opts)
+			if tt.expectErr {
+				assert.Error(t, err)
+				assert.Nil(t, verifiers)
+			} else {
+				assert.NoError(t, err)
+				assert.Len(t, verifiers, tt.expectedCount)
+				for _, verifier := range verifiers {
+					assert.Implements(t, (*ratify.Verifier)(nil), verifier)
+				}
+			}
+		})
+	}
+}
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go b/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
deleted file mode 100644
index fdad5f3..0000000
--- a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
-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 refresh
-
-import (
-	"context"
-	"crypto"
-	"crypto/x509"
-	"errors"
-	"net/http"
-	"reflect"
-	"testing"
-	"time"
-
-	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider/config"
-	_ "github.com/ratify-project/ratify/pkg/keymanagementprovider/inline"
-	mock "github.com/ratify-project/ratify/v2/pkg/keymanagementprovider/mocks"
-	nv "github.com/ratify-project/ratify/v2/pkg/verifier/notation"
-	ctrl "sigs.k8s.io/controller-runtime"
-)
-
-func TestKubeRefresher_Refresh(t *testing.T) {
-	tests := []struct {
-		name                    string
-		providerRawParameters   []byte
-		providerType            string
-		providerRefreshInterval string
-		GetCertsFunc            func(_ context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error)
-		GetKeysFunc             func(_ context.Context) (map[keymanagementprovider.KMPMapKey]crypto.PublicKey, keymanagementprovider.KeyManagementProviderStatus, error)
-		IsRefreshableFunc       func() bool
-		NewCRLHandler           nv.RevocationFactory
-		expectedResult          ctrl.Result
-		expectedError           bool
-	}{
-		{
-			name:                  "Non-refreshable",
-			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.CreateCRLHandlerFromConfig(),
-			expectedResult:        ctrl.Result{},
-			expectedError:         false,
-		},
-		{
-			name:                    "Disabled",
-			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-			providerType:            "test-kmp",
-			providerRefreshInterval: "",
-			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
-			IsRefreshableFunc:       func() bool { return true },
-			expectedResult:          ctrl.Result{},
-			expectedError:           false,
-		},
-		{
-			name:                    "Refreshable",
-			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-			providerType:            "test-kmp",
-			providerRefreshInterval: "1m",
-			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
-			IsRefreshableFunc:       func() bool { return true },
-			expectedResult:          ctrl.Result{RequeueAfter: time.Minute},
-			expectedError:           false,
-		},
-		{
-			name:                    "Invalid Interval",
-			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-			providerType:            "test-kmp",
-			providerRefreshInterval: "1mm",
-			NewCRLHandler:           nv.CreateCRLHandlerFromConfig(),
-			IsRefreshableFunc:       func() bool { return true },
-			expectedResult:          ctrl.Result{},
-			expectedError:           true,
-		},
-		{
-			name: "Error Fetching Certificates",
-			GetCertsFunc: func(_ context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error) {
-				// Example behavior: Return an error
-				return nil, nil, errors.New("test error")
-			},
-			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.CreateCRLHandlerFromConfig(),
-			expectedError:         true,
-		},
-		{
-			name: "Error Fetching Keys",
-			GetKeysFunc: func(_ context.Context) (map[keymanagementprovider.KMPMapKey]crypto.PublicKey, keymanagementprovider.KeyManagementProviderStatus, error) {
-				// Example behavior: Return an error
-				return nil, nil, errors.New("test error")
-			},
-			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.CreateCRLHandlerFromConfig(),
-			expectedError:         true,
-		},
-		{
-			name: "Error Caching with CRL Fetcher (non-blocking)",
-			GetCertsFunc: func(_ context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error) {
-				return map[keymanagementprovider.KMPMapKey][]*x509.Certificate{
-					{Name: "sample"}: {&x509.Certificate{}},
-				}, keymanagementprovider.KeyManagementProviderStatus{}, nil
-			},
-			providerRawParameters:   []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-			providerType:            "test-kmp",
-			providerRefreshInterval: "1m",
-			IsRefreshableFunc:       func() bool { return true },
-			NewCRLHandler:           &MockCRLHandler{CacheDisabled: false, httpClient: &http.Client{}},
-			expectedResult:          ctrl.Result{RequeueAfter: time.Minute},
-			expectedError:           false,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			var factory mock.TestKeyManagementProviderFactory
-			if tt.GetCertsFunc != nil {
-				factory = mock.TestKeyManagementProviderFactory{
-					GetCertsFunc:      tt.GetCertsFunc,
-					IsRefreshableFunc: tt.IsRefreshableFunc,
-				}
-			} else if tt.GetKeysFunc != nil {
-				factory = mock.TestKeyManagementProviderFactory{
-					GetKeysFunc:       tt.GetKeysFunc,
-					IsRefreshableFunc: tt.IsRefreshableFunc,
-				}
-			} else {
-				factory = mock.TestKeyManagementProviderFactory{
-					IsRefreshableFunc: tt.IsRefreshableFunc,
-				}
-			}
-
-			provider, _ := factory.Create("", config.KeyManagementProviderConfig{}, "")
-
-			kr := &KubeRefresher{
-				Provider:                provider,
-				ProviderType:            tt.providerType,
-				ProviderRefreshInterval: tt.providerRefreshInterval,
-				Resource:                "kmpname",
-				CRLHandler:              tt.NewCRLHandler,
-			}
-
-			err := kr.Refresh(context.Background())
-			result := kr.GetResult()
-			if !reflect.DeepEqual(result, tt.expectedResult) {
-				t.Fatalf("Expected nil but got %v with error %v", result, err)
-			}
-			if tt.expectedError && err == nil {
-				t.Fatalf("Expected error but got nil")
-			}
-		})
-	}
-}
-
-type MockCRLHandler struct {
-	CacheDisabled bool
-	httpClient    *http.Client
-}
-
-func (h *MockCRLHandler) NewFetcher() (corecrl.Fetcher, error) {
-	return nil, re.ErrorCodeConfigInvalid.WithDetail("failed to create CRL fetcher")
-}
-
-func TestKubeRefresher_GetResult(t *testing.T) {
-	kr := &KubeRefresher{
-		Result:     ctrl.Result{RequeueAfter: time.Minute},
-		CRLHandler: nv.CreateCRLHandlerFromConfig(),
-	}
-
-	result := kr.GetResult()
-	expectedResult := ctrl.Result{RequeueAfter: time.Minute}
-
-	if !reflect.DeepEqual(result, expectedResult) {
-		t.Fatalf("Expected result %v, but got %v", expectedResult, result)
-	}
-}
-func TestKubeRefresher_GetStatus(t *testing.T) {
-	kr := &KubeRefresher{
-		Status: keymanagementprovider.KeyManagementProviderStatus{
-			"attribute1": "value1",
-			"attribute2": "value2",
-		},
-		CRLHandler: nv.CreateCRLHandlerFromConfig(),
-	}
-
-	status := kr.GetStatus()
-	expectedStatus := keymanagementprovider.KeyManagementProviderStatus{
-		"attribute1": "value1",
-		"attribute2": "value2",
-	}
-
-	if !reflect.DeepEqual(status, expectedStatus) {
-		t.Fatalf("Expected status %v, but got %v", expectedStatus, status)
-	}
-}
-func TestKubeRefresher_Create(t *testing.T) {
-	tests := []struct {
-		name                    string
-		config                  RefresherConfig
-		expectedProviderType    string
-		expectedRefreshInterval string
-		expectedResource        string
-	}{
-		{
-			name: "Valid Config",
-			config: RefresherConfig{
-				Provider:                &mock.TestKeyManagementProvider{},
-				ProviderType:            "test-kmp",
-				ProviderRefreshInterval: "1m",
-				Resource:                "test-resource",
-			},
-			expectedProviderType:    "test-kmp",
-			expectedRefreshInterval: "1m",
-			expectedResource:        "test-resource",
-		},
-		{
-			name: "Empty Config",
-			config: RefresherConfig{
-				Provider:                nil,
-				ProviderType:            "",
-				ProviderRefreshInterval: "",
-				Resource:                "",
-			},
-			expectedProviderType:    "",
-			expectedRefreshInterval: "",
-			expectedResource:        "",
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			kr := &KubeRefresher{CRLHandler: nv.CreateCRLHandlerFromConfig()}
-			refresher, err := kr.Create(tt.config)
-			if err != nil {
-				t.Fatalf("Expected no error, but got %v", err)
-			}
-
-			kubeRefresher, ok := refresher.(*KubeRefresher)
-			if !ok {
-				t.Fatalf("Expected KubeRefresher type, but got %T", refresher)
-			}
-
-			if kubeRefresher.ProviderType != tt.expectedProviderType {
-				t.Fatalf("Expected ProviderType %v, but got %v", tt.expectedProviderType, kubeRefresher.ProviderType)
-			}
-
-			if kubeRefresher.ProviderRefreshInterval != tt.expectedRefreshInterval {
-				t.Fatalf("Expected ProviderRefreshInterval %v, but got %v", tt.expectedRefreshInterval, kubeRefresher.ProviderRefreshInterval)
-			}
-
-			if kubeRefresher.Resource != tt.expectedResource {
-				t.Fatalf("Expected Resource %v, but got %v", tt.expectedResource, kubeRefresher.Resource)
-			}
-		})
-	}
-}
diff --git a/pkg/verifier/notation/certstoresbytype_test.go b/pkg/verifier/notation/certstoresbytype_test.go
deleted file mode 100644
index cd4ae90..0000000
--- a/pkg/verifier/notation/certstoresbytype_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-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 "testing"
-
-func TestNewCertStoreByTypeInvalidInput(t *testing.T) {
-	tests := []struct {
-		name      string
-		conf      verificationCertStores
-		expectErr bool
-	}{
-		{
-			name: "invalid certStores type",
-			conf: verificationCertStores{
-				trustStoreTypeCA: []string{},
-			},
-			expectErr: true,
-		},
-		{
-			name: "invalid certProviderList type",
-			conf: verificationCertStores{
-				trustStoreTypeCA: map[string]interface{}{
-					"certstore1": "akv1",
-					"certstore2": []interface{}{"akv3", "akv4"},
-				},
-			},
-			expectErr: true,
-		},
-		{
-			name: "invalid certProvider type",
-			conf: verificationCertStores{
-				trustStoreTypeCA: map[string]interface{}{
-					"certstore1": []interface{}{"akv1", []string{}},
-				},
-			},
-			expectErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			_, err := newCertStoreByType(tt.conf)
-			if (err != nil) != tt.expectErr {
-				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-		})
-	}
-}
diff --git a/pkg/verifier/notation/notation_test.go b/pkg/verifier/notation/notation_test.go
deleted file mode 100644
index 61a0c2e..0000000
--- a/pkg/verifier/notation/notation_test.go
+++ /dev/null
@@ -1,632 +0,0 @@
-// 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 (
-	"context"
-	"crypto/x509"
-	"crypto/x509/pkix"
-	"fmt"
-	"net/http"
-	paths "path/filepath"
-	"reflect"
-	"testing"
-
-	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
-	sig "github.com/notaryproject/notation-core-go/signature"
-	"github.com/notaryproject/notation-go"
-	"github.com/notaryproject/notation-go/verifier/trustpolicy"
-	"github.com/opencontainers/go-digest"
-	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
-	ratifyconfig "github.com/ratify-project/ratify/config"
-	"github.com/ratify-project/ratify/pkg/common"
-	"github.com/ratify-project/ratify/pkg/homedir"
-	"github.com/ratify-project/ratify/pkg/ocispecs"
-	"github.com/ratify-project/ratify/pkg/referrerstore"
-	"github.com/ratify-project/ratify/pkg/referrerstore/config"
-	"github.com/ratify-project/ratify/pkg/verifier"
-)
-
-const (
-	testArtifactType1 = "testArtifactType1"
-	testArtifactType2 = "testArtifactType2"
-	test              = "test"
-	testPath          = "/test/path"
-	testMediaType     = "testMediaType"
-	testVersion       = "1.0"
-	testDigest        = "sha256:123456"
-	testDigest2       = "sha256:234567"
-	invalidDigest     = "invalidDigest"
-)
-
-var (
-	failedResult = verifier.VerifierResult{IsSuccess: false}
-	testOutcome  = &notation.VerificationOutcome{
-		EnvelopeContent: &sig.EnvelopeContent{
-			SignerInfo: sig.SignerInfo{
-				CertificateChain: []*x509.Certificate{
-					{Issuer: pkix.Name{}, Subject: pkix.Name{}},
-				},
-			},
-		},
-	}
-	testRefBlob  = []byte("test")
-	testRefBlob2 = []byte("test2")
-	testDesc1    = ocispec.Descriptor{}
-	validRef     = common.Reference{
-		Original: "testRegistry/repo:v1",
-		Digest:   testDigest,
-	}
-	validRef2 = common.Reference{
-		Original: "testRegistry/repo:v2",
-		Digest:   testDigest2,
-	}
-	invalidRef = common.Reference{
-		Original: "invalid",
-		Tag:      "invalid",
-	}
-	invalidRef2 = common.Reference{
-		Original: "invalid",
-	}
-	testNotationPluginVerifier notation.Verifier = mockNotationPluginVerifier{}
-	validBlobDesc                                = ocispec.Descriptor{
-		Digest: testDigest,
-	}
-	validBlobDesc2 = ocispec.Descriptor{
-		Digest: testDigest2,
-	}
-	defaultCertDir  = paths.Join(homedir.Get(), ratifyconfig.ConfigFileDir, defaultCertPath)
-	testTrustPolicy = map[string]interface{}{
-		"version": "1.0",
-		"trustPolicies": []map[string]interface{}{
-			{
-				"name":           "default",
-				"registryScopes": []string{"*"},
-				"signatureVerification": map[string]string{
-					"level": "strict",
-				},
-				"trustStores":       []string{"ca:certs"},
-				"trustedIdentities": []string{"*"},
-			},
-		},
-	}
-)
-
-type mockNotationPluginVerifier struct{}
-
-func (v mockNotationPluginVerifier) Verify(_ context.Context, _ ocispec.Descriptor, signature []byte, _ notation.VerifierVerifyOptions) (*notation.VerificationOutcome, error) {
-	if reflect.DeepEqual(signature, testRefBlob2) {
-		return nil, fmt.Errorf("failed verification")
-	}
-	return testOutcome, nil
-}
-
-type mockStore struct {
-	refBlob  []byte
-	manifest ocispecs.ReferenceManifest
-}
-
-func (s mockStore) Name() string {
-	return test
-}
-
-func (s mockStore) ListReferrers(_ context.Context, _ common.Reference, _ []string, _ string, _ *ocispecs.SubjectDescriptor) (referrerstore.ListReferrersResult, error) {
-	return referrerstore.ListReferrersResult{}, nil
-}
-
-func (s mockStore) GetBlobContent(_ context.Context, _ common.Reference, _ digest.Digest) ([]byte, error) {
-	if s.refBlob == nil {
-		return nil, fmt.Errorf("invalid blob")
-	}
-	return s.refBlob, nil
-}
-
-func (s mockStore) GetReferenceManifest(_ context.Context, _ common.Reference, _ ocispecs.ReferenceDescriptor) (ocispecs.ReferenceManifest, error) {
-	if len(s.manifest.Blobs) == 0 {
-		return s.manifest, fmt.Errorf("invalid reference")
-	}
-	return s.manifest, nil
-}
-
-func (s mockStore) GetConfig() *config.StoreConfig {
-	return nil
-}
-
-func (s mockStore) GetSubjectDescriptor(_ context.Context, subjectReference common.Reference) (*ocispecs.SubjectDescriptor, error) {
-	if subjectReference.Tag == "invalid" {
-		return nil, fmt.Errorf("cannot resolve digest for the subject reference")
-	}
-	return &ocispecs.SubjectDescriptor{
-		Descriptor: ocispec.Descriptor{},
-	}, nil
-}
-
-func TestName(t *testing.T) {
-	verifierConfig := map[string]interface{}{
-		"name":           "notation-verifier-0",
-		"type":           "notation",
-		"trustPolicyDoc": testTrustPolicy,
-	}
-
-	f := &notationPluginVerifierFactory{}
-	verifier, err := f.Create(testVersion, verifierConfig, "", "")
-	if err != nil {
-		t.Fatalf("failed create notation verifier got error = %v", err)
-	}
-	if name := verifier.Name(); name != "notation-verifier-0" {
-		t.Fatalf("expect name: notation-verifier-0, got: %s", name)
-	}
-}
-
-func TestCanVerify(t *testing.T) {
-	tests := []struct {
-		name              string
-		artifactTypes     []string
-		referenceArtifact string
-		expect            bool
-	}{
-		{
-			name:              "wildcard pattern",
-			artifactTypes:     []string{"*"},
-			referenceArtifact: testArtifactType1,
-			expect:            true,
-		},
-		{
-			name:              "type unmatched",
-			artifactTypes:     []string{testArtifactType2},
-			referenceArtifact: testArtifactType1,
-			expect:            false,
-		},
-		{
-			name:              "type matched",
-			artifactTypes:     []string{testArtifactType1},
-			referenceArtifact: testArtifactType1,
-			expect:            true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			v := &notationPluginVerifier{
-				artifactTypes: tt.artifactTypes,
-			}
-			desc := ocispecs.ReferenceDescriptor{
-				ArtifactType: tt.referenceArtifact,
-			}
-
-			got := v.CanVerify(context.Background(), desc)
-			if got != tt.expect {
-				t.Fatalf("Expect: %v, got: %v", tt.expect, got)
-			}
-		})
-	}
-}
-
-func TestParseVerifierConfig(t *testing.T) {
-	tests := []struct {
-		name      string
-		configMap map[string]interface{}
-		expectErr bool
-		expect    *NotationPluginVerifierConfig
-	}{
-		{
-			name: "failed unmarshalling to notation config",
-			configMap: map[string]interface{}{
-				"name":              test,
-				"verificationCerts": make(chan int),
-			},
-			expectErr: true,
-			expect:    nil,
-		},
-		{
-			name: "failed unmarshalling to notation config",
-			configMap: map[string]interface{}{
-				"name": test,
-				"verificationCertStores": verificationCertStores{
-					"certstore1": []interface{}{"akv1", "akv2"},
-					"ca": map[string]interface{}{
-						"certstore1": []interface{}{"akv1", "akv2"},
-						"certstore2": []interface{}{"akv3", "akv4"},
-					},
-				},
-			},
-			expectErr: true,
-			expect:    nil,
-		},
-		{
-			name: "successfully parsed with default cert directory",
-			configMap: map[string]interface{}{
-				"name": test,
-			},
-			expectErr: false,
-			expect: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{defaultCertDir},
-			},
-		},
-		{
-			name: "successfully parsed with specified cert directory",
-			configMap: map[string]interface{}{
-				"name":              test,
-				"verificationCerts": []string{testPath},
-			},
-			expectErr: false,
-			expect: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-			},
-		},
-		{
-			name: "successfully parsed with specified cert stores",
-			configMap: map[string]interface{}{
-				"name":              test,
-				"verificationCerts": []string{testPath},
-				"verificationCertStores": map[string][]string{
-					"certstore1": {"akv1", "akv2"},
-					"certstore2": {"akv3", "akv4"},
-				},
-			},
-			expectErr: false,
-			expect: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-				VerificationCertStores: verificationCertStores{
-					trustStoreTypeCA: map[string]interface{}{
-						"certstore1": []interface{}{"akv1", "akv2"},
-						"certstore2": []interface{}{"akv3", "akv4"},
-					},
-				},
-			},
-		},
-	}
-
-	//TODO add new test for parseVerifierConfig
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			notationPluginConfig, err := parseVerifierConfig(tt.configMap, "testns")
-
-			if (err != nil) != tt.expectErr {
-				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-			if !reflect.DeepEqual(notationPluginConfig, tt.expect) {
-				t.Errorf("expect %+v, got %+v", tt.expect, notationPluginConfig)
-			}
-		})
-	}
-}
-
-func TestVerifySignature(t *testing.T) {
-	v := &notationPluginVerifier{
-		notationVerifier: &testNotationPluginVerifier,
-	}
-
-	outcome, err := v.verifySignature(context.Background(), testArtifactType1, testMediaType, testDesc1, testRefBlob)
-	if err != nil {
-		t.Errorf("got unexpected error: %v", err)
-	}
-	if !reflect.DeepEqual(outcome, testOutcome) {
-		t.Fatalf("expect outcome: %v, got: %v", outcome, testOutcome)
-	}
-}
-
-func TestCreate(t *testing.T) {
-	tests := []struct {
-		name      string
-		configMap map[string]interface{}
-		expect    verifier.ReferenceVerifier
-		expectErr bool
-	}{
-		{
-			name: "failed get verify service",
-			configMap: map[string]interface{}{
-				"name": test,
-				"verificationCertStores": verificationCertStores{
-					trustStoreTypeCA: verificationCertStores{
-						"certstore1": []interface{}{"akv1", "akv2", 1},
-					},
-				},
-			},
-			expectErr: true,
-		},
-		{
-			name: "failed parsing verifier config",
-			configMap: map[string]interface{}{
-				"name":           test,
-				"trustPolicyDoc": 1,
-			},
-			expectErr: true,
-		},
-		{
-			name: "failed loading policy",
-			configMap: map[string]interface{}{
-				"name":        test,
-				"trustPolicy": "{",
-			},
-			expectErr: true,
-		},
-		{
-			name: "created verifier successfully",
-			configMap: map[string]interface{}{
-				"name":           test,
-				"trustPolicyDoc": testTrustPolicy,
-			},
-			expectErr: false,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			f := &notationPluginVerifierFactory{}
-			_, err := f.Create(testVersion, tt.configMap, "", "")
-
-			if (err != nil) != tt.expectErr {
-				t.Fatalf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-		})
-	}
-}
-
-func TestVerify(t *testing.T) {
-	tests := []struct {
-		name      string
-		expect    verifier.VerifierResult
-		ref       common.Reference
-		manifest  ocispecs.ReferenceManifest
-		refBlob   []byte
-		expectErr bool
-	}{
-		{
-			name:      "failed getting subject descriptor",
-			ref:       invalidRef,
-			refBlob:   []byte(""),
-			manifest:  ocispecs.ReferenceManifest{},
-			expect:    failedResult,
-			expectErr: true,
-		},
-		{
-			name:      "failed getting manifest",
-			ref:       invalidRef2,
-			refBlob:   []byte(""),
-			manifest:  ocispecs.ReferenceManifest{},
-			expect:    failedResult,
-			expectErr: true,
-		},
-		{
-			name:    "failed verifying signature",
-			ref:     validRef2,
-			refBlob: testRefBlob2,
-			manifest: ocispecs.ReferenceManifest{
-				Blobs: []ocispec.Descriptor{validBlobDesc2},
-			},
-			expect:    failedResult,
-			expectErr: true,
-		},
-		{
-			name:    "multiple signature blobs",
-			ref:     validRef2,
-			refBlob: testRefBlob2,
-			manifest: ocispecs.ReferenceManifest{
-				Blobs: []ocispec.Descriptor{validBlobDesc, validBlobDesc2},
-			},
-			expect:    failedResult,
-			expectErr: true,
-		},
-		{
-			name:    "get blob content failed",
-			ref:     validRef,
-			refBlob: nil,
-			manifest: ocispecs.ReferenceManifest{
-				Blobs: []ocispec.Descriptor{validBlobDesc},
-			},
-			expect:    failedResult,
-			expectErr: true,
-		},
-		{
-			name:    "verified successfully",
-			ref:     validRef,
-			refBlob: testRefBlob,
-			manifest: ocispecs.ReferenceManifest{
-				Blobs: []ocispec.Descriptor{validBlobDesc},
-			},
-			expect:    verifier.VerifierResult{IsSuccess: true},
-			expectErr: false,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			v := &notationPluginVerifier{
-				notationVerifier: &testNotationPluginVerifier,
-			}
-
-			store := &mockStore{
-				refBlob:  tt.refBlob,
-				manifest: tt.manifest,
-			}
-
-			result, err := v.Verify(context.Background(), tt.ref, ocispecs.ReferenceDescriptor{}, store)
-
-			if (err != nil) != tt.expectErr {
-				t.Fatalf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-			if result.IsSuccess != tt.expect.IsSuccess {
-				t.Fatalf("expect %+v, got %+v", tt.expect, result)
-			}
-		})
-	}
-}
-
-func TestGetNestedReferences(t *testing.T) {
-	verifier := &notationPluginVerifier{}
-	nestedReferences := verifier.GetNestedReferences()
-
-	if len(nestedReferences) != 0 {
-		t.Fatalf("notation signature should not have nested references")
-	}
-}
-
-func TestNormalizeVerificationCertsStores(t *testing.T) {
-	tests := []struct {
-		name      string
-		conf      *NotationPluginVerifierConfig
-		expectErr bool
-	}{
-		{
-			name: "failed normalizaVerificationCertsStores in marshal function",
-			conf: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-				VerificationCertStores: verificationCertStores{
-					"certstore2": []interface{}{make(chan int)},
-				},
-			},
-			expectErr: true,
-		},
-		{
-
-			name: "failed normalizaVerificationCertsStores with both old VerificationCertStores and new VerificationCertStores are provided",
-			conf: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-				VerificationCertStores: verificationCertStores{
-					trustStoreTypeCA: map[string]interface{}{
-						"certstore1": []interface{}{"akv1", "akv2"},
-					},
-					"certstore2": []interface{}{"akv3", "akv4"},
-				},
-			},
-			expectErr: true,
-		},
-		{
-			name: "successfully normalizaVerificationCertsStores",
-			conf: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-				VerificationCertStores: verificationCertStores{
-					trustStoreTypeCA: map[string]interface{}{
-						"certstore1": []interface{}{"akv1", "akv2"},
-						"certstore2": []interface{}{"akv3", "akv4"},
-					},
-				},
-			},
-			expectErr: false,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			err := normalizeVerificationCertsStores(tt.conf)
-			if (err != nil) != tt.expectErr {
-				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-		})
-	}
-}
-
-func TestNormalizeLegacyCertStore(t *testing.T) {
-	tests := []struct {
-		name      string
-		conf      *NotationPluginVerifierConfig
-		expectErr bool
-	}{
-		{
-			name: "successfully normalizaVerificationCertsStores",
-			conf: &NotationPluginVerifierConfig{
-				Name:              test,
-				VerificationCerts: []string{testPath, defaultCertDir},
-				VerificationCertStores: verificationCertStores{
-					"certstore2": []interface{}{make(chan int)},
-				},
-			},
-			expectErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			_, err := normalizeLegacyCertStore(tt.conf)
-			if (err != nil) != tt.expectErr {
-				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-		})
-	}
-}
-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: "successfully create verifier service",
-			conf: &NotationPluginVerifierConfig{
-				VerificationCerts: []string{defaultCertDir},
-				TrustPolicyDoc: trustpolicy.Document{
-					Version: "1.0",
-					TrustPolicies: []trustpolicy.TrustPolicy{
-						{
-							Name:           "default",
-							RegistryScopes: []string{"*"},
-							SignatureVerification: trustpolicy.SignatureVerification{
-								VerificationLevel: "strict",
-							},
-							TrustStores:       []string{"ca:certs"},
-							TrustedIdentities: []string{"*"},
-						},
-					},
-				},
-			},
-			pluginDir:         "",
-			RevocationFactory: mockRevocationFactory{httpClient: &http.Client{}},
-			expectErr:         false,
-			errContent:        nil,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			_, err := getVerifierService(context.Background(), 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
-	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)
-}
diff --git a/pkg/verifier/notation/notationrevocationfactory_test.go b/pkg/verifier/notation/notationrevocationfactory_test.go
deleted file mode 100644
index 4021313..0000000
--- a/pkg/verifier/notation/notationrevocationfactory_test.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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-go/dir"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewRevocationFactoryImpl(t *testing.T) {
-	factory := CreateCRLHandlerFromConfig()
-	assert.NotNil(t, factory)
-}
-
-func TestNewFetcher(t *testing.T) {
-	tests := []struct {
-		name       string
-		cacheRoot  string
-		httpClient *http.Client
-		wantErr    bool
-		firstCall  bool
-	}{
-		{
-			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.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 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)
-			}
-		})
-	}
-}
diff --git a/pkg/verifier/notation/pluginmanager_test.go b/pkg/verifier/notation/pluginmanager_test.go
deleted file mode 100644
index 8ac16eb..0000000
--- a/pkg/verifier/notation/pluginmanager_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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 (
-	"context"
-	"os"
-	"testing"
-)
-
-const (
-	pluginDirectory  = "./pluginmanagertest"
-	ignoredDirectory = "notation-ignored"
-	ignoredFile      = "ignored.file"
-	testPluginName   = "mock.plugin"
-)
-
-func TestMain(m *testing.M) {
-	err := setupTestFiles()
-	code := 1
-	if err == nil {
-		code = m.Run()
-	}
-	cleanupTestFiles()
-	os.Exit(code)
-}
-
-func setupTestFiles() error {
-	err := os.Mkdir(pluginDirectory, 0700)
-	if err != nil {
-		return err
-	}
-
-	err = os.Mkdir(pluginDirectory+"/"+ignoredDirectory, 0700)
-	if err != nil {
-		return err
-	}
-
-	err = os.WriteFile(pluginDirectory+"/"+notationPluginPrefix+testPluginName, []byte(""), 0600)
-	if err != nil {
-		return err
-	}
-
-	err = os.WriteFile(pluginDirectory+"/"+ignoredFile, []byte(""), 0600)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func cleanupTestFiles() {
-	os.RemoveAll(pluginDirectory)
-}
-
-func TestPluginManagerGet(t *testing.T) {
-	pluginManager := NewRatifyPluginManager(pluginDirectory)
-
-	_, err := pluginManager.Get(context.TODO(), testPluginName)
-	if err != nil {
-		t.Errorf("unexpected error: %v", err)
-	}
-}
-
-func TestPluginManagerList(t *testing.T) {
-	pluginManager := NewRatifyPluginManager(pluginDirectory)
-
-	pluginList, err := pluginManager.List(context.TODO())
-	if err != nil {
-		t.Errorf("unexpected error: %v", err)
-	}
-
-	if len(pluginList) != 1 {
-		t.Errorf("expected to find exactly one plugin, instead found %d", len(pluginList))
-		t.Fatalf("plugin list: %+v", pluginList)
-	}
-
-	if pluginList[0] != testPluginName {
-		t.Errorf("expected to find plugin named %s, instead found %s", testPluginName, pluginList[0])
-	}
-}
diff --git a/pkg/verifier/notation/revocationfactory_test.go b/pkg/verifier/notation/revocationfactory_test.go
deleted file mode 100644
index 79f9766..0000000
--- a/pkg/verifier/notation/revocationfactory_test.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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 (
-	"context"
-	"crypto/x509"
-	"fmt"
-	"net/http"
-	"testing"
-
-	corecrl "github.com/notaryproject/notation-core-go/revocation/crl"
-	"github.com/ratify-project/ratify/config"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestSupportCRL(t *testing.T) {
-	t.Run("certificate with CRL distribution points", func(t *testing.T) {
-		cert := &x509.Certificate{
-			CRLDistributionPoints: []string{"http://example.com/crl"},
-		}
-		assert.True(t, SupportCRL(cert))
-	})
-
-	t.Run("certificate without CRL distribution points", func(t *testing.T) {
-		cert := &x509.Certificate{}
-		assert.False(t, SupportCRL(cert))
-	})
-
-	t.Run("nil certificate", func(t *testing.T) {
-		assert.False(t, SupportCRL(nil))
-	})
-}
-func TestCacheCRL(t *testing.T) {
-	ctx := context.Background()
-	httpClient := &http.Client{}
-	cacheRoot := "/tmp/cache"
-	fetcher, _ := CreateCRLFetcher(httpClient, cacheRoot)
-
-	t.Run("nil fetcher", func(t *testing.T) {
-		certs := []*x509.Certificate{
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl"},
-			},
-		}
-		CacheCRL(ctx, certs, nil)
-		// Check logs if necessary
-		t.Log("CRL fetcher is nil")
-	})
-
-	t.Run("certificate without CRL distribution points", func(t *testing.T) {
-		certs := []*x509.Certificate{
-			{},
-		}
-		CacheCRL(ctx, certs, fetcher)
-		// Check logs if necessary
-		t.Log("Certificate does not support CRL")
-	})
-
-	t.Run("certificates with CRL distribution points", func(t *testing.T) {
-		certs := []*x509.Certificate{
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl1"},
-			},
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl2"},
-			},
-		}
-		CacheCRL(ctx, certs, fetcher)
-		// Check logs if necessary
-		t.Log("Completed fetching CRLs")
-	})
-}
-func TestIntermittentFailCacheCRL(t *testing.T) {
-	ctx := context.Background()
-	t.Run("fetch CRL fails", func(t *testing.T) {
-		// Mock fetcher to simulate failure
-		mockFetcher := &MockFetcher{
-			flag: true,
-			FetchFunc: func(_ context.Context, _ string) (*corecrl.Bundle, error) {
-				return &corecrl.Bundle{}, nil
-			},
-		}
-		certs := []*x509.Certificate{
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl1"},
-			},
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl2"},
-			},
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl3"},
-			},
-			{
-				CRLDistributionPoints: []string{"http://example.com/crl4"},
-			},
-		}
-		CacheCRL(ctx, certs, mockFetcher)
-		// Check logs if necessary
-		t.Log("Completed fetching CRLs with intermittent failures")
-	})
-}
-
-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
-	FetchFunc func(ctx context.Context, url string) (*corecrl.Bundle, error)
-}
-
-func (m *MockFetcher) Fetch(ctx context.Context, url string) (*corecrl.Bundle, error) {
-	m.flag = !m.flag
-	if m.flag {
-		return nil, fmt.Errorf("failed to fetch CRL from %s", url)
-	}
-	return m.FetchFunc(ctx, url)
-}
diff --git a/pkg/verifier/notation/truststore_test.go b/pkg/verifier/notation/truststore_test.go
deleted file mode 100644
index 964f97c..0000000
--- a/pkg/verifier/notation/truststore_test.go
+++ /dev/null
@@ -1,273 +0,0 @@
-// 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 (
-	"context"
-	"crypto/x509"
-	"encoding/pem"
-	"errors"
-	"os"
-	"reflect"
-	"testing"
-
-	"github.com/notaryproject/notation-go/verifier/truststore"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/pkg/controllers"
-)
-
-const (
-	certStr     = "-----BEGIN CERTIFICATE-----\nMIIDsDCCApigAwIBAgIQMdNmNTKwQ9aOe6iuMRokDzANBgkqhkiG9w0BAQsFADBa\nMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzAN\nBgNVBAoTBk5vdGFyeTEbMBkGA1UEAxMSd2FiYml0LW5ldHdvcmtzLmlvMB4XDTIy\nMTIxNDIxNTAzMVoXDTIzMTIxNDIyMDAzMVowWjELMAkGA1UEBhMCVVMxCzAJBgNV\nBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxGzAZBgNV\nBAMTEndhYmJpdC1uZXR3b3Jrcy5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAOP6AHCFz41kRqsAiv6guFtQVsrzMgzoCX7o9NtQ57rr8BESP1LTGRAO\n4bjyP0i+at5uwIm4tdz0gW+g0P+f9bmfiScYgOFuxAJxLkMkBWPN3dJ9ulP/OGgB\n6mSCsEGreB3uaGc5rMbWCRaux65bMPjEzx5ex0qRSsn+fFMTwINPQUJpXSvi/W2/\n1umEWE1x59x0vlkP2dN7CXtB5/Bh01QNNbMdKU9saYn0kaBrCYZLwr6AxFRzLqLM\nQggy/6bOp/+cTTVqTiChMcdyIX52GRr2lChRsB34dDPYxDeKSI5LoRy07bveLjex\n4wm9+vx/WOSS5z0QPvE/v8avuIkMXR0CAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeA\nMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAUwVvE\nvqQPxnE6j6pfX6jpSyv2dOAwHQYDVR0OBBYEFMFbxL6kD8ZxOo+qX1+o6Usr9nTg\nMA0GCSqGSIb3DQEBCwUAA4IBAQDE61FLbagvlCcXf0zcv+mUQ+0HvDVs7ofQe3Yw\naz7gAwxgTspr+jIFQWnPOOBupsyx/jucoz78ndbc5DGWPs2Qz/pIEGnLto2W/PYy\nas/9n8xHxembS4n/Mxxp60PF6ladi/nJAtDJds67sBeqLOfJzh6jV2uQvW7PXe1P\nOMSUHbBn8AfArZ/9njusiLs75+XcAgpnBFqKVv2Vd/INp2YQpVzusuiodeM8A9Qt\n/5xykjdCJw3ceZxD7dSkHgchKZPINFBYHt/EkN/d8mXFOKjGXZyntp4PO6PJ2HYN\nhMMDwdNu4mBmlMTdZMPEpIZIeW7G0P9KpCuvvD7po7NxdBgI\n-----END CERTIFICATE-----\n"
-	certStr2    = "-----BEGIN CERTIFICATE-----\nMIIDsDCCApigAwIBAgIQFJMQeqR8TRuHqNu+x0MuEDANBgkqhkiG9w0BAQsFADBa\nMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0ExEDAOBgNVBAcTB1NlYXR0bGUxDzAN\nBgNVBAoTBk5vdGFyeTEbMBkGA1UEAxMSd2FiYml0LW5ldHdvcmtzLmlvMB4XDTIz\nMDExMTE5MjAxMloXDTI0MDExMTE5MzAxMlowWjELMAkGA1UEBhMCVVMxCzAJBgNV\nBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZOb3RhcnkxGzAZBgNV\nBAMTEndhYmJpdC1uZXR3b3Jrcy5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\nAQoCggEBAMh7F6sZyeiQRva83SvQu0PbsyD4zkEeWAyj03n1dx91FEeEXItCr+Y1\nghQKgdBOY/wJQmSq/We1e+17NoNICrzy2Y1sOVMYR5sx8H/UxO3q8oS7bxctFy+e\nHs4BxlHIqeIiWnz9bFAJFqV6BkJDVjp9k5QfHlkqH08WBvm/D8YTpWzvEPn+71ZG\nN1RKqFUeeM949oGGnC63vVMRRYIx2LoJliNZXdj9qoOHZksDrX2jkgPykkOYcmfo\n9CH9v0JNX+0t0Enp0ruUFK1pSZW+TicI22GvENYHGZNZ0m+6oD5ePRZoYhWyAzgZ\nndHO5bYh3yC7DMc6ssOEJeNN0I2+iLUCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeA\nMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAUYhhf\nPFgAqU8PF3ClvfKs67HmpWwwHQYDVR0OBBYEFGIYXzxYAKlPDxdwpb3yrOux5qVs\nMA0GCSqGSIb3DQEBCwUAA4IBAQCXu1w+6s2RO2/KPmC+29m9EjbDReI4bGlDGgiv\nwk1fmvPvDrqL4Ebpcrb1nstNlsxpKYQP+3Vi8gPiqNQ7JvPStd1NBu+ViCXdvOe5\nCtN7tBFTCBgdgXNZ9bvIM2dS+xW/ZAJdyHbV9Hn77+rs/uCDHtbaQMJ3N9LGW8GR\nGY+uYylrrCrjb9fzotMaONnF9c1GKiANskc9371wbaninpxcwMNA5j027XzfnMEW\nm807wjlNV3Kuf4fdDpzBLe940iplfTlQMylWMqgANpEw4EqHCrBJPQAHfQEpQlo+\n9H72lrqOiYNNwApfB9P+UqMDi1B7T2yzfvXcqQ75FpSRIxzK\n-----END CERTIFICATE-----\n"
-	caCertStr   = "-----BEGIN CERTIFICATE-----\nMIIDNTCCAh2gAwIBAgIUbLzOMsPOGflj7TS34tzjs5vBWYIwDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzAzMTAwMTEwMjlaFw0yNDAzMDkwMTEwMjlaMCoxDzANBgNVBAoMBlJhdGlm\neTEXMBUGA1UEAwwOUmF0aWZ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\nDwAwggEKAoIBAQCeNlh95GnkHLBVSCoYmlPztNKw5jwmlZYWLgwZMOK0qKedlsZs\naxbb5YzQlIV/z8D+/DnsZ3hTmokset0hE6JDQ1lw5wjk1I8DijkjwiE3oVH5Kyv/\nPSUtbSP7LmNDG/2vtWBkyTltXf3SfqAazLXVd0IQqGTXie+2SJa9Q6UAZFWKB1t7\n0Js6rDyQULcUMSzvF39QBPHFcd9iuSZLPw9CGG7hHNTlaOQryukr6U9tjY4hLK7e\n1OdgyP17nXELIlL81ngoWufi3rLgePqfkg8GgwnWyFrDS2eZSofFqW0X80gDvEQ+\n5WGj4XklyGGHpwyR4qNMnv5hp7QMtDd62iyPAgMBAAGjUzBRMB0GA1UdDgQWBBQQ\nGxu39HR2ynlSR40ZySohaxKGMDAfBgNVHSMEGDAWgBQQGxu39HR2ynlSR40ZySoh\naxKGMDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB22EixNuBZ\nyeGtrtSpkVPer+nxKU+6upwXmLfTe3ZEbv1NqC2auUvD+EN/86+mJfeXhkdVHHoV\nteuXNVU0oJ4ocRUXkgA/jPUEnjXwYK661/N67mqr5wLHcKIt48yKNdMvfXO6tXSE\nx/xLQlX7v2JehEQtTv7axnYGoHOvKL2H0+lq5VN0rDnB5hb7LyRX9kQq6mszLzG5\nbypfWX1aReWViWU2d6hvVegDYFpRpPXE3o5FGWvrad91RXdSJLsjJGdYJMlUe3xR\n+guQHepJ0iCoreAr+0XkctcV0qlyOiIuikWMdrQiXXTIDCGTRNmD9XCTu5+2tZe+\nW2O8QLkvH3Fv\n-----END CERTIFICATE-----\n"
-	leafCertStr = "-----BEGIN CERTIFICATE-----\nMIIC7jCCAdagAwIBAgIURNiOON+GKbFS8yFxG6aMRoMg29cwDQYJKoZIhvcNAQEL\nBQAwKjEPMA0GA1UECgwGUmF0aWZ5MRcwFQYDVQQDDA5SYXRpZnkgUm9vdCBDQTAe\nFw0yMzAzMTAwMTEwMjlaFw0yNDAzMDkwMTEwMjlaMBkxFzAVBgNVBAMMDnJhdGlm\neS5kZWZhdWx0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUwGuWJ5\nDwspcL+7K+0XlkQ0g+sbyvfY0j0NdUmzsTPQNxsdUsbgYeidLnp0ruHKuHLq6Y9t\nEHUPF+A4S6lIi5OPhEkVxd/A5kzSX23WocJGmlew+Z/usjQdtiQ4ylYyHoHfPNrf\nrocbY21XQ3x2IM3yIo1QqSHNdCsE0UxsFI3j9XC+saIqrkr+k1SsI2AhhGRjXTke\nPNpOaJ+CRwsGz7PbnsACLbiAdOUJUGRkOlIl/p7hU2IcZUYTTGcKOFXP8DtbUJ+K\nQcBQOsfZyg36jvkpzmw/yAK00Uuc0X+5CaKfDKDw4MXvJFpRvG+Vc0mb5RB1E8py\neA6eXtUrZ5J4hQIDAQABox0wGzAZBgNVHREEEjAQgg5yYXRpZnkuZGVmYXVsdDAN\nBgkqhkiG9w0BAQsFAAOCAQEAHbiuodTJCDpCUu8tNjbww5ebTRznKZGnFmKQs5zU\no8KyCfLhR9/9zetDADwtWCQUvykFuHjx8tj41hALXXXafzkYPeTsfDmEoVWIJMQ1\nHqjbzc6bbxQAY7cC5HqM67fXYjPs1v3Uv3GZhF2EjBMqymKC+lZ/RSfktzN0iADn\nlwG9DrDibD739jBF09b3LHtdV55blN2wyB54DwMl5x0a4+bFYVj7fZzjctG4pH7T\njnBS69oxetPaqcRY7SQljJKaesiqx3CtiwVUpGTBexDtw6OIj9cWiCFT0lS3TfCh\nunfSQvVgezqE7txrFbXDQCgbl1jGagfia2ol7+IbLUR6TQ==\n-----END CERTIFICATE-----\n"
-)
-
-type mockCertStores struct {
-	certMap      map[string][]*x509.Certificate
-	reconcileErr error
-}
-
-func (m *mockCertStores) GetCertsFromStore(_ context.Context, storeName string) ([]*x509.Certificate, error) {
-	if m.reconcileErr != nil {
-		return nil, m.reconcileErr
-	}
-	if m.certMap == nil {
-		return nil, nil
-	}
-	return m.certMap[storeName], nil
-}
-
-func (m *mockCertStores) AddStore(_ string, _ []*x509.Certificate) {}
-
-func (m *mockCertStores) DeleteStore(_ string) {}
-
-func (m *mockCertStores) AddStoreError(_ string, _ error) {}
-
-func TestIsReconcileError(t *testing.T) {
-	err := errors.New("reconcile error")
-	if !isReconcileError(err) {
-		t.Fatalf("expected to be a reconcile error")
-	}
-
-	err = re.ErrorCodeNotFound.WithDetail("not found")
-	if isReconcileError(err) {
-		t.Fatalf("expected not to be a reconcile error")
-	}
-}
-
-func TestParseErrFromKmpAndCertStore(t *testing.T) {
-	reconcileErr := errors.New("reconcile error")
-	notFoundErr := re.ErrorCodeNotFound.WithDetail("not found")
-	tests := []struct {
-		name         string
-		kmpErr       error
-		certStoreErr error
-		expectedErr  error
-	}{
-		{
-			name:         "nil errors",
-			kmpErr:       nil,
-			certStoreErr: nil,
-			expectedErr:  nil,
-		},
-		{
-			name:         "kmpErr should be returned",
-			kmpErr:       reconcileErr,
-			certStoreErr: notFoundErr,
-			expectedErr:  reconcileErr,
-		},
-		{
-			name:         "certStoreErr should be returned",
-			kmpErr:       notFoundErr,
-			certStoreErr: reconcileErr,
-			expectedErr:  reconcileErr,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			result := parseErrFromKmpAndCertStore(tt.kmpErr, tt.certStoreErr)
-			if !errors.Is(result, tt.expectedErr) {
-				t.Fatalf("expected %+v, got %+v", tt.expectedErr, result)
-			}
-		})
-	}
-}
-
-func TestGetCertificates_EmptyCertMap(t *testing.T) {
-	resetCertStore()
-	certStore := verificationCertStores{
-		trustStoreTypeCA: map[string]interface{}{
-			"certstore1": []interface{}{"akv1", "akv2"},
-			"certstore2": []interface{}{"akv3", "akv4"},
-		},
-	}
-	store, err := newTrustStore([]string{}, certStore)
-	if err != nil {
-		panic("failed to parse verificationCertStores: " + err.Error())
-	}
-	if _, err := store.getCertificatesInternal(context.Background(), truststore.TypeCA, "certstore1"); err == nil {
-		t.Fatalf("error expected if cert map is empty")
-	}
-}
-
-func TestGetCertificates_ErrorFromKMPReconcile(t *testing.T) {
-	resetCertStore()
-	certStore := verificationCertStores{
-		trustStoreTypeCA: map[string]interface{}{
-			"certstore1": []interface{}{"default/kv1"},
-			"certstore2": []interface{}{"projecta/kv2"},
-		},
-	}
-	store, err := newTrustStore(nil, certStore)
-	if err != nil {
-		t.Fatalf("failed to parse verificationCertStores: %s", err.Error())
-	}
-
-	controllers.NamespacedCertStores = &mockCertStores{
-		reconcileErr: errors.New("reconcile error"),
-	}
-
-	// only the certificate in the specified namedStore should be returned
-	if _, err := store.getCertificatesInternal(context.Background(), truststore.TypeCA, "certstore1"); err == nil {
-		t.Fatalf("error expected if error from KMP reconcile")
-	}
-}
-
-func TestGetCertificates_NamedStore(t *testing.T) {
-	resetCertStore()
-	certStore := verificationCertStores{
-		trustStoreTypeCA: map[string]interface{}{
-			"certstore1": []interface{}{"default/kv1"},
-			"certstore2": []interface{}{"projecta/kv2"},
-		},
-	}
-	store, err := newTrustStore(nil, certStore)
-	if err != nil {
-		panic("failed to parse verificationCertStores: " + err.Error())
-	}
-
-	kv1Cert := getCert(certStr)
-	kv2Cert := getCert(certStr2)
-
-	certificatesMap := map[string][]*x509.Certificate{}
-	certificatesMap["default/kv1"] = []*x509.Certificate{kv1Cert}
-	certificatesMap["projecta/kv2"] = []*x509.Certificate{kv2Cert}
-	controllers.NamespacedCertStores = &mockCertStores{
-		certMap: certificatesMap,
-	}
-
-	// only the certificate in the specified namedStore should be returned
-	result, _ := store.getCertificatesInternal(context.Background(), truststore.TypeCA, "certstore1")
-	expectedLen := 1
-
-	if len(result) != expectedLen {
-		t.Fatalf("unexpected count of certificate, expected %+v, got %+v", expectedLen, len(result))
-	}
-
-	if !kv1Cert.Equal(result[0]) {
-		t.Fatalf("unexpected certificate returned")
-	}
-}
-
-func TestGetCertificates_certPath(t *testing.T) {
-	resetCertStore()
-	// create a temporary certificate file
-	tmpFile, err := os.CreateTemp("", "*.pem")
-	if err != nil {
-		t.Fatalf("failed to create temporary file: %v", err)
-	}
-	if _, err := tmpFile.Write([]byte(certStr)); err != nil {
-		t.Fatalf("failed to write cert: %v", err)
-	}
-
-	trustStore := &trustStore{
-		certPaths:  []string{tmpFile.Name()},
-		certStores: certStoresByType{},
-	}
-	certs, err := trustStore.getCertificatesInternal(context.Background(), truststore.TypeCA, "")
-	if err != nil {
-		t.Fatalf("failed to get certs: %v", err)
-	}
-
-	if len(certs) != 1 || !certs[0].Equal(getCert(certStr)) {
-		t.Fatalf("unexpected certificate returned")
-	}
-
-	// remove the temporary certificate file
-	if err := tmpFile.Close(); err != nil {
-		t.Fatalf("failed to close temporary file: %v", err)
-	}
-}
-
-func TestFilterValidCerts(t *testing.T) {
-	trustStore := trustStore{}
-	tests := []struct {
-		name      string
-		certs     []*x509.Certificate
-		expect    []*x509.Certificate
-		expectErr bool
-	}{
-		{
-			name:      "CA cert",
-			certs:     []*x509.Certificate{getCert(caCertStr)},
-			expect:    []*x509.Certificate{getCert(caCertStr)},
-			expectErr: false,
-		},
-		{
-			name:      "self-signed cert",
-			certs:     []*x509.Certificate{getCert(certStr)},
-			expect:    []*x509.Certificate{getCert(certStr)},
-			expectErr: false,
-		},
-		{
-			name:      "invalid cert",
-			certs:     []*x509.Certificate{getCert(leafCertStr)},
-			expect:    nil,
-			expectErr: true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			result, err := trustStore.filterValidCerts(tt.certs)
-			if (err != nil) != tt.expectErr {
-				t.Errorf("error = %v, expectErr = %v", err, tt.expectErr)
-			}
-			if !reflect.DeepEqual(result, tt.expect) {
-				t.Errorf("expect %+v, got %+v", tt.expect, result)
-			}
-		})
-	}
-}
-
-// convert string to a x509 certificate
-func getCert(certString string) *x509.Certificate {
-	block, _ := pem.Decode([]byte(certString))
-	if block == nil {
-		panic("failed to parse certificate PEM")
-	}
-
-	test, err := x509.ParseCertificate(block.Bytes)
-	if err != nil {
-		panic("failed to parse certificate: " + err.Error())
-	}
-
-	return test
-}
-
-func resetCertStore() {
-	controllers.NamespacedCertStores = &mockCertStores{}
-}