Repository: deislabs/ratify
Pull request #1429 (2024-04-30 13:53:07)

test: add e2e tests for multi-tenancy [multi-tenancy PR 12]
# Description

## What this PR does / why we need it:
This is the 12th PR for multi-tenancy support. Check the diff between PR 11 and PR 12 at: https://github.com/binbin-li/ratify/pull/145
1. Added namespace to the logger values for easier debugging. e.g. 
![image](https://github.com/deislabs/ratify/assets/6919333/2e8dc7a6-f70f-434f-8007-8c1ae17cf9ce)
2. Added constraint templates for multi-tenancy scenarios and updated all references to CT in bats files. To use multi-tenancy in Ratify, constraint template should pass keys in format: [namespace]image-reference instead of single image-reference.
3. Added a e2e test for using namespaced CRs to validate images.

## 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)
- [ ] 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

- [ ] Test A
- [ ] Test B

# 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/deislabs/ratify/pull/1429?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) Report
Attention: Patch coverage is `66.52893%` with `81 lines` in your changes are missing coverage. Please review.
> :exclamation: No coverage uploaded for pull request base (`dev@bf4eade`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#section-missing-base-commit).

> :exclamation: Current head 65dbb3a differs from pull request most recent head 26f45c9. Consider uploading reports for the commit 26f45c9 to get more accurate results

| [Files](https://app.codecov.io/gh/deislabs/ratify/pull/1429?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) | Patch % | Lines |
|---|---|---|
| [...espaceresource/keymanagementprovider\_controller.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fnamespaceresource%2Fkeymanagementprovider_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2NvbnRyb2xsZXJzL25hbWVzcGFjZXJlc291cmNlL2tleW1hbmFnZW1lbnRwcm92aWRlcl9jb250cm9sbGVyLmdv) | 35.21% | [46 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [pkg/manager/manager.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fmanager%2Fmanager.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL21hbmFnZXIvbWFuYWdlci5nbw==) | 0.00% | [18 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [...ntrollers/namespaceresource/verifier\_controller.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fnamespaceresource%2Fverifier_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2NvbnRyb2xsZXJzL25hbWVzcGFjZXJlc291cmNlL3ZlcmlmaWVyX2NvbnRyb2xsZXIuZ28=) | 80.00% | [7 Missing and 1 partial :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [...lusterresource/keymanagementprovider\_controller.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fclusterresource%2Fkeymanagementprovider_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2NvbnRyb2xsZXJzL2NsdXN0ZXJyZXNvdXJjZS9rZXltYW5hZ2VtZW50cHJvdmlkZXJfY29udHJvbGxlci5nbw==) | 40.00% | [3 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [...s/namespaceresource/certificatestore\_controller.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fnamespaceresource%2Fcertificatestore_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2NvbnRyb2xsZXJzL25hbWVzcGFjZXJlc291cmNlL2NlcnRpZmljYXRlc3RvcmVfY29udHJvbGxlci5nbw==) | 50.00% | [2 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [pkg/verifier/cosign/trustpolicy.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fverifier%2Fcosign%2Ftrustpolicy.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL3ZlcmlmaWVyL2Nvc2lnbi90cnVzdHBvbGljeS5nbw==) | 66.66% | [2 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [...controllers/clusterresource/verifier\_controller.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fclusterresource%2Fverifier_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2NvbnRyb2xsZXJzL2NsdXN0ZXJyZXNvdXJjZS92ZXJpZmllcl9jb250cm9sbGVyLmdv) | 85.71% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |
| [pkg/keymanagementprovider/keymanagementprovider.go](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&filepath=pkg%2Fkeymanagementprovider%2Fkeymanagementprovider.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs#diff-cGtnL2tleW1hbmFnZW1lbnRwcm92aWRlci9rZXltYW5hZ2VtZW50cHJvdmlkZXIuZ28=) | 87.50% | [1 Missing :warning: ](https://app.codecov.io/gh/deislabs/ratify/pull/1429?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs) |

<details><summary>Additional details and impacted files</summary>


```diff
@@          Coverage Diff           @@
##             dev    #1429   +/-   ##
======================================
  Coverage       ?   66.78%           
======================================
  Files          ?      119           
  Lines          ?     6129           
  Branches       ?        0           
======================================
  Hits           ?     4093           
  Misses         ?     1657           
  Partials       ?      379           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/deislabs/ratify/pull/1429?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=deislabs).

akashsinghal: @binbin-li cross posting discussion we were having in your fork's PR. Left another comment: https://github.com/binbin-li/ratify/pull/145/files#r1589761430
binbin-li: > @binbin-li cross posting discussion we were having in your fork's PR. Left another comment: https://github.com/binbin-li/ratify/pull/145/files#r1589761430

Following on the main PR. That's valid concern on the test failure. I'll add the basic test case covering the multi-tenancy scenario. Thanks for calling it out!
binbin-li: > > @binbin-li cross posting discussion we were having in your fork's PR. Left another comment: https://github.com/binbin-li/ratify/pull/145/files#r1589761430
> 
> Following on the main PR. That's valid concern on the test failure. I'll add the basic test case covering the multi-tenancy scenario. Thanks for calling it out!

Added a test covering notation and cosign verifiers which will cover both cert/key fetching in KMP. And we run the validation for notation and cosign separately which could avoid the testing failure.
akashsinghal: @binbin-li Side question: What is the guidance moving forward when we need to add e2e tests. Do we target clustered or namespaced scenarios or do we have to do both?
binbin-li: > @binbin-li Side question: What is the guidance moving forward when we need to add e2e tests. Do we target clustered or namespaced scenarios or do we have to do both?

good question. I think we can keep focusing on cluster-wide scenarios. But if the change involves multi-tenancy or namespace, then we should add or update namespaced tests.

Patch:
diff --git a/Makefile b/Makefile
index 70366ad..6e9f841 100644
--- a/Makefile
+++ b/Makefile
@@ -125,17 +125,17 @@ delete-ratify:
 
 .PHONY: deploy-demo-constraints
 deploy-demo-constraints:
-	kubectl apply -f ./library/default/template.yaml
-	kubectl apply -f ./library/default/samples/constraint.yaml
+	kubectl apply -f ./library/multi-tenancy-validation/template.yaml
+	kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
 
 .PHONY: delete-demo-constraints
 delete-demo-constraints:
-	kubectl delete -f ./library/default/template.yaml
-	kubectl delete -f ./library/default/samples/constraint.yaml
+	kubectl delete -f ./library/multi-tenancy-validation/template.yaml
+	kubectl delete -f ./library/multi-tenancy-validation/samples/constraint.yaml
 
 .PHONY: deploy-rego-policy
 deploy-rego-policy:
-	kubectl apply -f ./config/samples/clustered/policy/config_v1beta1_policy_rego.yaml
+	kubectl replace -f ./config/samples/clustered/policy/config_v1beta1_policy_rego.yaml
 
 .PHONY: deploy-gatekeeper
 deploy-gatekeeper:
diff --git a/config/samples/namespaced/verifier/config_v1beta1_verifier_cosign.yaml b/config/samples/namespaced/verifier/config_v1beta1_verifier_cosign.yaml
index 5de436f..dfb4597 100644
--- a/config/samples/namespaced/verifier/config_v1beta1_verifier_cosign.yaml
+++ b/config/samples/namespaced/verifier/config_v1beta1_verifier_cosign.yaml
@@ -11,4 +11,4 @@ spec:
         scopes:
           - "*"
         keys:
-          - provider: ratify-cosign-inline-key-0
\ No newline at end of file
+          - provider: default/ratify-cosign-inline-key-0
diff --git a/config/samples/namespaced/verifier/config_v1beta1_verifier_notation.yaml b/config/samples/namespaced/verifier/config_v1beta1_verifier_notation.yaml
index b20b4a8..b3c46c3 100644
--- a/config/samples/namespaced/verifier/config_v1beta1_verifier_notation.yaml
+++ b/config/samples/namespaced/verifier/config_v1beta1_verifier_notation.yaml
@@ -8,7 +8,7 @@ spec:
   parameters:
      verificationCertStores:
        certs:
-         - ratify-notation-inline-cert-0
+         - default/ratify-notation-inline-cert-0
      trustPolicyDoc:
       version: "1.0"
       trustPolicies:
diff --git a/internal/context/utils.go b/internal/context/utils.go
index 39c8ae5..1f77a87 100644
--- a/internal/context/utils.go
+++ b/internal/context/utils.go
@@ -22,16 +22,16 @@ import (
 
 type contextKey string
 
-const contextKeyNamespace = contextKey("namespace")
+const ContextKeyNamespace = contextKey("namespace")
 
 // SetContextWithNamespace embeds namespace to the context.
 func SetContextWithNamespace(ctx context.Context, namespace string) context.Context {
-	return context.WithValue(ctx, contextKeyNamespace, namespace)
+	return context.WithValue(ctx, ContextKeyNamespace, namespace)
 }
 
 // GetNamespace returns the embedded namespace from the context.
 func GetNamespace(ctx context.Context) string {
-	namespace := ctx.Value(contextKeyNamespace)
+	namespace := ctx.Value(ContextKeyNamespace)
 	if namespace == nil {
 		return ""
 	}
@@ -40,7 +40,7 @@ func GetNamespace(ctx context.Context) string {
 
 // CreateCacheKey creates a new cache key prefixed with embedded namespace.
 func CreateCacheKey(ctx context.Context, key string) string {
-	namespace := ctx.Value(contextKeyNamespace)
+	namespace := ctx.Value(ContextKeyNamespace)
 	if namespace == nil {
 		return key
 	}
diff --git a/internal/logger/logger.go b/internal/logger/logger.go
index 83b76c1..b833fa2 100644
--- a/internal/logger/logger.go
+++ b/internal/logger/logger.go
@@ -23,6 +23,7 @@ import (
 
 	logstash "github.com/bshuster-repo/logrus-logstash-hook"
 	re "github.com/deislabs/ratify/errors"
+	icontext "github.com/deislabs/ratify/internal/context"
 	dcontext "github.com/docker/distribution/context"
 	"github.com/google/uuid"
 	"github.com/sirupsen/logrus"
@@ -93,6 +94,7 @@ func InitContext(ctx context.Context, r *http.Request) context.Context {
 
 // GetLogger returns a logger with provided values.
 func GetLogger(ctx context.Context, opt Option) dcontext.Logger {
+	ctx = dcontext.WithLogger(ctx, dcontext.GetLogger(ctx, icontext.ContextKeyNamespace))
 	ctx = context.WithValue(ctx, ContextKeyComponentType, opt.ComponentType)
 	return dcontext.GetLogger(ctx, ContextKeyComponentType)
 }
diff --git a/library/multi-tenancy-validation/samples/constraint.yaml b/library/multi-tenancy-validation/samples/constraint.yaml
new file mode 100644
index 0000000..cb483c3
--- /dev/null
+++ b/library/multi-tenancy-validation/samples/constraint.yaml
@@ -0,0 +1,11 @@
+apiVersion: constraints.gatekeeper.sh/v1beta1
+kind: RatifyVerification
+metadata:
+  name: ratify-constraint
+spec:
+  enforcementAction: deny
+  match:
+    kinds:
+      - apiGroups: [""]
+        kinds: ["Pod"]
+    namespaces: ["default", "new-namespace"]
diff --git a/library/multi-tenancy-validation/template.yaml b/library/multi-tenancy-validation/template.yaml
new file mode 100644
index 0000000..425de64
--- /dev/null
+++ b/library/multi-tenancy-validation/template.yaml
@@ -0,0 +1,48 @@
+apiVersion: templates.gatekeeper.sh/v1beta1
+kind: ConstraintTemplate
+metadata:
+  name: ratifyverification
+spec:
+  crd:
+    spec:
+      names:
+        kind: RatifyVerification
+  targets:
+    - target: admission.k8s.gatekeeper.sh
+      rego: |
+        package ratifyverification
+
+        # Get data from Ratify
+        remote_data := response {
+          images := [img | img = concat("", ["[",input.review.object.metadata.namespace,"]",input.review.object.spec.containers[_].image])]
+          images_init := [img | img = concat("", ["[",input.review.object.metadata.namespace,"]",input.review.object.spec.initContainers[_].image])]
+          images_ephemeral := [img | img = concat("", ["[",input.review.object.metadata.namespace,"]",input.review.object.spec.ephemeralContainers[_].image])]
+          other_images := array.concat(images_init, images_ephemeral)
+          all_images := array.concat(other_images, images)
+          response := external_data({"provider": "ratify-provider", "keys": all_images})
+        }
+
+        # Base Gatekeeper violation
+        violation[{"msg": msg}] {
+          general_violation[{"result": msg}]
+        }
+
+        # Check if there are any system errors
+        general_violation[{"result": result}] {
+          err := remote_data.system_error
+          err != ""
+          result := sprintf("System error calling external data provider: %s", [err])
+        }
+
+        # Check if there are errors for any of the images
+        general_violation[{"result": result}] {
+          count(remote_data.errors) > 0
+          result := sprintf("Error validating one or more images: %s", remote_data.errors)
+        }
+
+        # Check if the success criteria is true
+        general_violation[{"result": result}] {
+          subject_validation := remote_data.responses[_]
+          subject_validation[1].isSuccess == false
+          result := sprintf("Subject failed verification: %s", [subject_validation[0]])
+        }


Test patch:
diff --git a/internal/context/utils_test.go b/internal/context/utils_test.go
index 1b2d94a..8a52faf 100644
--- a/internal/context/utils_test.go
+++ b/internal/context/utils_test.go
@@ -28,7 +28,7 @@ const (
 func TestSetContext(t *testing.T) {
 	ctx := context.Background()
 	ctx = SetContextWithNamespace(ctx, testNamespace)
-	namespace := ctx.Value(contextKeyNamespace).(string)
+	namespace := ctx.Value(ContextKeyNamespace).(string)
 	if namespace != testNamespace {
 		t.Fatalf("expected namespace %s, got %s", testNamespace, namespace)
 	}
diff --git a/test/bats/azure-test.bats b/test/bats/azure-test.bats
index 1a4f941..bde2056 100644
--- a/test/bats/azure-test.bats
+++ b/test/bats/azure-test.bats
@@ -24,7 +24,7 @@ SLEEP_TIME=1
 
     # ensure that the chart deployment is reset to a clean state for other tests
     teardown() {
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-dynamic --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-dynamic --ignore-not-found=true'
         pod=$(kubectl -n gatekeeper-system get pod -l=app.kubernetes.io/name=ratify --sort-by=.metadata.creationTimestamp -o=name | tail -n 1)
         helm upgrade --atomic --namespace gatekeeper-system --reuse-values --set featureFlags.RATIFY_EXPERIMENTAL_DYNAMIC_PLUGINS=false ratify ./charts/ratify
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl -n gatekeeper-system delete $pod --force --grace-period=0'
@@ -54,9 +54,9 @@ SLEEP_TIME=1
     }
 
     # configure the default template/constraint
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
 
     # verify that the image can be run with a root cert, root verification cert should have been configured on deployment
@@ -87,10 +87,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo1 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run demo --namespace default --image=${TEST_REGISTRY}/notation:signed
@@ -106,10 +106,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl apply -f ./test/bats/tests/config/config_v1beta1_verifier_cosign_akv.yaml
@@ -127,13 +127,13 @@ SLEEP_TIME=1
         echo "cleaning up"
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod license-checker --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod license-checker2 --namespace default --force --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -156,10 +156,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod sbom2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -179,17 +179,17 @@ SLEEP_TIME=1
 @test "schemavalidator verifier test" {
     teardown() {
         echo "cleaning up"
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --namespace default --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-sbom --namespace default --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-schemavalidator --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-sbom --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-schemavalidator --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod schemavalidator --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod schemavalidator2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -209,17 +209,17 @@ SLEEP_TIME=1
 @test "sbom/notary/cosign/licensechecker/schemavalidator verifiers test" {
     teardown() {
         echo "cleaning up"
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --namespace default --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-sbom --namespace default --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-schemavalidator --namespace default --ignore-not-found=true'
-        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-cosign --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-sbom --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-schemavalidator --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-cosign --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod all-in-one --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -262,23 +262,23 @@ SLEEP_TIME=1
 
 @test "configmap update test" {
     skip "Skipping test for now as we are no longer watching for configfile update in a K8s environment.This test ensures we are watching config file updates in a non-kub scenario"
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run demo2 --image=${TEST_REGISTRY}/notation:signed
     assert_success
 
     run kubectl get configmaps ratify-configuration --namespace=gatekeeper-system -o yaml >currentConfig.yaml
-    run kubectl delete -f ./library/default/samples/constraint.yaml
+    run kubectl delete -f ./library/multi-tenancy-validation/samples/constraint.yaml
 
     wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl replace --namespace=gatekeeper-system -f ${BATS_TESTS_DIR}/configmap/invalidconfigmap.yaml"
     echo "Waiting for 150 second for configuration update"
     sleep 150
 
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     run kubectl run demo3 --image=${TEST_REGISTRY}/notation:signed
     echo "Current time after validate : $(date +"%T")"
@@ -307,10 +307,10 @@ SLEEP_TIME=1
         echo "cleaning up"
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod mutate-demo --namespace default --ignore-not-found=true'
     }
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run mutate-demo --namespace default --image=${TEST_REGISTRY}/notation:signed
diff --git a/test/bats/base-test.bats b/test/bats/base-test.bats
index 4d19476..11d6ed5 100644
--- a/test/bats/base-test.bats
+++ b/test/bats/base-test.bats
@@ -28,10 +28,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod initcontainer-pod --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod initcontainer-pod1 --namespace default --force --ignore-not-found=true'
     }
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     # validate key management provider status property shows success
@@ -45,7 +45,7 @@ RATIFY_NAMESPACE=gatekeeper-system
     # validate initContainers image
     run kubectl apply -f ./test/testdata/pod_initContainers_signed.yaml --namespace default
     assert_success
-    
+
     run kubectl apply -f ./test/testdata/pod_initContainers_unsigned.yaml --namespace default
     assert_failure
 
@@ -79,10 +79,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo1 --namespace default --force --ignore-not-found=true'
     }
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -97,47 +97,56 @@ RATIFY_NAMESPACE=gatekeeper-system
 }
 
 @test "notation test with certs across namespace" {
-    skip "cluster-wide verifiers cannot access KMPs in specific namespace, need to add another test for namespaced verifiers accessing namespaced KMPs once we support multi-tenancy"
     teardown() {
         echo "cleaning up"
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo1 --namespace default --force --ignore-not-found=true'
-        
+
         # restore cert store in ratify namespace
-        run bash -c "kubectl get keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0 -o yaml > kmprovider.yaml"
-        run kubectl delete keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0
-        sed 's/default/gatekeeper-system/' kmprovider.yaml > kmproviderNewNS.yaml
-        run kubectl apply -f kmproviderNewNS.yaml        
+        run kubectl apply -f clusterkmprovider.yaml
         assert_success
 
         # restore the original notation verifier for other tests
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_notation.yaml'
+
+        # delete new namespace
+        run kubectl delete namespace new-namespace
+        assert_success
     }
-    run kubectl apply -f ./library/default/template.yaml
+
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
-
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
-    
-    # apply the key management provider to default namespace
-    run bash -c "kubectl get keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0 -o yaml > kmprovider.yaml"    
+
+    # create a new namespace.
+    run kubectl create namespace new-namespace
     assert_success
-    sed 's/gatekeeper-system/default/' kmprovider.yaml > kmproviderNewNS.yaml    
-    run kubectl apply -f kmproviderNewNS.yaml
+    sleep 3
+
+    # apply the key management provider to new namespace
+    run bash -c "kubectl get keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0 -o yaml > clusterkmprovider.yaml"
     assert_success
+    sed 's/KeyManagementProvider/NamespacedKeyManagementProvider/' clusterkmprovider.yaml >namespacedkmprovider.yaml
+    run kubectl apply -f namespacedkmprovider.yaml -n new-namespace
+    assert_success
+
+    # delete the cluster-wide key management provider
     run kubectl delete keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0
     assert_success
-    
-    # configure the notation verifier to use inline certificate store with specific namespace
-    run kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_notation_specificnskmprovider.yaml
+
+    # configure the notation verifier to use inline certificate store in new namespace.
+    sed 's/default\//new-namespace\//' ./config/samples/clustered/verifier/config_v1beta1_verifier_notation_specificnskmprovider.yaml >verifier-new-namespace.yaml
+    run kubectl apply -f verifier-new-namespace.yaml
     assert_success
+    sleep 3
 
-    run kubectl run demo --namespace default --image=registry:5000/notation:signed
+    run kubectl run demo --namespace new-namespace --image=registry:5000/notation:signed
     assert_success
 
-    run kubectl run demo1 --namespace default --image=registry:5000/notation:unsigned
+    run kubectl run demo1 --namespace new-namespace --image=registry:5000/notation:unsigned
     assert_failure
 }
 
@@ -147,10 +156,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo-key --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo-unsigned --namespace default --force --ignore-not-found=true'
     }
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -172,10 +181,10 @@ RATIFY_NAMESPACE=gatekeeper-system
     run kubectl replace -f ./config/samples/clustered/verifier/config_v1beta1_verifier_cosign_legacy.yaml
     sleep 5
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -243,7 +252,7 @@ RATIFY_NAMESPACE=gatekeeper-system
     assert_success
 
     # apply a invalid verifier CR, validate status with error
-    sed 's/licensechecker/invalidlicensechecker/' ./config/samples/clustered/verifier/config_v1beta1_verifier_complete_licensechecker.yaml > invalidVerifier.yaml
+    sed 's/licensechecker/invalidlicensechecker/' ./config/samples/clustered/verifier/config_v1beta1_verifier_complete_licensechecker.yaml >invalidVerifier.yaml
     run kubectl apply -f invalidVerifier.yaml
     assert_success
     run bash -c "kubectl describe verifiers.config.ratify.deislabs.io/verifier-license-checker -n ${RATIFY_NAMESPACE} | grep 'Brieferror:  Original Error:'"
@@ -265,7 +274,7 @@ RATIFY_NAMESPACE=gatekeeper-system
     }
 
     # apply a invalid verifier CR, validate status with error
-    sed 's/:v1/:invalid/' ./config/samples/clustered/store/config_v1beta1_store_dynamic.yaml > invalidstore.yaml
+    sed 's/:v1/:invalid/' ./config/samples/clustered/store/config_v1beta1_store_dynamic.yaml >invalidstore.yaml
     run kubectl apply -f invalidstore.yaml
     assert_success
     # wait for download of image
@@ -276,23 +285,23 @@ RATIFY_NAMESPACE=gatekeeper-system
 
 @test "configmap update test" {
     skip "Skipping test for now as we are no longer watching for configfile update in a K8s environment. This test ensures we are watching config file updates in a non-kub scenario"
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run demo2 --image=registry:5000/notation:signed
     assert_success
 
     run kubectl get configmaps ratify-configuration --namespace=${RATIFY_NAMESPACE} -o yaml >currentConfig.yaml
-    run kubectl delete -f ./library/default/samples/constraint.yaml
+    run kubectl delete -f ./library/multi-tenancy-validation/samples/constraint.yaml
 
     wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl replace --namespace=${RATIFY_NAMESPACE} -f ${BATS_TESTS_DIR}/configmap/invalidconfigmap.yaml"
     echo "Waiting for 150 second for configuration update"
     sleep 150
 
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     run kubectl run demo3 --image=registry:5000/notation:signed
     echo "Current time after validate : $(date +"%T")"
@@ -307,10 +316,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod mutate-demo --namespace default --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run mutate-demo --namespace default --image=registry:5000/notation:signed
@@ -372,9 +381,9 @@ RATIFY_NAMESPACE=gatekeeper-system
     }
 
     # configure the default template/constraint
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
 
     # verify that the image cannot be run due to an invalid cert
@@ -408,10 +417,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo1 --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete certificatestores.config.ratify.deislabs.io/ratify-notation-inline-cert-0 --namespace ${RATIFY_NAMESPACE} --ignore-not-found=true'
     }
-     # configure the default template/constraint
-    run kubectl apply -f ./library/default/template.yaml
+    # configure the default template/constraint
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
 
     # validate key management provider status property shows success
@@ -422,7 +431,7 @@ RATIFY_NAMESPACE=gatekeeper-system
 
     sleep 10
 
-    # apply an invalid cert in an inline certificate store 
+    # apply an invalid cert in an inline certificate store
     run kubectl apply -f ./test/bats/tests/config/config_v1beta1_certstore_inline_invalid.yaml -n ${RATIFY_NAMESPACE}
     assert_success
     # validate key management provider status property shows success
@@ -442,10 +451,10 @@ RATIFY_NAMESPACE=gatekeeper-system
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl replace -f ./config/samples/clustered/store/config_v1beta1_store_oras_http.yaml'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     # apply store CRD with K8s secret auth provier enabled
@@ -469,9 +478,9 @@ RATIFY_NAMESPACE=gatekeeper-system
     }
 
     # configure the default template/constraint
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
 
     # add the root certificate as an inline key management provider
@@ -520,12 +529,81 @@ RATIFY_NAMESPACE=gatekeeper-system
     sleep 100
 
     # verify that the verification succeeds
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl run demo --namespace default --image=registry:5000/notation:signed
     assert_success
 }
+
+@test "namespaced notation/cosign verifiers test" {
+    teardown() {
+        echo "cleaning up"
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete namespacedverifiers.config.ratify.deislabs.io/verifier-cosign --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete namespacedverifiers.config.ratify.deislabs.io/verifier-notation --namespace default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_notation.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_cosign.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete namespacedkeymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0 -n default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f clusternotationkmprovider.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete namespacedkeymanagementproviders.config.ratify.deislabs.io/ratify-cosign-inline-key-0 -n default --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f clustercosignkmprovider.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete namespacedpolicies.config.ratify.deislabs.io/ratify-policy --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl apply -f clusterpolicy.yaml'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod notation-demo --namespace default --force --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod notation-demo1 --namespace default --force --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo-key --namespace default --force --ignore-not-found=true'
+        wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod cosign-demo-unsigned --namespace default --force --ignore-not-found=true'
+    }
+
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
+    sleep 3
+
+    # apply namespaced policy and delete cluster-wide policy.
+    run bash -c "kubectl get policies.config.ratify.deislabs.io/ratify-policy -o yaml > clusterpolicy.yaml"
+    assert_success
+    sed 's/kind: Policy/kind: NamespacedPolicy/;/^\s*resourceVersion:/d' clusterpolicy.yaml >namespacedpolicy.yaml
+    run kubectl apply -f namespacedpolicy.yaml
+    assert_success
+
+    # apply namespaced kmp and delete cluster-wide kmp.
+    run bash -c "kubectl get keymanagementproviders.config.ratify.deislabs.io/ratify-notation-inline-cert-0 -o yaml > clusternotationkmprovider.yaml"
+    assert_success
+    sed 's/KeyManagementProvider/NamespacedKeyManagementProvider/' clusternotationkmprovider.yaml >namespacednotationkmprovider.yaml
+    run kubectl apply -f namespacednotationkmprovider.yaml
+    assert_success
+
+    run bash -c "kubectl get keymanagementproviders.config.ratify.deislabs.io/ratify-cosign-inline-key-0 -o yaml > clustercosignkmprovider.yaml"
+    assert_success
+    sed 's/KeyManagementProvider/NamespacedKeyManagementProvider/;/^\s*resourceVersion:/d' clustercosignkmprovider.yaml >namespacedcosignkmprovider.yaml
+    run kubectl delete namespacedkeymanagementproviders.config.ratify.deislabs.io/ratify-cosign-inline-key-0 -n default --ignore-not-found=true
+    sleep 5
+    run kubectl apply -f namespacedcosignkmprovider.yaml
+    assert_success
+    sleep 5
+
+    # apply namespaced notation verifiers and delete cluster-wide notation verifiers.
+    run kubectl apply -f ./config/samples/namespaced/verifier/config_v1beta1_verifier_notation.yaml
+    run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notation --ignore-not-found=true
+
+    # validate notation images.
+    run kubectl run notation-demo --namespace default --image=registry:5000/notation:signed
+    assert_success
+
+    run kubectl run notation-demo1 --namespace default --image=registry:5000/notation:unsigned
+    assert_failure
+
+    # apply namespaced cosign verifiers and delete cluster-wide cosign verifiers.
+    run kubectl apply -f ./config/samples/namespaced/verifier/config_v1beta1_verifier_cosign.yaml
+    run kubectl delete verifiers.config.ratify.deislabs.io/verifier-cosign --ignore-not-found=true
+
+    # validate cosign images.
+    run kubectl run cosign-demo-key --namespace default --image=registry:5000/cosign:signed-key
+    assert_success
+
+    run kubectl run cosign-demo-unsigned --namespace default --image=registry:5000/cosign:unsigned
+    assert_failure
+}
diff --git a/test/bats/high-availability.bats b/test/bats/high-availability.bats
index cf6d246..a175019 100644
--- a/test/bats/high-availability.bats
+++ b/test/bats/high-availability.bats
@@ -25,10 +25,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo --namespace default --force --ignore-not-found=true'
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod demo2 --namespace default --force --ignore-not-found=true'
     }
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     # validate key management provider status property shows success
diff --git a/test/bats/plugin-test.bats b/test/bats/plugin-test.bats
index 233da79..a44edc6 100644
--- a/test/bats/plugin-test.bats
+++ b/test/bats/plugin-test.bats
@@ -67,10 +67,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete verifiers.config.ratify.deislabs.io/verifier-license-checker --namespace default --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
     run kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_partial_licensechecker.yaml
@@ -92,10 +92,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod sbom2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -103,7 +103,7 @@ SLEEP_TIME=1
     sleep 5
     run kubectl run sbom --namespace default --image=registry:5000/sbom:v0
     assert_failure
-   
+
     run kubectl apply -f ./config/samples/clustered/verifier/config_v1beta1_verifier_sbom.yaml
     # wait for the httpserver cache to be invalidated
     sleep 15
@@ -129,10 +129,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod schemavalidator2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -157,10 +157,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod vulnerabilityreport2 --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
@@ -185,10 +185,10 @@ SLEEP_TIME=1
         wait_for_process ${WAIT_TIME} ${SLEEP_TIME} 'kubectl delete pod all-in-one --namespace default --force --ignore-not-found=true'
     }
 
-    run kubectl apply -f ./library/default/template.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/template.yaml
     assert_success
     sleep 5
-    run kubectl apply -f ./library/default/samples/constraint.yaml
+    run kubectl apply -f ./library/multi-tenancy-validation/samples/constraint.yaml
     assert_success
     sleep 5
 
diff --git a/test/bats/tests/config/config_v1beta1_verifier_cosign_akv.yaml b/test/bats/tests/config/config_v1beta1_verifier_cosign_akv.yaml
index fe1d9ef..a2ca0bd 100644
--- a/test/bats/tests/config/config_v1beta1_verifier_cosign_akv.yaml
+++ b/test/bats/tests/config/config_v1beta1_verifier_cosign_akv.yaml
@@ -15,4 +15,4 @@ spec:
         scopes:
           - "*"
         keys:
-          - provider: gatekeeper-system/kmprovider-akv
\ No newline at end of file
+          - provider: kmprovider-akv
\ No newline at end of file