Repository: ratify-project/ratify
Pull request #1804 (2024-09-13 02:43:19)

chore: prepare for release 1.3.0
# Description

## What this PR does / why we need it:
<!--Please include a summary of the changes and relevant context. -->

## 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)*:
Cut dev branch for release 1.3.0

## 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`



Patch:
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index 0af3612..804ea6a 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -15,7 +15,7 @@ jobs:
     uses: ./.github/workflows/e2e-cli.yml
     secrets:
       CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
-   
+
   call_test_e2e_basic:
     name: "run e2e on basic matrix"
     if: ${{ ! (contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'workflow_dispatch') }}
@@ -25,8 +25,8 @@ jobs:
       fail-fast: false
       matrix:
         KUBERNETES_VERSION: ["1.29.2"]
-        GATEKEEPER_VERSION: ["3.16.0"]
-    uses: ./.github/workflows/e2e-k8s.yml 
+        GATEKEEPER_VERSION: ["3.17.0"]
+    uses: ./.github/workflows/e2e-k8s.yml
     with:
       k8s_version: ${{ matrix.KUBERNETES_VERSION }}
       gatekeeper_version: ${{ matrix.GATEKEEPER_VERSION }}
@@ -38,11 +38,11 @@ jobs:
       fail-fast: false
       matrix:
         KUBERNETES_VERSION: ["1.28.12", "1.29.2"]
-        GATEKEEPER_VERSION: ["3.14.0", "3.15.0", "3.16.0"]
-    uses: ./.github/workflows/e2e-k8s.yml 
+        GATEKEEPER_VERSION: ["3.15.0", "3.16.0", "3.17.0"]
+    uses: ./.github/workflows/e2e-k8s.yml
     with:
       k8s_version: ${{ matrix.KUBERNETES_VERSION }}
-      gatekeeper_version: ${{ matrix.GATEKEEPER_VERSION }} 
+      gatekeeper_version: ${{ matrix.GATEKEEPER_VERSION }}
 
   build_test_aks_e2e_conditional:
     name: "Build and run e2e Test on AKS with conditions"
@@ -54,15 +54,15 @@ jobs:
       fail-fast: false
       matrix:
         KUBERNETES_VERSION: ["1.28.12", "1.29.2"]
-        GATEKEEPER_VERSION: ["3.14.0", "3.15.0", "3.16.0"]
+        GATEKEEPER_VERSION: ["3.15.0", "3.16.0", "3.17.0"]
     uses: ./.github/workflows/e2e-aks.yml
     with:
       k8s_version: ${{ matrix.KUBERNETES_VERSION }}
       gatekeeper_version: ${{ matrix.GATEKEEPER_VERSION }}
     secrets: inherit
-  
+
   aks-test-cleanup:
-    needs: ['build_test_aks_e2e_conditional']
+    needs: ["build_test_aks_e2e_conditional"]
     runs-on: ubuntu-latest
     permissions:
       id-token: write
@@ -70,7 +70,7 @@ jobs:
     environment: azure-test
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -79,7 +79,7 @@ jobs:
       - name: Set up Go 1.22
         uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
 
       - name: Az CLI login
         uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
@@ -90,4 +90,4 @@ jobs:
 
       - name: clean up
         run: |
-          make e2e-cleanup AZURE_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}
\ No newline at end of file
+          make e2e-cleanup AZURE_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}
diff --git a/.github/workflows/cache-cleanup.yml b/.github/workflows/cache-cleanup.yml
index 5fbb3d0..46042f7 100644
--- a/.github/workflows/cache-cleanup.yml
+++ b/.github/workflows/cache-cleanup.yml
@@ -10,16 +10,16 @@ permissions:
 jobs:
   cleanup:
     runs-on: ubuntu-latest
-    steps:      
+    steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
       - name: Cleanup
         run: |
           gh extension install actions/gh-actions-cache
-          
+
           echo "Fetching list of cache key"
           cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
 
@@ -34,4 +34,4 @@ jobs:
         env:
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           REPO: ${{ github.repository }}
-          BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
\ No newline at end of file
+          BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
diff --git a/.github/workflows/clean-dev-package.yml b/.github/workflows/clean-dev-package.yml
index 98cc5cf..0a53bd8 100644
--- a/.github/workflows/clean-dev-package.yml
+++ b/.github/workflows/clean-dev-package.yml
@@ -10,24 +10,24 @@ jobs:
   cleanup-packages:
     runs-on: ubuntu-latest
     permissions:
-        packages: write
+      packages: write
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
       - name: Clean up ratify-crds-dev
         uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
-        with: 
-          package-name: 'ratify-crds-dev'
-          package-type: 'container'
+        with:
+          package-name: "ratify-crds-dev"
+          package-type: "container"
           min-versions-to-keep: 7
           delete-only-pre-release-versions: "true"
       - name: Clean up ratify-dev
         uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
-        with: 
-          package-name: 'ratify-dev'
-          package-type: 'container'
+        with:
+          package-name: "ratify-dev"
+          package-type: "container"
           min-versions-to-keep: 7
-          delete-only-pre-release-versions: "true"
\ No newline at end of file
+          delete-only-pre-release-versions: "true"
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 82ddd78..fe0ac83 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -1,19 +1,18 @@
-
 name: "CodeQL Scan"
 
 on:
   push:
-    branches: 
+    branches:
       - main
       - dev
       - 1.0.0*
   pull_request:
-    branches: 
+    branches:
       - main
       - dev
       - 1.0.0*
   schedule:
-    - cron: '30 1 * * 0'
+    - cron: "30 1 * * 0"
   workflow_dispatch:
 
 permissions: read-all
@@ -27,7 +26,7 @@ jobs:
 
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index dd5bec5..cb827af 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -15,13 +15,13 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
       - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
       - name: golangci-lint
         uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0
diff --git a/.github/workflows/high-availability.yml b/.github/workflows/high-availability.yml
index e711f94..631f9bb 100644
--- a/.github/workflows/high-availability.yml
+++ b/.github/workflows/high-availability.yml
@@ -30,7 +30,7 @@ jobs:
         DAPR_VERSION: ["1.13.2"]
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -39,7 +39,7 @@ jobs:
       - name: Set up Go 1.22
         uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
 
       - name: Bootstrap e2e
         run: |
diff --git a/.github/workflows/pr-to-main.yml b/.github/workflows/pr-to-main.yml
index 3aecd8b..5fcefe2 100644
--- a/.github/workflows/pr-to-main.yml
+++ b/.github/workflows/pr-to-main.yml
@@ -2,7 +2,7 @@ name: pr_to_main
 
 on:
   schedule:
-    - cron: '30 8 * * 0'  # early morning (08:30 UTC) every Sunday
+    - cron: "30 8 * * 0" # early morning (08:30 UTC) every Sunday
   workflow_dispatch:
 
 permissions:
@@ -13,7 +13,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/publish-charts.yml b/.github/workflows/publish-charts.yml
index cfb5789..8508387 100644
--- a/.github/workflows/publish-charts.yml
+++ b/.github/workflows/publish-charts.yml
@@ -13,7 +13,7 @@ jobs:
       contents: write
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -21,4 +21,4 @@ jobs:
       - name: Publish Helm charts
         uses: stefanprodan/helm-gh-pages@0ad2bb377311d61ac04ad9eb6f252fb68e207260 # v1.7.0
         with:
-          token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+          token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/publish-cosign-sample.yml b/.github/workflows/publish-cosign-sample.yml
index 925284a..566c278 100644
--- a/.github/workflows/publish-cosign-sample.yml
+++ b/.github/workflows/publish-cosign-sample.yml
@@ -1,11 +1,11 @@
 name: publish-cosign-sample
 
-on: 
+on:
   workflow_dispatch:
-   
+
 env:
   REGISTRY: ghcr.io
-  
+
 permissions:
   contents: read
 
@@ -18,9 +18,9 @@ jobs:
       contents: write
       packages: write
       id-token: write
-    steps:            
+    steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -28,7 +28,7 @@ jobs:
         uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0
 
       - name: Get repo
-        run: |          
+        run: |
           echo "REPOSITORY=${{ env.REGISTRY }}/${{ github.repository }}" >> $GITHUB_ENV
 
       - name: Write signing key to disk
diff --git a/.github/workflows/publish-dev-assets.yml b/.github/workflows/publish-dev-assets.yml
index c5dc1ef..c64a243 100644
--- a/.github/workflows/publish-dev-assets.yml
+++ b/.github/workflows/publish-dev-assets.yml
@@ -2,7 +2,7 @@ name: publish-dev-assets
 
 on:
   schedule:
-    - cron: '30 8 * * 0'  # early morning (08:30 UTC) every Sunday
+    - cron: "30 8 * * 0" # early morning (08:30 UTC) every Sunday
   workflow_dispatch:
 
 permissions: read-all
@@ -17,7 +17,7 @@ jobs:
     environment: azure-publish
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
       - name: Checkout
@@ -108,11 +108,11 @@ jobs:
         run: |
           sed -i '/^  repository:/c\  repository: ghcr.io/ratify-project/ratify-dev' charts/ratify/values.yaml
           sed -i '/^  crdRepository:/c\  crdRepository: ghcr.io/ratify-project/ratify-crds-dev' charts/ratify/values.yaml
-          sed -i '/^  tag:/c\  tag: ${{ steps.prepare.outputs.version }}' charts/ratify/values.yaml 
+          sed -i '/^  tag:/c\  tag: ${{ steps.prepare.outputs.version }}' charts/ratify/values.yaml
       - name: helm package
         run: |
-            helm package ./charts/ratify --version ${{ steps.prepare.outputs.semversion }}
-            helm package ./charts/ratify --version ${{ steps.prepare.outputs.semversionrolling }}
+          helm package ./charts/ratify --version ${{ steps.prepare.outputs.semversion }}
+          helm package ./charts/ratify --version ${{ steps.prepare.outputs.semversionrolling }}
       - name: helm push
         run: |
           helm push ratify-${{ steps.prepare.outputs.semversion }}.tgz oci://${{ steps.prepare.outputs.chartrepo }}
diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml
index 32a893d..e4d81f9 100644
--- a/.github/workflows/publish-package.yml
+++ b/.github/workflows/publish-package.yml
@@ -16,7 +16,7 @@ jobs:
       contents: read
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
       - name: Checkout
diff --git a/.github/workflows/publish-sample.yml b/.github/workflows/publish-sample.yml
index b21e884..5298179 100644
--- a/.github/workflows/publish-sample.yml
+++ b/.github/workflows/publish-sample.yml
@@ -1,11 +1,11 @@
 name: publish-sample
 
-on: 
- workflow_dispatch:
+on:
+  workflow_dispatch:
 
 env:
   REGISTRY: ghcr.io
-  
+
 permissions:
   contents: read
 
@@ -17,14 +17,14 @@ jobs:
     permissions:
       contents: write
       packages: write
-    steps:            
+    steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
       - name: Get repo
-        run: |          
+        run: |
           echo "REPOSITORY=${{ env.REGISTRY }}/${{ github.repository }}" >> $GITHUB_ENV
 
       - name: Log in to the GHCR
@@ -35,9 +35,7 @@ jobs:
           password: ${{ secrets.GITHUB_TOKEN }}
 
       - name: Copy signed sample test image
-        run: 
-          oras cp -r wabbitnetworks.azurecr.io/ratify/notary-image:signed ${REPOSITORY}/notary-image:signed
+        run: oras cp -r wabbitnetworks.azurecr.io/ratify/notary-image:signed ${REPOSITORY}/notary-image:signed
 
-      - name: Copy unsigned sample test image 
-        run: 
-          oras cp wabbitnetworks.azurecr.io/ratify/notary-image:unsigned ${REPOSITORY}/notary-image:unsigned
+      - name: Copy unsigned sample test image
+        run: oras cp wabbitnetworks.azurecr.io/ratify/notary-image:unsigned ${REPOSITORY}/notary-image:unsigned
diff --git a/.github/workflows/quick-start.yml b/.github/workflows/quick-start.yml
index 6e26af5..f6739f2 100644
--- a/.github/workflows/quick-start.yml
+++ b/.github/workflows/quick-start.yml
@@ -30,7 +30,7 @@ jobs:
         KUBERNETES_VERSION: ["1.29.2"]
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 13f9185..e261c1b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -3,7 +3,7 @@ name: Release Ratify
 on:
   push:
     tags:
-      - 'v*'
+      - "v*"
   workflow_dispatch:
 
 permissions: read-all
@@ -15,41 +15,41 @@ jobs:
     permissions:
       contents: write
     steps:
-    - name: Harden Runner
-      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
-      with:
-        egress-policy: audit
-
-    - name: Checkout
-      uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # tag=3.0.2
-      with:
+      - name: Harden Runner
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        with:
+          egress-policy: audit
+
+      - name: Checkout
+        uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # tag=3.0.2
+        with:
           fetch-depth: 0
-    
-    - name: Install Syft
-      uses: anchore/sbom-action/download-syft@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.17.2
-          
-    - name: Set up Go
-      uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
-      with:
-        go-version: '1.22'
-
-    - name: Goreleaser
-      id: goreleaser
-      uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
-      with:
-        version: '2.0.1'
-        args: release --clean
-      env:
+
+      - name: Install Syft
+        uses: anchore/sbom-action/download-syft@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.17.2
+
+      - name: Set up Go
+        uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
+        with:
+          go-version: "1.22"
+
+      - name: Goreleaser
+        id: goreleaser
+        uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
+        with:
+          version: "2.0.1"
+          args: release --clean
+        env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
-    - name: Generate SBOM
-      run: |
-        curl -Lo $RUNNER_TEMP/sbom-tool https://github.com/microsoft/sbom-tool/releases/latest/download/sbom-tool-linux-x64
-        chmod +x $RUNNER_TEMP/sbom-tool
-        $RUNNER_TEMP/sbom-tool generate -b . -bc . -pn ratify -pv $GITHUB_REF_NAME -ps Microsoft -nsb https://microsoft.com -V Verbose
-
-    - name: Upload a Build Artifact
-      uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # tag=v4.4.0
-      with:
-        name: SBOM SPDX files
-        path: _manifest/spdx_2.2/**
+      - name: Generate SBOM
+        run: |
+          curl -Lo $RUNNER_TEMP/sbom-tool https://github.com/microsoft/sbom-tool/releases/latest/download/sbom-tool-linux-x64
+          chmod +x $RUNNER_TEMP/sbom-tool
+          $RUNNER_TEMP/sbom-tool generate -b . -bc . -pn ratify -pv $GITHUB_REF_NAME -ps Microsoft -nsb https://microsoft.com -V Verbose
+
+      - name: Upload a Build Artifact
+        uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # tag=v4.4.0
+        with:
+          name: SBOM SPDX files
+          path: _manifest/spdx_2.2/**
diff --git a/.github/workflows/run-full-validation.yml b/.github/workflows/run-full-validation.yml
index 71db17f..3f2464c 100644
--- a/.github/workflows/run-full-validation.yml
+++ b/.github/workflows/run-full-validation.yml
@@ -27,8 +27,8 @@ jobs:
       fail-fast: false
       matrix:
         KUBERNETES_VERSION: ["1.28.12", "1.29.2"]
-        GATEKEEPER_VERSION: ["3.14.0", "3.15.0", "3.16.0"]
-    uses: ./.github/workflows/e2e-k8s.yml 
+        GATEKEEPER_VERSION: ["3.15.0", "3.16.0", "3.17.0"]
+    uses: ./.github/workflows/e2e-k8s.yml
     with:
       k8s_version: ${{ matrix.KUBERNETES_VERSION }}
       gatekeeper_version: ${{ matrix.GATEKEEPER_VERSION }}
@@ -42,7 +42,7 @@ jobs:
       fail-fast: false
       matrix:
         KUBERNETES_VERSION: ["1.28.12", "1.29.2"]
-        GATEKEEPER_VERSION: ["3.14.0", "3.15.0", "3.16.0"]
+        GATEKEEPER_VERSION: ["3.15.0", "3.16.0", "3.17.0"]
     uses: ./.github/workflows/e2e-aks.yml
     with:
       k8s_version: ${{ matrix.KUBERNETES_VERSION }}
@@ -50,7 +50,7 @@ jobs:
     secrets: inherit
 
   aks-test-cleanup:
-    needs: ['build_test_aks_e2e']
+    needs: ["build_test_aks_e2e"]
     runs-on: ubuntu-latest
     permissions:
       id-token: write
@@ -58,7 +58,7 @@ jobs:
     environment: azure-test
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -67,7 +67,7 @@ jobs:
       - name: Set up Go 1.22
         uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
 
       - name: Az CLI login
         uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
@@ -78,4 +78,4 @@ jobs:
 
       - name: clean up
         run: |
-          make e2e-cleanup AZURE_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}
\ No newline at end of file
+          make e2e-cleanup AZURE_SUBSCRIPTION_ID=${{ secrets.AZURE_SUBSCRIPTION_ID }}
diff --git a/.github/workflows/scan-vulns.yaml b/.github/workflows/scan-vulns.yaml
index 7c0ff23..aed9bba 100644
--- a/.github/workflows/scan-vulns.yaml
+++ b/.github/workflows/scan-vulns.yaml
@@ -11,7 +11,7 @@ on:
       - "library/**"
       - "**.md"
   schedule:
-    - cron: '30 8 * * 0'  # early morning (08:30 UTC) every Sunday
+    - cron: "30 8 * * 0" # early morning (08:30 UTC) every Sunday
   workflow_dispatch:
 
 permissions: read-all
@@ -23,7 +23,7 @@ jobs:
     timeout-minutes: 15
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -39,7 +39,7 @@ jobs:
     timeout-minutes: 15
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 970cd11..96efefe 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -3,7 +3,7 @@ on:
   branch_protection_rule:
   schedule:
     # Weekly on Saturdays.
-    - cron: '30 1 * * 6'
+    - cron: "30 1 * * 6"
   push:
     branches:
       - main
@@ -27,10 +27,10 @@ jobs:
       id-token: write
       actions: read
       contents: read
-    
+
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -53,7 +53,7 @@ jobs:
           name: SARIF file
           path: results.sarif
           retention-days: 5
-      
+
       - name: "Upload to code-scanning"
         uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # tag=v3.26.6
         with:
diff --git a/.github/workflows/sync-gh-pages.yml b/.github/workflows/sync-gh-pages.yml
index fd44a65..8c584c7 100644
--- a/.github/workflows/sync-gh-pages.yml
+++ b/.github/workflows/sync-gh-pages.yml
@@ -2,9 +2,9 @@ name: Sync GH Pages
 on:
   push:
     branches:
-    - main
+      - main
     paths:
-    - library/**
+      - library/**
 
 permissions: read-all
 
@@ -17,7 +17,7 @@ jobs:
       repository-projects: write
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -26,5 +26,5 @@ jobs:
         with:
           github_token: ${{ github.token }}
           source_ref: ${{ github.ref }}
-          target_branch: 'gh-pages'
-          commit_message_template: '[Automated] Merged {source_ref} into target {target_branch}'
\ No newline at end of file
+          target_branch: "gh-pages"
+          commit_message_template: "[Automated] Merged {source_ref} into target {target_branch}"
diff --git a/Makefile b/Makefile
index f6895c9..376a2d1 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ LDFLAGS += -X $(GO_PKG)/internal/version.GitTag=$(GIT_TAG)
 KIND_VERSION ?= 0.22.0
 KUBERNETES_VERSION ?= 1.29.2
 KIND_KUBERNETES_VERSION ?= 1.29.2
-GATEKEEPER_VERSION ?= 3.16.0
+GATEKEEPER_VERSION ?= 3.17.0
 DAPR_VERSION ?= 1.12.5
 COSIGN_VERSION ?= 2.2.3
 NOTATION_VERSION ?= 1.2.0
diff --git a/api/unversioned/keymanagementprovider_types.go b/api/unversioned/keymanagementprovider_types.go
index 9b3a77d..b347b96 100644
--- a/api/unversioned/keymanagementprovider_types.go
+++ b/api/unversioned/keymanagementprovider_types.go
@@ -32,6 +32,10 @@ type KeyManagementProviderSpec struct {
 	// Name of the key management provider
 	Type string `json:"type,omitempty"`
 
+	// Refresh interval for fetching the certificate/key files from the provider. Only for providers that are refreshable. The value is in the format of "1h30m" where "h" means hour and "m" means minute. Valid time units are units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+	// +kubebuilder:default=""
+	RefreshInterval string `json:"refreshInterval,omitempty"`
+
 	// Parameters of the key management provider
 	Parameters runtime.RawExtension `json:"parameters,omitempty"`
 }
diff --git a/api/unversioned/namespacedkeymanagementprovider_types.go b/api/unversioned/namespacedkeymanagementprovider_types.go
index 70dcf55..cdccfe7 100644
--- a/api/unversioned/namespacedkeymanagementprovider_types.go
+++ b/api/unversioned/namespacedkeymanagementprovider_types.go
@@ -33,6 +33,10 @@ type NamespacedKeyManagementProviderSpec struct {
 	// Name of the key management provider
 	Type string `json:"type,omitempty"`
 
+	// Refresh interval for fetching the certificate/key files from the provider. Only for providers that are refreshable. The value is in the format of "1h30m" where "h" means hour and "m" means minute. Valid time units are units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
+	// +kubebuilder:default=""
+	RefreshInterval string `json:"refreshInterval,omitempty"`
+
 	// +kubebuilder:pruning:PreserveUnknownFields
 	// Parameters of the key management provider
 	Parameters runtime.RawExtension `json:"parameters,omitempty"`
diff --git a/api/unversioned/namespacedverifier_types.go b/api/unversioned/namespacedverifier_types.go
index 7e196a2..994e9d1 100644
--- a/api/unversioned/namespacedverifier_types.go
+++ b/api/unversioned/namespacedverifier_types.go
@@ -27,19 +27,22 @@ type NamespacedVerifierSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// Parameters for this verifier
diff --git a/api/unversioned/verifier_types.go b/api/unversioned/verifier_types.go
index 74b8bdf..fbdd69b 100644
--- a/api/unversioned/verifier_types.go
+++ b/api/unversioned/verifier_types.go
@@ -26,19 +26,22 @@ import (
 type VerifierSpec struct {
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name,omitempty"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes,omitempty"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// Parameters for this verifier
diff --git a/api/v1alpha1/zz_generated.conversion.go b/api/v1alpha1/zz_generated.conversion.go
index 467a815..9be9f81 100644
--- a/api/v1alpha1/zz_generated.conversion.go
+++ b/api/v1alpha1/zz_generated.conversion.go
@@ -642,6 +642,7 @@ func Convert_v1alpha1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec,
 
 func autoConvert_unversioned_VerifierSpec_To_v1alpha1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	// WARNING: in.Type requires manual conversion: does not exist in peer-type
 	// WARNING: in.Version requires manual conversion: does not exist in peer-type
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
diff --git a/api/v1beta1/namespacedverifier_types.go b/api/v1beta1/namespacedverifier_types.go
index 31e1c8e..17809a4 100644
--- a/api/v1beta1/namespacedverifier_types.go
+++ b/api/v1beta1/namespacedverifier_types.go
@@ -29,19 +29,22 @@ type NamespacedVerifierSpec struct {
 	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 	// Important: Run "make" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// +kubebuilder:pruning:PreserveUnknownFields
diff --git a/api/v1beta1/verifier_types.go b/api/v1beta1/verifier_types.go
index 5d4bf09..b273a48 100644
--- a/api/v1beta1/verifier_types.go
+++ b/api/v1beta1/verifier_types.go
@@ -25,19 +25,22 @@ import (
 type VerifierSpec struct {
 	// Important: Run "make install-crds" to regenerate code after modifying this file
 
-	// Name of the verifier
+	// Name of the verifier. Deprecated
 	Name string `json:"name"`
 
+	// Type of the verifier. Optional
+	Type string `json:"type,omitempty"`
+
 	// Version of the verifier plugin. Optional
 	Version string `json:"version,omitempty"`
 
 	// The type of artifact this verifier handles
 	ArtifactTypes string `json:"artifactTypes"`
 
-	// # Optional. URL/file path
+	// URL/file path. Optional
 	Address string `json:"address,omitempty"`
 
-	// OCI Artifact source to download the plugin from, optional
+	// OCI Artifact source to download the plugin from. Optional
 	Source *PluginSource `json:"source,omitempty"`
 
 	// +kubebuilder:pruning:PreserveUnknownFields
diff --git a/api/v1beta1/zz_generated.conversion.go b/api/v1beta1/zz_generated.conversion.go
index fafb65b..0b69afa 100644
--- a/api/v1beta1/zz_generated.conversion.go
+++ b/api/v1beta1/zz_generated.conversion.go
@@ -569,6 +569,7 @@ func Convert_unversioned_KeyManagementProviderList_To_v1beta1_KeyManagementProvi
 
 func autoConvert_v1beta1_KeyManagementProviderSpec_To_unversioned_KeyManagementProviderSpec(in *KeyManagementProviderSpec, out *unversioned.KeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -580,6 +581,7 @@ func Convert_v1beta1_KeyManagementProviderSpec_To_unversioned_KeyManagementProvi
 
 func autoConvert_unversioned_KeyManagementProviderSpec_To_v1beta1_KeyManagementProviderSpec(in *unversioned.KeyManagementProviderSpec, out *KeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -673,6 +675,7 @@ func Convert_unversioned_NamespacedKeyManagementProviderList_To_v1beta1_Namespac
 
 func autoConvert_v1beta1_NamespacedKeyManagementProviderSpec_To_unversioned_NamespacedKeyManagementProviderSpec(in *NamespacedKeyManagementProviderSpec, out *unversioned.NamespacedKeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -684,6 +687,7 @@ func Convert_v1beta1_NamespacedKeyManagementProviderSpec_To_unversioned_Namespac
 
 func autoConvert_unversioned_NamespacedKeyManagementProviderSpec_To_v1beta1_NamespacedKeyManagementProviderSpec(in *unversioned.NamespacedKeyManagementProviderSpec, out *NamespacedKeyManagementProviderSpec, s conversion.Scope) error {
 	out.Type = in.Type
+	out.RefreshInterval = in.RefreshInterval
 	out.Parameters = in.Parameters
 	return nil
 }
@@ -983,6 +987,7 @@ func Convert_unversioned_NamespacedVerifierList_To_v1beta1_NamespacedVerifierLis
 
 func autoConvert_v1beta1_NamespacedVerifierSpec_To_unversioned_NamespacedVerifierSpec(in *NamespacedVerifierSpec, out *unversioned.NamespacedVerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -998,6 +1003,7 @@ func Convert_v1beta1_NamespacedVerifierSpec_To_unversioned_NamespacedVerifierSpe
 
 func autoConvert_unversioned_NamespacedVerifierSpec_To_v1beta1_NamespacedVerifierSpec(in *unversioned.NamespacedVerifierSpec, out *NamespacedVerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -1319,6 +1325,7 @@ func Convert_unversioned_VerifierList_To_v1beta1_VerifierList(in *unversioned.Ve
 
 func autoConvert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec, out *unversioned.VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
@@ -1334,6 +1341,7 @@ func Convert_v1beta1_VerifierSpec_To_unversioned_VerifierSpec(in *VerifierSpec,
 
 func autoConvert_unversioned_VerifierSpec_To_v1beta1_VerifierSpec(in *unversioned.VerifierSpec, out *VerifierSpec, s conversion.Scope) error {
 	out.Name = in.Name
+	out.Type = in.Type
 	out.Version = in.Version
 	out.ArtifactTypes = in.ArtifactTypes
 	out.Address = in.Address
diff --git a/charts/ratify/README.md b/charts/ratify/README.md
index 10ec625..af36002 100644
--- a/charts/ratify/README.md
+++ b/charts/ratify/README.md
@@ -77,7 +77,7 @@ Values marked `# DEPRECATED` in the `values.yaml` as well as **DEPRECATED** in t
 | resources.requests.memory                          | Memory request of Ratify Deployment                                                                                                                                                                                                                                                                                                                                    | `512Mi`                           |
 | serviceAccount.create                              | Create new dedicated Ratify service account                                                                                                                                                                                                                                                                                                                            | `true`                            |
 | serviceAccount.name                                | Name of Ratify service account to create                                                                                                                                                                                                                                                                                                                               | `ratify-admin`                    |
-| gatekeeper.version                                 | Determines the Gatekeeper CRD versioning                                                                                                                                                                                                                                                                                                                               | `3.16.0`                          |
+| gatekeeper.version                                 | Determines the Gatekeeper CRD versioning                                                                                                                                                                                                                                                                                                                               | `3.17.0`                          |
 | gatekeeper.namespace                               | Namespace Gatekeeper is installed                                                                                                                                                                                                                                                                                                                                      | `gatekeeper-system`               |
 | instrumentation.metricsEnabled                     | Initializes the configured metrics provider                                                                                                                                                                                                                                                                                                                            | `true`                            |
 | instrumentation.metricsType                        | Specifies the metrics provider type                                                                                                                                                                                                                                                                                                                                    | `prometheus`                      |
diff --git a/charts/ratify/values.yaml b/charts/ratify/values.yaml
index 2bc52a0..aa08d89 100644
--- a/charts/ratify/values.yaml
+++ b/charts/ratify/values.yaml
@@ -53,7 +53,7 @@ serviceAccount:
   create: true
   name: ratify-admin
 gatekeeper:
-  version: "3.16.0"
+  version: "3.17.0"
   namespace: # default is gatekeeper-system
 instrumentation:
   metricsEnabled: true
diff --git a/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
index 784bcb5..b61b077 100644
--- a/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_namespacedverifiers.yaml
@@ -48,20 +48,20 @@ spec:
             description: NamespacedVerifierSpec defines the desired state of NamespacedVerifier
             properties:
               address:
-                description: '# Optional. URL/file path'
+                description: URL/file path. Optional
                 type: string
               artifactTypes:
                 description: The type of artifact this verifier handles
                 type: string
               name:
-                description: Name of the verifier
+                description: Name of the verifier. Deprecated
                 type: string
               parameters:
                 description: Parameters for this verifier
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
-                description: OCI Artifact source to download the plugin from, optional
+                description: OCI Artifact source to download the plugin from. Optional
                 properties:
                   artifact:
                     description: OCI Artifact source to download the plugin from
@@ -72,6 +72,9 @@ spec:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                 type: object
+              type:
+                description: Type of the verifier. Optional
+                type: string
               version:
                 description: Version of the verifier plugin. Optional
                 type: string
diff --git a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
index a23d981..8d08f76 100644
--- a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
+++ b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
@@ -107,20 +107,20 @@ spec:
             description: VerifierSpec defines the desired state of Verifier
             properties:
               address:
-                description: '# Optional. URL/file path'
+                description: URL/file path. Optional
                 type: string
               artifactTypes:
                 description: The type of artifact this verifier handles
                 type: string
               name:
-                description: Name of the verifier
+                description: Name of the verifier. Deprecated
                 type: string
               parameters:
                 description: Parameters for this verifier
                 type: object
                 x-kubernetes-preserve-unknown-fields: true
               source:
-                description: OCI Artifact source to download the plugin from, optional
+                description: OCI Artifact source to download the plugin from. Optional
                 properties:
                   artifact:
                     description: OCI Artifact source to download the plugin from
@@ -131,6 +131,9 @@ spec:
                     type: object
                     x-kubernetes-preserve-unknown-fields: true
                 type: object
+              type:
+                description: Type of the verifier. Optional
+                type: string
               version:
                 description: Version of the verifier plugin. Optional
                 type: string
diff --git a/dev.helmfile.yaml b/dev.helmfile.yaml
index 0a3f406..bec894a 100644
--- a/dev.helmfile.yaml
+++ b/dev.helmfile.yaml
@@ -10,7 +10,7 @@ releases:
     namespace: gatekeeper-system
     createNamespace: true
     chart: gatekeeper/gatekeeper
-    version: 3.16.0
+    version: 3.17.0
     wait: true
     set:
       - name: enableExternalData
diff --git a/dev.high-availability.helmfile.yaml b/dev.high-availability.helmfile.yaml
index 3436a1c..29c40fe 100644
--- a/dev.high-availability.helmfile.yaml
+++ b/dev.high-availability.helmfile.yaml
@@ -20,7 +20,7 @@ releases:
     namespace: gatekeeper-system
     createNamespace: true
     chart: gatekeeper/gatekeeper
-    version: 3.16.0
+    version: 3.17.0
     wait: true
     set:
       - name: enableExternalData
diff --git a/pkg/controllers/clusterresource/keymanagementprovider_controller.go b/pkg/controllers/clusterresource/keymanagementprovider_controller.go
index 93dda98..afb53a9 100644
--- a/pkg/controllers/clusterresource/keymanagementprovider_controller.go
+++ b/pkg/controllers/clusterresource/keymanagementprovider_controller.go
@@ -18,11 +18,19 @@ package clusterresource
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 
+	re "github.com/ratify-project/ratify/errors"
+	"github.com/ratify-project/ratify/internal/constants"
+	cutils "github.com/ratify-project/ratify/pkg/controllers/utils"
+	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
 	_ "github.com/ratify-project/ratify/pkg/keymanagementprovider/azurekeyvault" // register azure key vault key management provider
 	_ "github.com/ratify-project/ratify/pkg/keymanagementprovider/inline"        // register inline key management provider
 	"github.com/ratify-project/ratify/pkg/keymanagementprovider/refresh"
+	"github.com/sirupsen/logrus"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -37,20 +45,91 @@ type KeyManagementProviderReconciler struct {
 	Scheme *runtime.Scheme
 }
 
-func (r *KeyManagementProviderReconciler) ReconcileWithConfig(ctx context.Context, config map[string]interface{}) (ctrl.Result, error) {
-	refresher, err := refresh.CreateRefresherFromConfig(config)
-	if err != nil {
+func (r *KeyManagementProviderReconciler) ReconcileWithType(ctx context.Context, req ctrl.Request, refresherType string) (ctrl.Result, error) {
+	logger := logrus.WithContext(ctx)
+
+	var keyManagementProvider configv1beta1.KeyManagementProvider
+
+	resource := req.Name
+
+	logger.Infof("reconciling cluster key management provider '%v'", resource)
+
+	if err := r.Get(ctx, req.NamespacedName, &keyManagementProvider); err != nil {
+		if apierrors.IsNotFound(err) {
+			logger.Infof("deletion detected, removing key management provider %v", resource)
+			kmp.DeleteResourceFromMap(resource)
+		} else {
+			logger.Error(err, "unable to fetch key management provider")
+		}
+
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	lastFetchedTime := metav1.Now()
+
+	// get certificate store list to check if certificate store is configured
+	// TODO: remove check in v2.0.0+
+	var certificateStoreList configv1beta1.CertificateStoreList
+	if err := r.List(ctx, &certificateStoreList); err != nil {
+		logger.Error(err, "unable to list certificate stores")
 		return ctrl.Result{}, err
 	}
+
+	if len(certificateStoreList.Items) > 0 {
+		// Note: for backwards compatibility in upgrade scenarios, Ratify will only log a warning statement.
+		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
+	}
+
+	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
+	if err != nil {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
+
+		kmp.SetCertificateError(resource, kmpErr)
+		kmp.SetKeyError(resource, kmpErr)
+		writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, false, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
+	}
+
+	refresherConfig := refresh.RefresherConfig{
+		RefresherType:           refresherType,
+		Provider:                provider,
+		ProviderType:            keyManagementProvider.Spec.Type,
+		ProviderRefreshInterval: keyManagementProvider.Spec.RefreshInterval,
+		Resource:                resource,
+	}
+
+	refresher, err := refresh.CreateRefresherFromConfig(refresherConfig)
+	if err != nil {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create refresher from config")
+		kmp.SetCertificateError(resource, kmpErr)
+		kmp.SetKeyError(resource, kmpErr)
+		writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, false, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
+	}
+
 	err = refresher.Refresh(ctx)
 	if err != nil {
-		return ctrl.Result{}, err
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to refresh key management provider")
+		writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, false, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
 	}
 
 	result, ok := refresher.GetResult().(ctrl.Result)
 	if !ok {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to get result from refresher")
+		writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, false, &kmpErr, lastFetchedTime, nil)
 		return ctrl.Result{}, fmt.Errorf("unexpected type returned from GetResult: %T", refresher.GetResult())
 	}
+
+	status, ok := refresher.GetStatus().(kmp.KeyManagementProviderStatus)
+	if !ok {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to get status from refresher")
+		writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, false, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, fmt.Errorf("unexpected type returned from GetStatus: %T", refresher.GetStatus())
+	}
+
+	writeKMProviderStatus(ctx, r, &keyManagementProvider, logger, true, nil, lastFetchedTime, status)
+
 	return result, nil
 }
 
@@ -58,12 +137,7 @@ func (r *KeyManagementProviderReconciler) ReconcileWithConfig(ctx context.Contex
 // +kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=keymanagementproviders/status,verbs=get;update;patch
 // +kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=keymanagementproviders/finalizers,verbs=update
 func (r *KeyManagementProviderReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
-	refresherConfig := map[string]interface{}{
-		"type":    refresh.KubeRefresherType,
-		"client":  r.Client,
-		"request": req,
-	}
-	return r.ReconcileWithConfig(ctx, refresherConfig)
+	return r.ReconcileWithType(ctx, req, refresh.KubeRefresherType)
 }
 
 // SetupWithManager sets up the controller with the Manager.
@@ -77,3 +151,40 @@ func (r *KeyManagementProviderReconciler) SetupWithManager(mgr ctrl.Manager) err
 		For(&configv1beta1.KeyManagementProvider{}).WithEventFilter(pred).
 		Complete(r)
 }
+
+func writeKMProviderStatus(ctx context.Context, r client.StatusClient, keyManagementProvider *configv1beta1.KeyManagementProvider, logger *logrus.Entry, isSuccess bool, err *re.Error, operationTime metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
+	if isSuccess {
+		updateKMProviderSuccessStatus(keyManagementProvider, &operationTime, kmProviderStatus)
+	} else {
+		updateKMProviderErrorStatus(keyManagementProvider, err, &operationTime)
+	}
+	if statusErr := r.Status().Update(ctx, keyManagementProvider); statusErr != nil {
+		logger.Error(statusErr, ",unable to update key management provider error status")
+	}
+}
+
+// updateKMProviderErrorStatus updates the key management provider status with error, brief error and last fetched time
+func updateKMProviderErrorStatus(keyManagementProvider *configv1beta1.KeyManagementProvider, err *re.Error, operationTime *metav1.Time) {
+	keyManagementProvider.Status.IsSuccess = false
+	keyManagementProvider.Status.Error = err.Error()
+	keyManagementProvider.Status.BriefError = err.GetConciseError(constants.MaxBriefErrLength)
+	keyManagementProvider.Status.LastFetchedTime = operationTime
+}
+
+// updateKMProviderSuccessStatus updates the key management provider status if status argument is non nil
+// Success status includes last fetched time and other provider-specific properties
+func updateKMProviderSuccessStatus(keyManagementProvider *configv1beta1.KeyManagementProvider, lastOperationTime *metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
+	keyManagementProvider.Status.IsSuccess = true
+	keyManagementProvider.Status.Error = ""
+	keyManagementProvider.Status.BriefError = ""
+	keyManagementProvider.Status.LastFetchedTime = lastOperationTime
+
+	if kmProviderStatus != nil {
+		jsonString, _ := json.Marshal(kmProviderStatus)
+
+		raw := runtime.RawExtension{
+			Raw: jsonString,
+		}
+		keyManagementProvider.Status.Properties = raw
+	}
+}
diff --git a/pkg/controllers/clusterresource/verifier_controller.go b/pkg/controllers/clusterresource/verifier_controller.go
index c8c8cd8..f752fa1 100644
--- a/pkg/controllers/clusterresource/verifier_controller.go
+++ b/pkg/controllers/clusterresource/verifier_controller.go
@@ -85,7 +85,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 
 // creates a verifier reference from CR spec and add verifier to map
 func verifierAddOrReplace(spec configv1beta1.VerifierSpec, objectName string) error {
-	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
+	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, cutils.GetVerifierType(spec), spec.ArtifactTypes, spec.Source)
 	if err != nil {
 		errMsg := fmt.Sprintf("Unable to apply cluster-wide resource %s of Verifier kind", objectName)
 		logrus.Error(err, errMsg)
diff --git a/pkg/controllers/namespaceresource/keymanagementprovider_controller.go b/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
index ba439a2..2bbdd0b 100644
--- a/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
+++ b/pkg/controllers/namespaceresource/keymanagementprovider_controller.go
@@ -18,11 +18,18 @@ package namespaceresource
 
 import (
 	"context"
-	"fmt"
+	"encoding/json"
 
+	re "github.com/ratify-project/ratify/errors"
+	"github.com/ratify-project/ratify/internal/constants"
+	cutils "github.com/ratify-project/ratify/pkg/controllers/utils"
+	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
 	_ "github.com/ratify-project/ratify/pkg/keymanagementprovider/azurekeyvault" // register azure key vault key management provider
 	_ "github.com/ratify-project/ratify/pkg/keymanagementprovider/inline"        // register inline key management provider
 	"github.com/ratify-project/ratify/pkg/keymanagementprovider/refresh"
+	"github.com/sirupsen/logrus"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -37,20 +44,89 @@ type KeyManagementProviderReconciler struct {
 	Scheme *runtime.Scheme
 }
 
-func (r *KeyManagementProviderReconciler) ReconcileWithConfig(ctx context.Context, config map[string]interface{}) (ctrl.Result, error) {
-	refresher, err := refresh.CreateRefresherFromConfig(config)
-	if err != nil {
+func (r *KeyManagementProviderReconciler) ReconcileWithType(ctx context.Context, req ctrl.Request, refresherType string) (ctrl.Result, error) {
+	logger := logrus.WithContext(ctx)
+
+	var resource = req.NamespacedName.String()
+	var keyManagementProvider configv1beta1.NamespacedKeyManagementProvider
+
+	logger.Infof("reconciling cluster key management provider '%v'", resource)
+
+	if err := r.Get(ctx, req.NamespacedName, &keyManagementProvider); err != nil {
+		if apierrors.IsNotFound(err) {
+			logger.Infof("deletion detected, removing key management provider %v", resource)
+			kmp.DeleteResourceFromMap(resource)
+		} else {
+			logger.Error(err, "unable to fetch key management provider")
+		}
+
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	lastFetchedTime := metav1.Now()
+	isFetchSuccessful := false
+
+	// get certificate store list to check if certificate store is configured
+	// TODO: remove check in v2.0.0+
+	var certificateStoreList configv1beta1.CertificateStoreList
+	if err := r.List(ctx, &certificateStoreList); err != nil {
+		logger.Error(err, "unable to list certificate stores")
 		return ctrl.Result{}, err
 	}
+
+	if len(certificateStoreList.Items) > 0 {
+		// Note: for backwards compatibility in upgrade scenarios, Ratify will only log a warning statement.
+		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
+	}
+
+	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
+	if err != nil {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
+
+		kmp.SetCertificateError(resource, err)
+		kmp.SetKeyError(resource, err)
+		writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
+	}
+
+	refresherConfig := refresh.RefresherConfig{
+		RefresherType:           refresherType,
+		Provider:                provider,
+		ProviderType:            keyManagementProvider.Spec.Type,
+		ProviderRefreshInterval: keyManagementProvider.Spec.RefreshInterval,
+		Resource:                resource,
+	}
+
+	refresher, err := refresh.CreateRefresherFromConfig(refresherConfig)
+	if err != nil {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to create refresher from config")
+		writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
+	}
+
 	err = refresher.Refresh(ctx)
 	if err != nil {
-		return ctrl.Result{}, err
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to refresh key management provider")
+		writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
 	}
 
 	result, ok := refresher.GetResult().(ctrl.Result)
 	if !ok {
-		return ctrl.Result{}, fmt.Errorf("unexpected type returned from GetResult: %T", refresher.GetResult())
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to get result from refresher")
+		writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, kmpErr
+	}
+
+	status, ok := refresher.GetStatus().(kmp.KeyManagementProviderStatus)
+	if !ok {
+		kmpErr := re.ErrorCodeKeyManagementProviderFailure.WithError(err).WithDetail("Failed to get status from refresher")
+		writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
+		return ctrl.Result{}, &kmpErr
 	}
+
+	writeKMProviderStatusNamespaced(ctx, r, &keyManagementProvider, logger, true, nil, lastFetchedTime, status)
+
 	return result, nil
 }
 
@@ -58,12 +134,7 @@ func (r *KeyManagementProviderReconciler) ReconcileWithConfig(ctx context.Contex
 // +kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=namespacedkeymanagementproviders/status,verbs=get;update;patch
 // +kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=namespacedkeymanagementproviders/finalizers,verbs=update
 func (r *KeyManagementProviderReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
-	refresherConfig := map[string]interface{}{
-		"type":    refresh.KubeRefresherNamespacedType,
-		"client":  r.Client,
-		"request": req,
-	}
-	return r.ReconcileWithConfig(ctx, refresherConfig)
+	return r.ReconcileWithType(ctx, req, refresh.KubeRefresherType)
 }
 
 // SetupWithManager sets up the controller with the Manager.
@@ -77,3 +148,40 @@ func (r *KeyManagementProviderReconciler) SetupWithManager(mgr ctrl.Manager) err
 		For(&configv1beta1.NamespacedKeyManagementProvider{}).WithEventFilter(pred).
 		Complete(r)
 }
+
+// writeKMProviderStatusNamespaced updates the status of the key management provider resource
+func writeKMProviderStatusNamespaced(ctx context.Context, r client.StatusClient, keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, logger *logrus.Entry, isSuccess bool, err *re.Error, operationTime metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
+	if isSuccess {
+		updateKMProviderSuccessStatusNamespaced(keyManagementProvider, &operationTime, kmProviderStatus)
+	} else {
+		updateKMProviderErrorStatusNamespaced(keyManagementProvider, err, &operationTime)
+	}
+	if statusErr := r.Status().Update(ctx, keyManagementProvider); statusErr != nil {
+		logger.Error(statusErr, ",unable to update key management provider error status")
+	}
+}
+
+// updateKMProviderErrorStatusNamespaced updates the key management provider status with error, brief error and last fetched time
+func updateKMProviderErrorStatusNamespaced(keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, err *re.Error, operationTime *metav1.Time) {
+	keyManagementProvider.Status.IsSuccess = false
+	keyManagementProvider.Status.Error = err.Error()
+	keyManagementProvider.Status.BriefError = err.GetConciseError(constants.MaxBriefErrLength)
+	keyManagementProvider.Status.LastFetchedTime = operationTime
+}
+
+// Success status includes last fetched time and other provider-specific properties
+func updateKMProviderSuccessStatusNamespaced(keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, lastOperationTime *metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
+	keyManagementProvider.Status.IsSuccess = true
+	keyManagementProvider.Status.Error = ""
+	keyManagementProvider.Status.BriefError = ""
+	keyManagementProvider.Status.LastFetchedTime = lastOperationTime
+
+	if kmProviderStatus != nil {
+		jsonString, _ := json.Marshal(kmProviderStatus)
+
+		raw := runtime.RawExtension{
+			Raw: jsonString,
+		}
+		keyManagementProvider.Status.Properties = raw
+	}
+}
diff --git a/pkg/controllers/namespaceresource/verifier_controller.go b/pkg/controllers/namespaceresource/verifier_controller.go
index 4b19b61..a2926ef 100644
--- a/pkg/controllers/namespaceresource/verifier_controller.go
+++ b/pkg/controllers/namespaceresource/verifier_controller.go
@@ -84,7 +84,7 @@ func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
 
 // creates a verifier reference from CRD spec and add store to map
 func verifierAddOrReplace(spec configv1beta1.NamespacedVerifierSpec, objectName string, namespace string) error {
-	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, spec.Name, spec.ArtifactTypes, spec.Source)
+	verifierConfig, err := cutils.SpecToVerifierConfig(spec.Parameters.Raw, objectName, cutils.GetVerifierType(spec), spec.ArtifactTypes, spec.Source)
 	if err != nil {
 		errMsg := fmt.Sprintf("Unable to apply the resource %s of NamespacedVerifier kind in the namespace %s", objectName, namespace)
 		logrus.Error(err, errMsg)
diff --git a/pkg/controllers/utils/verifier.go b/pkg/controllers/utils/verifier.go
index e65a059..43a9e85 100644
--- a/pkg/controllers/utils/verifier.go
+++ b/pkg/controllers/utils/verifier.go
@@ -72,3 +72,22 @@ func SpecToVerifierConfig(raw []byte, verifierName, verifierType, artifactTypes
 
 	return verifierConfig, nil
 }
+
+// GetVerifierType returns verifier type and is backward compatible with the deprecated name field
+func GetVerifierType(verifierSpec interface{}) string {
+	switch spec := verifierSpec.(type) {
+	case configv1beta1.VerifierSpec:
+		if spec.Type == "" {
+			return spec.Name
+		}
+		return spec.Type
+	case configv1beta1.NamespacedVerifierSpec:
+		if spec.Type == "" {
+			return spec.Name
+		}
+		return spec.Type
+	default:
+		logrus.Error("unable to assert verifierSpec type", spec)
+	}
+	return ""
+}
diff --git a/pkg/keymanagementprovider/mocks/client.go b/pkg/keymanagementprovider/mocks/client.go
index f24c190..4d651ce 100644
--- a/pkg/keymanagementprovider/mocks/client.go
+++ b/pkg/keymanagementprovider/mocks/client.go
@@ -17,7 +17,7 @@ package mocks
 
 import (
 	"context"
-	"fmt"
+	"errors"
 
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -25,8 +25,43 @@ import (
 
 type TestClient struct {
 	client.Client
+	GetFunc  func(ctx context.Context, key types.NamespacedName, obj client.Object) error
+	ListFunc func(ctx context.Context, list client.ObjectList) error
 }
 
-func (m TestClient) Get(_ context.Context, _ types.NamespacedName, _ client.Object, _ ...client.GetOption) error {
-	return fmt.Errorf("error")
+func (m TestClient) Get(_ context.Context, key types.NamespacedName, obj client.Object, _ ...client.GetOption) error {
+	if m.GetFunc != nil {
+		return m.GetFunc(context.Background(), key, obj)
+	}
+	return nil
+}
+
+func (m TestClient) List(_ context.Context, list client.ObjectList, _ ...client.ListOption) error {
+	if m.ListFunc != nil {
+		return m.ListFunc(context.Background(), list)
+	}
+	return nil
+}
+
+type mockSubResourceWriter struct {
+	updateFailed bool
+}
+
+func (m *TestClient) Status() client.StatusWriter {
+	return &mockSubResourceWriter{updateFailed: false}
+}
+
+func (m *mockSubResourceWriter) Create(_ context.Context, _ client.Object, _ client.Object, _ ...client.SubResourceCreateOption) error {
+	return nil
+}
+
+func (m *mockSubResourceWriter) Patch(_ context.Context, _ client.Object, _ client.Patch, _ ...client.SubResourcePatchOption) error {
+	return nil
+}
+
+func (m *mockSubResourceWriter) Update(_ context.Context, _ client.Object, _ ...client.SubResourceUpdateOption) error {
+	if m.updateFailed {
+		return errors.New("update failed")
+	}
+	return nil
 }
diff --git a/pkg/keymanagementprovider/mocks/factory.go b/pkg/keymanagementprovider/mocks/factory.go
index 0230582..15a0e0d 100644
--- a/pkg/keymanagementprovider/mocks/factory.go
+++ b/pkg/keymanagementprovider/mocks/factory.go
@@ -16,6 +16,7 @@ limitations under the License.
 package mocks
 
 import (
+	"context"
 	"crypto"
 	"crypto/x509"
 
@@ -24,10 +25,19 @@ import (
 )
 
 type TestKeyManagementProviderFactory struct {
+	GetCertsFunc      func(ctx context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error)
+	GetKeysFunc       func(ctx context.Context) (map[keymanagementprovider.KMPMapKey]crypto.PublicKey, keymanagementprovider.KeyManagementProviderStatus, error)
+	IsRefreshableFunc func() bool
 }
 
 func (f *TestKeyManagementProviderFactory) Create(_ string, _ config.KeyManagementProviderConfig, _ string) (keymanagementprovider.KeyManagementProvider, error) {
 	var certMap map[keymanagementprovider.KMPMapKey][]*x509.Certificate
 	var keyMap map[keymanagementprovider.KMPMapKey]crypto.PublicKey
-	return &TestKeyManagementProvider{certificates: certMap, keys: keyMap}, nil
+	return &TestKeyManagementProvider{
+		certificates:        certMap,
+		keys:                keyMap,
+		GetCertificatesFunc: f.GetCertsFunc,
+		GetKeysFunc:         f.GetKeysFunc,
+		IsRefreshableFunc:   f.IsRefreshableFunc,
+	}, nil
 }
diff --git a/pkg/keymanagementprovider/mocks/types.go b/pkg/keymanagementprovider/mocks/types.go
index 246de21..5cfa216 100644
--- a/pkg/keymanagementprovider/mocks/types.go
+++ b/pkg/keymanagementprovider/mocks/types.go
@@ -24,20 +24,32 @@ import (
 )
 
 type TestKeyManagementProvider struct {
-	certificates map[keymanagementprovider.KMPMapKey][]*x509.Certificate
-	keys         map[keymanagementprovider.KMPMapKey]crypto.PublicKey
-	status       keymanagementprovider.KeyManagementProviderStatus
-	err          error
+	certificates        map[keymanagementprovider.KMPMapKey][]*x509.Certificate
+	keys                map[keymanagementprovider.KMPMapKey]crypto.PublicKey
+	status              keymanagementprovider.KeyManagementProviderStatus
+	err                 error
+	GetCertificatesFunc func(ctx context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error)
+	GetKeysFunc         func(ctx context.Context) (map[keymanagementprovider.KMPMapKey]crypto.PublicKey, keymanagementprovider.KeyManagementProviderStatus, error)
+	IsRefreshableFunc   func() bool
 }
 
 func (c *TestKeyManagementProvider) GetCertificates(_ context.Context) (map[keymanagementprovider.KMPMapKey][]*x509.Certificate, keymanagementprovider.KeyManagementProviderStatus, error) {
+	if c.GetCertificatesFunc != nil {
+		return c.GetCertificatesFunc(context.Background())
+	}
 	return c.certificates, c.status, c.err
 }
 
 func (c *TestKeyManagementProvider) GetKeys(_ context.Context) (map[keymanagementprovider.KMPMapKey]crypto.PublicKey, keymanagementprovider.KeyManagementProviderStatus, error) {
+	if c.GetKeysFunc != nil {
+		return c.GetKeysFunc(context.Background())
+	}
 	return c.keys, c.status, c.err
 }
 
 func (c *TestKeyManagementProvider) IsRefreshable() bool {
-	return true
+	if c.IsRefreshableFunc != nil {
+		return c.IsRefreshableFunc()
+	}
+	return false
 }
diff --git a/pkg/keymanagementprovider/refresh/factory.go b/pkg/keymanagementprovider/refresh/factory.go
index 186951c..eed41e1 100644
--- a/pkg/keymanagementprovider/refresh/factory.go
+++ b/pkg/keymanagementprovider/refresh/factory.go
@@ -21,7 +21,8 @@ var refresherFactories = make(map[string]RefresherFactory)
 
 type RefresherFactory interface {
 	// Create creates a new instance of the refresher using the provided configuration
-	Create(config map[string]interface{}) (Refresher, error)
+	// Create(config map[string]interface{}) (Refresher, error)
+	Create(config RefresherConfig) (Refresher, error)
 }
 
 // Refresher is an interface that defines methods to be implemented by a each refresher
@@ -37,17 +38,10 @@ func Register(name string, factory RefresherFactory) {
 }
 
 // CreateRefresherFromConfig creates a new instance of the refresher using the provided configuration
-func CreateRefresherFromConfig(refresherConfig map[string]interface{}) (Refresher, error) {
-	refresherType, ok := refresherConfig["type"].(string)
+func CreateRefresherFromConfig(refresherConfig RefresherConfig) (Refresher, error) {
+	factory, ok := refresherFactories[refresherConfig.RefresherType]
 	if !ok {
-		return nil, fmt.Errorf("refresher type is not a string")
-	}
-	if !ok || refresherType == "" {
-		return nil, fmt.Errorf("refresher type cannot be empty")
-	}
-	factory, ok := refresherFactories[refresherType]
-	if !ok {
-		return nil, fmt.Errorf("refresher factory with name %s not found", refresherType)
+		return nil, fmt.Errorf("refresher factory with name %s not found", refresherConfig.RefresherType)
 	}
 	return factory.Create(refresherConfig)
 }
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh.go b/pkg/keymanagementprovider/refresh/kubeRefresh.go
index acd967e..895cb7d 100644
--- a/pkg/keymanagementprovider/refresh/kubeRefresh.go
+++ b/pkg/keymanagementprovider/refresh/kubeRefresh.go
@@ -18,28 +18,23 @@ package refresh
 
 import (
 	"context"
-	"encoding/json"
 	"fmt"
 	"maps"
 	"time"
 
-	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
 	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/internal/constants"
-	cutils "github.com/ratify-project/ratify/pkg/controllers/utils"
 	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
 	"github.com/sirupsen/logrus"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
 	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 type KubeRefresher struct {
-	client.Client
-	Request ctrl.Request
-	Result  ctrl.Result
+	Provider                kmp.KeyManagementProvider
+	ProviderType            string
+	ProviderRefreshInterval string
+	Resource                string
+	Result                  ctrl.Result
+	Status                  kmp.KeyManagementProviderStatus
 }
 
 // Register registers the kubeRefresher factory
@@ -51,99 +46,45 @@ func init() {
 func (kr *KubeRefresher) Refresh(ctx context.Context) error {
 	logger := logrus.WithContext(ctx)
 
-	var resource = kr.Request.Name
-	var keyManagementProvider configv1beta1.KeyManagementProvider
-
-	logger.Infof("reconciling cluster key management provider '%v'", resource)
-
-	if err := kr.Get(ctx, kr.Request.NamespacedName, &keyManagementProvider); err != nil {
-		if apierrors.IsNotFound(err) {
-			logger.Infof("deletion detected, removing key management provider %v", resource)
-			kmp.DeleteResourceFromMap(resource)
-		} else {
-			logger.Error(err, "unable to fetch key management provider")
-		}
-
-		kr.Result = ctrl.Result{}
-
-		return client.IgnoreNotFound(err)
-	}
-
-	lastFetchedTime := metav1.Now()
-	isFetchSuccessful := false
-
-	// get certificate store list to check if certificate store is configured
-	// TODO: remove check in v2.0.0+
-	var certificateStoreList configv1beta1.CertificateStoreList
-	if err := kr.List(ctx, &certificateStoreList); err != nil {
-		logger.Error(err, "unable to list certificate stores")
-		kr.Result = ctrl.Result{}
-		return err
-	}
-
-	if len(certificateStoreList.Items) > 0 {
-		// Note: for backwards compatibility in upgrade scenarios, Ratify will only log a warning statement.
-		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
-	}
-
-	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
-	if err != nil {
-		kmpErr := re.ErrorCodePluginInitFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
-
-		kmp.SetCertificateError(resource, kmpErr)
-		kmp.SetKeyError(resource, kmpErr)
-		writeKMProviderStatus(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Request = ctrl.Request{}
-		return kmpErr
-	}
-
 	// fetch certificates and store in map
-	certificates, certAttributes, err := provider.GetCertificates(ctx)
+	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]", resource, keyManagementProvider.Spec.Type))
-
-		kmp.SetCertificateError(resource, err)
-		writeKMProviderStatus(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Request = ctrl.Request{}
+		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 keys and store in map
-	keys, keyAttributes, err := provider.GetKeys(ctx)
+	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]", resource, keyManagementProvider.Spec.Type))
-
-		kmp.SetKeyError(resource, kmpErr)
-		writeKMProviderStatus(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Request = ctrl.Request{}
+		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(resource, keyManagementProvider.Spec.Type, keys, certificates)
+
+	kmp.SaveSecrets(kr.Resource, kr.ProviderType, keys, certificates)
 	// merge certificates and keys status into one
 	maps.Copy(keyAttributes, certAttributes)
-	isFetchSuccessful = true
-	writeKMProviderStatus(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, nil, lastFetchedTime, keyAttributes)
+	kr.Status = keyAttributes
 
-	logger.Infof("%v certificate(s) & %v key(s) fetched for key management provider %v", len(certificates), len(keys), resource)
+	logger.Infof("%v certificate(s) & %v key(s) fetched for key management provider %v", len(certificates), len(keys), kr.Resource)
 
-	// returning empty result and no error to indicate we’ve successfully reconciled this object
+	// 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 !provider.IsRefreshable() {
-		kr.Request = ctrl.Request{}
+	if !kr.Provider.IsRefreshable() {
 		return nil
 	}
 
 	// if interval is not set, disable refresh
-	if keyManagementProvider.Spec.RefreshInterval == "" {
-		kr.Result = ctrl.Result{}
+	if kr.ProviderRefreshInterval == "" {
 		return nil
 	}
+
 	// resource is refreshable, requeue after interval
-	intervalDuration, err := time.ParseDuration(keyManagementProvider.Spec.RefreshInterval)
+	intervalDuration, err := time.ParseDuration(kr.ProviderRefreshInterval)
 	if err != nil {
-		logger.Error(err, "unable to parse interval duration")
-		kr.Result = ctrl.Result{}
-		return err
+		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)
@@ -157,57 +98,16 @@ func (kr *KubeRefresher) GetResult() interface{} {
 	return kr.Result
 }
 
-// Create creates a new KubeRefresher instance
-func (kr *KubeRefresher) Create(config map[string]interface{}) (Refresher, error) {
-	client, ok := config["client"].(client.Client)
-	if !ok {
-		return nil, fmt.Errorf("client is required in config")
-	}
-
-	request, ok := config["request"].(ctrl.Request)
-	if !ok {
-		return nil, fmt.Errorf("request is required in config")
-	}
+func (kr *KubeRefresher) GetStatus() interface{} {
+	return kr.Status
+}
 
+// Create creates a new KubeRefresher instance
+func (kr *KubeRefresher) Create(config RefresherConfig) (Refresher, error) {
 	return &KubeRefresher{
-		Client:  client,
-		Request: request,
+		Provider:                config.Provider,
+		ProviderType:            config.ProviderType,
+		ProviderRefreshInterval: config.ProviderRefreshInterval,
+		Resource:                config.Resource,
 	}, nil
 }
-
-func writeKMProviderStatus(ctx context.Context, r client.StatusClient, keyManagementProvider *configv1beta1.KeyManagementProvider, logger *logrus.Entry, isSuccess bool, err *re.Error, operationTime metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
-	if isSuccess {
-		updateKMProviderSuccessStatus(keyManagementProvider, &operationTime, kmProviderStatus)
-	} else {
-		updateKMProviderErrorStatus(keyManagementProvider, err, &operationTime)
-	}
-	if statusErr := r.Status().Update(ctx, keyManagementProvider); statusErr != nil {
-		logger.Error(statusErr, ",unable to update key management provider error status")
-	}
-}
-
-// updateKMProviderErrorStatus updates the key management provider status with error, brief error and last fetched time
-func updateKMProviderErrorStatus(keyManagementProvider *configv1beta1.KeyManagementProvider, err *re.Error, operationTime *metav1.Time) {
-	keyManagementProvider.Status.IsSuccess = false
-	keyManagementProvider.Status.Error = err.Error()
-	keyManagementProvider.Status.BriefError = err.GetConciseError(constants.MaxBriefErrLength)
-	keyManagementProvider.Status.LastFetchedTime = operationTime
-}
-
-// updateKMProviderSuccessStatus updates the key management provider status if status argument is non nil
-// Success status includes last fetched time and other provider-specific properties
-func updateKMProviderSuccessStatus(keyManagementProvider *configv1beta1.KeyManagementProvider, lastOperationTime *metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
-	keyManagementProvider.Status.IsSuccess = true
-	keyManagementProvider.Status.Error = ""
-	keyManagementProvider.Status.BriefError = ""
-	keyManagementProvider.Status.LastFetchedTime = lastOperationTime
-
-	if kmProviderStatus != nil {
-		jsonString, _ := json.Marshal(kmProviderStatus)
-
-		raw := runtime.RawExtension{
-			Raw: jsonString,
-		}
-		keyManagementProvider.Status.Properties = raw
-	}
-}
diff --git a/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced.go b/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced.go
deleted file mode 100644
index 8bd4ade..0000000
--- a/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced.go
+++ /dev/null
@@ -1,211 +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"
-	"encoding/json"
-	"fmt"
-	"maps"
-	"time"
-
-	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/internal/constants"
-	cutils "github.com/ratify-project/ratify/pkg/controllers/utils"
-	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
-	"github.com/sirupsen/logrus"
-	apierrors "k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/client"
-)
-
-type KubeRefresherNamespaced struct {
-	client.Client
-	Request ctrl.Request
-	Result  ctrl.Result
-}
-
-// Register registers the kubeRefresherNamespaced factory
-func init() {
-	Register(KubeRefresherNamespacedType, &KubeRefresherNamespaced{})
-}
-
-// Refresh the certificates/keys for the key management provider by calling the GetCertificates and GetKeys methods
-func (kr *KubeRefresherNamespaced) Refresh(ctx context.Context) error {
-	logger := logrus.WithContext(ctx)
-
-	var resource = kr.Request.NamespacedName.String()
-	var keyManagementProvider configv1beta1.NamespacedKeyManagementProvider
-
-	logger.Infof("reconciling namespaced key management provider '%v'", resource)
-
-	if err := kr.Get(ctx, kr.Request.NamespacedName, &keyManagementProvider); err != nil {
-		if apierrors.IsNotFound(err) {
-			logger.Infof("deletion detected, removing key management provider %v", resource)
-			kmp.DeleteResourceFromMap(resource)
-		} else {
-			logger.Error(err, "unable to fetch key management provider")
-		}
-
-		kr.Result = ctrl.Result{}
-
-		return client.IgnoreNotFound(err)
-	}
-
-	lastFetchedTime := metav1.Now()
-	isFetchSuccessful := false
-
-	// get certificate store list to check if certificate store is configured
-	// TODO: remove check in v2.0.0+
-	var certificateStoreList configv1beta1.CertificateStoreList
-	if err := kr.List(ctx, &certificateStoreList); err != nil {
-		logger.Error(err, "unable to list certificate stores")
-		kr.Result = ctrl.Result{}
-		return err
-	}
-	// if certificate store is configured, return error. Only one of certificate store and key management provider can be configured
-	if len(certificateStoreList.Items) > 0 {
-		// Note: for backwards compatibility in upgrade scenarios, Ratify will only log a warning statement.
-		logger.Warn("Certificate Store already exists. Key management provider and certificate store should not be configured together. Please migrate to key management provider and delete certificate store.")
-	}
-
-	provider, err := cutils.SpecToKeyManagementProvider(keyManagementProvider.Spec.Parameters.Raw, keyManagementProvider.Spec.Type)
-	if err != nil {
-		kmpErr := re.ErrorCodePluginInitFailure.WithError(err).WithDetail("Failed to create key management provider from CR")
-
-		kmp.SetCertificateError(resource, kmpErr)
-		kmp.SetKeyError(resource, kmpErr)
-		writeKMProviderStatusNamespaced(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Result = ctrl.Result{}
-		return kmpErr
-	}
-
-	// fetch certificates and store in map
-	certificates, certAttributes, err := 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", resource, keyManagementProvider.Spec.Type))
-
-		kmp.SetCertificateError(resource, kmpErr)
-		writeKMProviderStatusNamespaced(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Result = ctrl.Result{}
-		return kmpErr
-	}
-
-	// fetch keys and store in map
-	keys, keyAttributes, err := 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", resource, keyManagementProvider.Spec.Type))
-
-		kmp.SetKeyError(resource, kmpErr)
-		writeKMProviderStatusNamespaced(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, &kmpErr, lastFetchedTime, nil)
-		kr.Result = ctrl.Result{}
-		return kmpErr
-	}
-	kmp.SaveSecrets(resource, keyManagementProvider.Spec.Type, keys, certificates)
-	// merge certificates and keys status into one
-	maps.Copy(keyAttributes, certAttributes)
-	isFetchSuccessful = true
-	writeKMProviderStatusNamespaced(ctx, kr, &keyManagementProvider, logger, isFetchSuccessful, nil, lastFetchedTime, keyAttributes)
-
-	logger.Infof("%v certificate(s) & %v key(s) fetched for key management provider %v", len(certificates), len(keys), resource)
-
-	if !provider.IsRefreshable() {
-		kr.Result = ctrl.Result{}
-		return nil
-	}
-
-	// if interval is not set, disable refresh
-	if keyManagementProvider.Spec.RefreshInterval == "" {
-		kr.Result = ctrl.Result{}
-		return nil
-	}
-
-	intervalDuration, err := time.ParseDuration(keyManagementProvider.Spec.RefreshInterval)
-	if err != nil {
-		logger.Error(err, "unable to parse interval duration")
-		kr.Result = ctrl.Result{}
-		return err
-	}
-
-	logger.Info("Reconciled KeyManagementProvider", "intervalDuration", intervalDuration)
-	kr.Result = ctrl.Result{RequeueAfter: intervalDuration}
-
-	return nil
-}
-
-// GetResult returns the result of the refresh as ctrl.Result
-func (kr *KubeRefresherNamespaced) GetResult() interface{} {
-	return kr.Result
-}
-
-// Create creates a new instance of KubeRefresherNamespaced
-func (kr *KubeRefresherNamespaced) Create(config map[string]interface{}) (Refresher, error) {
-	client, ok := config["client"].(client.Client)
-	if !ok {
-		return nil, fmt.Errorf("client is required in config")
-	}
-
-	request, ok := config["request"].(ctrl.Request)
-	if !ok {
-		return nil, fmt.Errorf("request is required in config")
-	}
-
-	return &KubeRefresherNamespaced{
-		Client:  client,
-		Request: request,
-	}, nil
-}
-
-// writeKMProviderStatus updates the status of the key management provider resource
-func writeKMProviderStatusNamespaced(ctx context.Context, r client.StatusClient, keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, logger *logrus.Entry, isSuccess bool, err *re.Error, operationTime metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
-	if isSuccess {
-		updateKMProviderSuccessStatusNamespaced(keyManagementProvider, &operationTime, kmProviderStatus)
-	} else {
-		updateKMProviderErrorStatusNamespaced(keyManagementProvider, err, &operationTime)
-	}
-	if statusErr := r.Status().Update(ctx, keyManagementProvider); statusErr != nil {
-		logger.Error(statusErr, ",unable to update key management provider error status")
-	}
-}
-
-// updateKMProviderErrorStatus updates the key management provider status with error, brief error and last fetched time
-func updateKMProviderErrorStatusNamespaced(keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, err *re.Error, operationTime *metav1.Time) {
-	keyManagementProvider.Status.IsSuccess = false
-	keyManagementProvider.Status.Error = err.Error()
-	keyManagementProvider.Status.BriefError = err.GetConciseError(constants.MaxBriefErrLength)
-	keyManagementProvider.Status.LastFetchedTime = operationTime
-}
-
-// updateKMProviderSuccessStatus updates the key management provider status if status argument is non nil
-// Success status includes last fetched time and other provider-specific properties
-func updateKMProviderSuccessStatusNamespaced(keyManagementProvider *configv1beta1.NamespacedKeyManagementProvider, lastOperationTime *metav1.Time, kmProviderStatus kmp.KeyManagementProviderStatus) {
-	keyManagementProvider.Status.IsSuccess = true
-	keyManagementProvider.Status.Error = ""
-	keyManagementProvider.Status.BriefError = ""
-	keyManagementProvider.Status.LastFetchedTime = lastOperationTime
-
-	if kmProviderStatus != nil {
-		jsonString, _ := json.Marshal(kmProviderStatus)
-
-		raw := runtime.RawExtension{
-			Raw: jsonString,
-		}
-		keyManagementProvider.Status.Properties = raw
-	}
-}
diff --git a/pkg/keymanagementprovider/refresh/refresh.go b/pkg/keymanagementprovider/refresh/refresh.go
index 78e32b1..36e05e2 100644
--- a/pkg/keymanagementprovider/refresh/refresh.go
+++ b/pkg/keymanagementprovider/refresh/refresh.go
@@ -18,11 +18,12 @@ package refresh
 
 import (
 	"context"
+
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
 )
 
 const (
-	KubeRefresherType           = "kubeRefresher"
-	KubeRefresherNamespacedType = "kubeRefresherNamespaced"
+	KubeRefresherType = "kubeRefresher"
 )
 
 // Refresher is an interface that defines methods to be implemented by a each refresher
@@ -31,4 +32,15 @@ type Refresher interface {
 	Refresh(ctx context.Context) error
 	// GetResult is a method that returns the result of the refresh
 	GetResult() interface{}
+	// GetStatus is a method that returns the status of the refresh
+	GetStatus() interface{}
+}
+
+// RefresherConfig is a struct that holds the configuration for a refresher
+type RefresherConfig struct {
+	RefresherType           string                                      // RefresherType is the type of the refresher
+	Provider                keymanagementprovider.KeyManagementProvider // Provider is the key management provider
+	ProviderType            string                                      // ProviderType is the type of the provider
+	ProviderRefreshInterval string                                      // ProviderRefreshInterval is the refresh interval for the provider
+	Resource                string                                      // Resource is the resource to be refreshed
 }
diff --git a/pkg/referrerstore/oras/cosign.go b/pkg/referrerstore/oras/cosign.go
index a60f458..4f6fc24 100644
--- a/pkg/referrerstore/oras/cosign.go
+++ b/pkg/referrerstore/oras/cosign.go
@@ -46,7 +46,7 @@ func getCosignReferences(ctx context.Context, subjectReference common.Reference,
 			return nil, nil
 		}
 		evictOnError(ctx, err, subjectReference.Original)
-		return nil, re.ErrorCodeRepositoryOperationFailure.WithError(err).WithComponentType(re.ReferrerStore)
+		return nil, re.ErrorCodeRepositoryOperationFailure.WithDetail(fmt.Sprintf("Failed to validate existence of Cosign signature of the artifact: %+v", subjectReference)).WithError(err)
 	}
 
 	references = append(references, ocispecs.ReferenceDescriptor{
@@ -64,7 +64,7 @@ func getCosignReferences(ctx context.Context, subjectReference common.Reference,
 func attachedImageTag(subjectReference common.Reference, tagSuffix string) (string, error) {
 	// sha256:d34db33f -> sha256-d34db33f.suffix
 	if subjectReference.Digest.String() == "" {
-		return "", re.ErrorCodeReferenceInvalid.WithComponentType(re.ReferrerStore).WithDetail("Cosign subject digest is empty")
+		return "", re.ErrorCodeReferenceInvalid.WithDetail("The digest of the artifact is empty")
 	}
 	tagStr := strings.ReplaceAll(subjectReference.Digest.String(), ":", "-") + tagSuffix
 	return fmt.Sprintf("%s:%s", subjectReference.Path, tagStr), nil
diff --git a/pkg/referrerstore/oras/oras.go b/pkg/referrerstore/oras/oras.go
index a8462d2..64679dd 100644
--- a/pkg/referrerstore/oras/oras.go
+++ b/pkg/referrerstore/oras/oras.go
@@ -208,7 +208,7 @@ func (store *orasStore) GetConfig() *config.StoreConfig {
 func (store *orasStore) ListReferrers(ctx context.Context, subjectReference common.Reference, _ []string, _ string, subjectDesc *ocispecs.SubjectDescriptor) (referrerstore.ListReferrersResult, error) {
 	repository, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
-		return referrerstore.ListReferrersResult{}, re.ErrorCodeCreateRepositoryFailure.WithError(err).WithComponentType(re.ReferrerStore)
+		return referrerstore.ListReferrersResult{}, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to connect to the remote registry").WithError(err)
 	}
 
 	// resolve subject descriptor if not provided
@@ -260,7 +260,7 @@ func (store *orasStore) GetBlobContent(ctx context.Context, subjectReference com
 
 	repository, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
-		return nil, err
+		return nil, re.ErrorCodeGetBlobContentFailure.WithDetail("Failed to connect to the remote registry").WithError(err)
 	}
 
 	// create a dummy Descriptor to check the local store cache
@@ -292,10 +292,10 @@ func (store *orasStore) GetBlobContent(ctx context.Context, subjectReference com
 		blobDesc, rc, err := repository.Blobs().FetchReference(ctx, ref)
 		if err != nil {
 			evictOnError(ctx, err, subjectReference.Original)
-			return nil, err
+			return nil, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to fetch the artifact metadata from the registry").WithError(err)
 		}
 		if blobContent, err = io.ReadAll(rc); err != nil {
-			return nil, re.ErrorCodeGetBlobContentFailure.WithError(err)
+			return nil, re.ErrorCodeRepositoryOperationFailure.WithDetail("Failed to parse the artifact metadata").WithError(err)
 		}
 
 		// push fetched content to local ORAS cache
diff --git a/pkg/verifier/cosign/cosign.go b/pkg/verifier/cosign/cosign.go
index fb3efd7..8644285 100644
--- a/pkg/verifier/cosign/cosign.go
+++ b/pkg/verifier/cosign/cosign.go
@@ -143,17 +143,17 @@ func (f *cosignVerifierFactory) Create(_ string, verifierConfig config.VerifierC
 	logger.GetLogger(context.Background(), logOpt).Debugf("creating cosign verifier with config %v, namespace '%v'", verifierConfig, namespace)
 	verifierName, hasName := verifierConfig[types.Name].(string)
 	if !hasName {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail("missing name in verifier config")
+		return nil, re.ErrorCodeConfigInvalid.WithDetail("The name field is required in the Cosign Verifier configuration")
 	}
 
 	config, err := parseVerifierConfig(verifierConfig)
 	if err != nil {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName)
+		return nil, re.ErrorCodeConfigInvalid.WithDetail("Failed to create the Cosign Verifier").WithError(err)
 	}
 
 	// if key or rekorURL is provided, trustPolicies should not be provided
 	if (config.KeyRef != "" || config.RekorURL != "") && len(config.TrustPolicies) > 0 {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail("'key' and 'rekorURL' are part of cosign legacy configuration and cannot be used with `trustPolicies`")
+		return nil, re.ErrorCodeConfigInvalid.WithDetail("'key' and 'rekorURL' are part of Cosign legacy configuration and cannot be used with `trustPolicies` parameter")
 	}
 
 	var trustPolicies *TrustPolicies
@@ -163,7 +163,7 @@ func (f *cosignVerifierFactory) Create(_ string, verifierConfig config.VerifierC
 		logger.GetLogger(context.Background(), logOpt).Debugf("legacy cosign verifier configuration not found, creating trust policies")
 		trustPolicies, err = CreateTrustPolicies(config.TrustPolicies, verifierName)
 		if err != nil {
-			return nil, err
+			return nil, re.ErrorCodePluginInitFailure.WithDetail("Failed to create the Cosign Verifier").WithError(err)
 		}
 		legacy = false
 	}
@@ -224,18 +224,18 @@ func (v *cosignVerifier) verifyInternal(ctx context.Context, subjectReference co
 	// get the reference manifest (cosign oci image)
 	referenceManifest, err := referrerStore.GetReferenceManifest(ctx, subjectReference, referenceDescriptor)
 	if err != nil {
-		return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to get reference manifest: %w", err)), nil
+		return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyPluginFailure.WithDetail(fmt.Sprintf("Failed to get Cosign signature metadata for %s", referenceDescriptor.Digest)).WithError(err)), nil
 	}
 
 	// manifest must be an OCI Image
 	if referenceManifest.MediaType != imgspec.MediaTypeImageManifest {
-		return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("reference manifest is not an image")), nil
+		return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyPluginFailure.WithDetail("The artifact metadata is not an OCI image")), nil
 	}
 
 	// get the subject image descriptor
 	subjectDesc, err := referrerStore.GetSubjectDescriptor(ctx, subjectReference)
 	if err != nil {
-		return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to create subject hash: %w", err)), nil
+		return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyReferenceFailure.WithDetail(fmt.Sprintf("Failed to validate the Cosign signature of the artifact: %+v", subjectReference)).WithError(err)), nil
 	}
 
 	// create the hash of the subject image descriptor (used as the hashed payload)
@@ -255,23 +255,23 @@ func (v *cosignVerifier) verifyInternal(ctx context.Context, subjectReference co
 		// fetch the blob content of the signature from the referrer store
 		blobBytes, err := referrerStore.GetBlobContent(ctx, subjectReference, blob.Digest)
 		if err != nil {
-			return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to get blob content: %w", err)), nil
+			return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeGetBlobContentFailure.WithDetail(fmt.Sprintf("Failed to get Cosign signature with digest %s", blob.Digest)).WithError(err)), nil
 		}
 		// convert the blob to a static signature
 		staticOpts, err := staticLayerOpts(blob)
 		if err != nil {
-			return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to parse static signature opts: %w", err)), nil
+			return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyPluginFailure.WithDetail(fmt.Sprintf("Failed to parse Cosign signature with digest %s", blob.Digest)).WithError(err)), nil
 		}
 		sig, err := static.NewSignature(blobBytes, blob.Annotations[static.SignatureAnnotationKey], staticOpts...)
 		if err != nil {
-			return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to generate static signature: %w", err)), nil
+			return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to validate the Cosign signature").WithError(err)), nil
 		}
 		if len(keysMap) > 0 {
 			// if keys are found, perform verification with keys
 			var verifications []cosignExtension
 			verifications, hasValidSignature, err = verifyWithKeys(ctx, keysMap, sig, blob.Annotations[static.SignatureAnnotationKey], blobBytes, staticOpts, &cosignOpts, subjectDescHash)
 			if err != nil {
-				return errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("failed to verify with keys: %w", err)), nil
+				return errorToVerifyResult(v.name, v.verifierType, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to validate the Cosign signature with keys").WithError(err)), nil
 			}
 			extensionListEntry.Verifications = append(extensionListEntry.Verifications, verifications...)
 		} else {
@@ -295,7 +295,7 @@ func (v *cosignVerifier) verifyInternal(ctx context.Context, subjectReference co
 		), nil
 	}
 
-	errorResult := errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("no valid signatures found"))
+	errorResult := errorToVerifyResult(v.name, v.verifierType, fmt.Errorf("no valid Cosign signatures found"))
 	errorResult.Extensions = Extension{SignatureExtension: sigExtensions, TrustPolicy: trustPolicy.GetName()}
 	return errorResult, nil
 }
@@ -485,7 +485,7 @@ func staticLayerOpts(desc imgspec.Descriptor) ([]static.Option, error) {
 
 // ErrorToVerifyResult returns a verifier result with the error message and isSuccess set to false
 func errorToVerifyResult(name string, verifierType string, err error) verifier.VerifierResult {
-	verifierErr := re.ErrorCodeVerifyReferenceFailure.WithDetail("Verification failed").WithError(err)
+	verifierErr := re.ErrorCodeVerifyReferenceFailure.WithDetail("Failed to validate the Cosign signature").WithError(err)
 	return verifier.NewVerifierResult(
 		"",
 		name,
@@ -540,14 +540,14 @@ func verifyWithKeys(ctx context.Context, keysMap map[PKKey]keymanagementprovider
 		if pubKey.ProviderType == azurekeyvault.ProviderName {
 			hashType, sig, err = processAKVSignature(sigEncoded, sig, pubKey.Key, payload, staticOpts)
 			if err != nil {
-				return verifications, false, fmt.Errorf("failed to process AKV signature: %w", err)
+				return verifications, false, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to validate the Cosign signature generated by Azure Key Vault").WithError(err)
 			}
 		}
 
 		// return the correct verifier based on public key type and bytes
 		verifier, err := signature.LoadVerifier(pubKey.Key, hashType)
 		if err != nil {
-			return verifications, false, fmt.Errorf("failed to load public key from provider [%s] name [%s] version [%s]: %w", mapKey.Provider, mapKey.Name, mapKey.Version, err)
+			return verifications, false, re.ErrorCodeVerifyPluginFailure.WithDetail(fmt.Sprintf("Failed to load public key from provider [%s] name [%s] version [%s]", mapKey.Provider, mapKey.Name, mapKey.Version)).WithError(err)
 		}
 		cosignOpts.SigVerifier = verifier
 		// verify signature with cosign options + perform bundle verification
@@ -627,17 +627,17 @@ func processAKVSignature(sigEncoded string, staticSig oci.Signature, publicKey c
 		// EC verifiers in cosign have built in ASN.1 decoding, but RSA verifiers do not
 		base64DecodedBytes, err := base64.StdEncoding.DecodeString(sigEncoded)
 		if err != nil {
-			return crypto.SHA256, nil, fmt.Errorf("RSA key check: failed to decode base64 signature: %w", err)
+			return crypto.SHA256, nil, re.ErrorCodeVerifyPluginFailure.WithDetail("RSA key check: failed to decode base64 signature").WithError(err)
 		}
 		// decode ASN.1 signature to raw signature if it is ASN.1 encoded
 		decodedSigBytes, err := decodeASN1Signature(base64DecodedBytes)
 		if err != nil {
-			return crypto.SHA256, nil, fmt.Errorf("RSA key check: failed to decode ASN.1 signature: %w", err)
+			return crypto.SHA256, nil, re.ErrorCodeVerifyPluginFailure.WithDetail("RSA key check: failed to decode ASN.1 signature").WithError(err)
 		}
 		encodedBase64SigBytes := base64.StdEncoding.EncodeToString(decodedSigBytes)
 		staticSig, err = static.NewSignature(payloadBytes, encodedBase64SigBytes, staticOpts...)
 		if err != nil {
-			return crypto.SHA256, nil, fmt.Errorf("RSA key check: failed to generate static signature: %w", err)
+			return crypto.SHA256, nil, re.ErrorCodeVerifyPluginFailure.WithDetail("RSA key check: failed to generate static signature").WithError(err)
 		}
 	case *ecdsa.PublicKey:
 		switch keyType.Curve {
@@ -648,10 +648,10 @@ func processAKVSignature(sigEncoded string, staticSig oci.Signature, publicKey c
 		case elliptic.P521():
 			hashType = crypto.SHA512
 		default:
-			return crypto.SHA256, nil, fmt.Errorf("ECDSA key check: unsupported key curve: %s", keyType.Params().Name)
+			return crypto.SHA256, nil, fmt.Errorf("ECDSA key check: unsupported key curve [%s]", keyType.Params().Name)
 		}
 	default:
-		return crypto.SHA256, nil, fmt.Errorf("unsupported public key type: %T", publicKey)
+		return crypto.SHA256, nil, fmt.Errorf("unsupported public key type [%T]", publicKey)
 	}
 	return hashType, staticSig, nil
 }
diff --git a/pkg/verifier/cosign/trustpolicies.go b/pkg/verifier/cosign/trustpolicies.go
index 4858cfd..6ba5521 100644
--- a/pkg/verifier/cosign/trustpolicies.go
+++ b/pkg/verifier/cosign/trustpolicies.go
@@ -35,14 +35,14 @@ var validScopeRegex = regexp.MustCompile(`^[a-z0-9\.\-:@\/]*\*?$`)
 // CreateTrustPolicies creates a set of trust policies from the given configuration
 func CreateTrustPolicies(configs []TrustPolicyConfig, verifierName string) (*TrustPolicies, error) {
 	if len(configs) == 0 {
-		return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail("failed to create trust policies: no policies found")
+		return nil, re.ErrorCodeConfigInvalid.WithDetail("Failed to create trust policies: policy configuration not found").WithRemediation("Ensure that the trust policy configuration is correct.")
 	}
 
 	policies := make([]TrustPolicy, 0, len(configs))
 	names := make(map[string]struct{})
 	for _, policyConfig := range configs {
 		if _, ok := names[policyConfig.Name]; ok {
-			return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("failed to create trust policies: duplicate policy name %s", policyConfig.Name))
+			return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: duplicate policy name %s", policyConfig.Name)).WithRemediation("Ensure that trust policy names are unique.")
 		}
 		names[policyConfig.Name] = struct{}{}
 		policy, err := CreateTrustPolicy(policyConfig, verifierName)
@@ -86,7 +86,7 @@ func (tps *TrustPolicies) GetScopedPolicy(reference string) (TrustPolicy, error)
 	if globalPolicy != nil {
 		return globalPolicy, nil
 	}
-	return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to get trust policy: no policy found for reference %s", reference))
+	return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("No policy found for the artifact %s", reference))
 }
 
 // validateScopes validates the scopes in the trust policies
@@ -97,16 +97,16 @@ func validateScopes(policies []TrustPolicy) error {
 		policyName := policy.GetName()
 		scopes := policy.GetScopes()
 		if len(scopes) == 0 {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: no scopes defined for trust policy %s", policyName))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: scope parameter is required for trust policy %s", policyName))
 		}
 		// check for global wildcard character along with other scopes in the same policy
 		if len(scopes) > 1 && slices.Contains(scopes, string(GlobalWildcardCharacter)) {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: global wildcard character %c cannot be used with other scopes within the same trust policy %s", GlobalWildcardCharacter, policyName))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: global wildcard character %c cannot be used with other scopes within the same trust policy %s", GlobalWildcardCharacter, policyName))
 		}
 		// check for duplicate global wildcard characters across policies
 		if slices.Contains(scopes, string(GlobalWildcardCharacter)) {
 			if hasGlobalWildcard {
-				return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: global wildcard character %c can only be used once", GlobalWildcardCharacter))
+				return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: global wildcard character %c can only be used once", GlobalWildcardCharacter))
 			}
 			hasGlobalWildcard = true
 			continue
@@ -114,15 +114,15 @@ func validateScopes(policies []TrustPolicy) error {
 		for _, scope := range scopes {
 			// check for empty scope
 			if scope == "" {
-				return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: scope defined is empty for trust policy %s", policyName))
+				return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: scope value cannot be empty in trust policy %s", policyName))
 			}
 			// check scope is formatted correctly
 			if !validScopeRegex.MatchString(scope) {
-				return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: invalid scope %s for trust policy %s", scope, policyName))
+				return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: invalid scope %s for trust policy %s", scope, policyName))
 			}
 			// check for duplicate scopes
 			if _, ok := scopesMap[scope]; ok {
-				return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: duplicate scope %s for trust policy %s", scope, policyName))
+				return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: duplicate scope %s for trust policy %s", scope, policyName))
 			}
 			// check wildcard overlaps
 			for existingScope := range scopesMap {
@@ -144,7 +144,7 @@ func validateScopes(policies []TrustPolicy) error {
 					isConflict = strings.HasPrefix(existingScope, trimmedScope)
 				}
 				if isConflict {
-					return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithDetail(fmt.Sprintf("failed to create trust policies: overlapping scopes %s and %s for trust policy %s", scope, existingScope, policyName))
+					return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Failed to create trust policies: overlapping scopes %s and %s for trust policy %s", scope, existingScope, policyName))
 				}
 			}
 			scopesMap[scope] = struct{}{}
diff --git a/pkg/verifier/cosign/trustpolicy.go b/pkg/verifier/cosign/trustpolicy.go
index c49b86a..8d20a73 100644
--- a/pkg/verifier/cosign/trustpolicy.go
+++ b/pkg/verifier/cosign/trustpolicy.go
@@ -97,7 +97,7 @@ func CreateTrustPolicy(config TrustPolicyConfig, verifierName string) (TrustPoli
 		config.Version = DefaultTrustPolicyConfigVersion
 	}
 
-	if err := validate(config, verifierName); err != nil {
+	if err := validate(config); err != nil {
 		return nil, err
 	}
 
@@ -107,7 +107,7 @@ func CreateTrustPolicy(config TrustPolicyConfig, verifierName string) (TrustPoli
 		if keyConfig.File != "" {
 			pubKey, err := loadKeyFromPath(keyConfig.File)
 			if err != nil {
-				return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: failed to load key from file %s", config.Name, keyConfig.File)).WithError(err)
+				return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy [%s]: failed to load the key from file %s", config.Name, keyConfig.File)).WithError(err).WithRemediation("Ensure that the key file path is correct and public key is correctly saved.")
 			}
 			keyMap[PKKey{Provider: fileProviderName, Name: keyConfig.File}] = keymanagementprovider.PublicKey{Key: pubKey, ProviderType: fileProviderName}
 		}
@@ -155,13 +155,13 @@ func (tp *trustPolicy) GetKeys(ctx context.Context, _ string) (map[PKKey]keymana
 		// get the key management provider resource which contains a map of keys
 		kmpResource, kmpErr := keymanagementprovider.GetKeysFromMap(ctx, keyConfig.Provider)
 		if kmpErr != nil {
-			return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(tp.verifierName).WithDetail(fmt.Sprintf("trust policy [%s] failed to access key management provider %s, err: %s", tp.config.Name, keyConfig.Provider, kmpErr.Error()))
+			return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy [%s]: failed to access key management provider %s", tp.config.Name, keyConfig.Provider)).WithError(kmpErr)
 		}
 		// get a specific key from the key management provider resource
 		if keyConfig.Name != "" {
 			pubKey, exists := kmpResource[keymanagementprovider.KMPMapKey{Name: keyConfig.Name, Version: keyConfig.Version}]
 			if !exists {
-				return nil, re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(tp.verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: key %s with version %s not found in key management provider %s", tp.config.Name, keyConfig.Name, keyConfig.Version, keyConfig.Provider))
+				return nil, re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy [%s]: key %s with version %s not found in key management provider %s", tp.config.Name, keyConfig.Name, keyConfig.Version, keyConfig.Provider))
 			}
 			keyMap[PKKey{Provider: keyConfig.Provider, Name: keyConfig.Name, Version: keyConfig.Version}] = pubKey
 		} else {
@@ -188,12 +188,12 @@ func (tp *trustPolicy) GetCosignOpts(ctx context.Context) (cosign.CheckOpts, err
 		// create the rekor client
 		cosignOpts.RekorClient, err = rekor.NewClient(tp.config.RekorURL)
 		if err != nil {
-			return cosignOpts, fmt.Errorf("failed to create Rekor client from URL %s: %w", tp.config.RekorURL, err)
+			return cosignOpts, re.ErrorCodeConfigInvalid.WithDetail(fmt.Errorf("Failed to create Rekor client from URL %s", tp.config.RekorURL)).WithRemediation("Ensure that the Rekor URL is valid.").WithError(err)
 		}
 		// Fetches the Rekor public keys from the Rekor server
 		cosignOpts.RekorPubKeys, err = cosign.GetRekorPubs(ctx)
 		if err != nil {
-			return cosignOpts, fmt.Errorf("failed to fetch Rekor public keys: %w", err)
+			return cosignOpts, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to fetch Rekor public keys").WithRemediation(fmt.Sprintf("Please check if the Rekor server %s is available", tp.config.RekorURL)).WithError(err)
 		}
 	} else {
 		cosignOpts.IgnoreTlog = true
@@ -203,20 +203,20 @@ func (tp *trustPolicy) GetCosignOpts(ctx context.Context) (cosign.CheckOpts, err
 	if tp.isKeyless {
 		roots, err := fulcio.GetRoots()
 		if err != nil || roots == nil {
-			return cosignOpts, fmt.Errorf("failed to get fulcio roots: %w", err)
+			return cosignOpts, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to get fulcio root").WithError(err).WithRemediation("Please check if Fulcio is available")
 		}
 		cosignOpts.RootCerts = roots
 		if tp.config.Keyless.CTLogVerify != nil && *tp.config.Keyless.CTLogVerify {
 			cosignOpts.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
 			if err != nil {
-				return cosignOpts, fmt.Errorf("failed to fetch certificate transparency log public keys: %w", err)
+				return cosignOpts, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to fetch certificate transparency log public keys").WithError(err).WithRemediation("Please check if TUF root is available")
 			}
 		} else {
 			cosignOpts.IgnoreSCT = true
 		}
 		cosignOpts.IntermediateCerts, err = fulcio.GetIntermediates()
 		if err != nil {
-			return cosignOpts, fmt.Errorf("failed to get fulcio intermediate certificates: %w", err)
+			return cosignOpts, re.ErrorCodeVerifyPluginFailure.WithDetail("Failed to get fulcio intermediate certificates").WithError(err).WithRemediation("Please check if Fulcio is available")
 		}
 		// Set the certificate identity and issuer for keyless verification
 		cosignOpts.Identities = []cosign.Identity{
@@ -234,42 +234,42 @@ func (tp *trustPolicy) GetCosignOpts(ctx context.Context) (cosign.CheckOpts, err
 
 // validate checks if the trust policy configuration is valid
 // returns an error if the configuration is invalid
-func validate(config TrustPolicyConfig, verifierName string) error {
+func validate(config TrustPolicyConfig) error {
 	// check if the trust policy version is supported
 	if !slices.Contains(SupportedTrustPolicyConfigVersions, config.Version) {
-		return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: unsupported version %s", config.Name, config.Version))
+		return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: unsupported version %s", config.Name, config.Version)).WithRemediation(fmt.Sprintf("Supported versions are: %v", SupportedTrustPolicyConfigVersions))
 	}
 
 	if config.Name == "" {
-		return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail("missing trust policy name")
+		return re.ErrorCodeConfigInvalid.WithDetail("name parameter is required in trust policy configuration").WithRemediation("Please provide a name for the trust policy.")
 	}
 
 	if len(config.Scopes) == 0 {
-		return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: no scopes defined", config.Name))
+		return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("scopes parameter is required in trust policy configuration %s", config.Name)).WithRemediation("Please provide at least one scope for the trust policy.")
 	}
 
 	// keys or keyless must be defined
 	if len(config.Keys) == 0 && config.Keyless == (KeylessConfig{}) {
-		return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: no keys defined and keyless section not configured", config.Name))
+		return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("keys or keyless parameter is required in trust policy configuration %s", config.Name))
 	}
 
 	// only one of keys or keyless can be defined
 	if len(config.Keys) > 0 && config.Keyless != (KeylessConfig{}) {
-		return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: both keys and keyless sections are defined", config.Name))
+		return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Only one of keys or keyless parameter is required in trust policy configuration %s", config.Name))
 	}
 
 	for _, keyConfig := range config.Keys {
 		// check if the key is defined by file path or by key management provider
 		if keyConfig.File == "" && keyConfig.Provider == "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: key management provider name is required when not using file path", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: key management provider name is required when not using file path", config.Name))
 		}
 		// both file path and key management provider cannot be defined together
 		if keyConfig.File != "" && keyConfig.Provider != "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: 'name' and 'file' cannot be configured together", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: 'name' and 'file' cannot be configured together", config.Name))
 		}
 		// key name is required when key version is defined
 		if keyConfig.Version != "" && keyConfig.Name == "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: key name is required when key version is defined", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: key name is required when key version is defined", config.Name))
 		}
 	}
 
@@ -277,19 +277,19 @@ func validate(config TrustPolicyConfig, verifierName string) error {
 	if config.Keyless != (KeylessConfig{}) {
 		// validate certificate identity specified
 		if config.Keyless.CertificateIdentity == "" && config.Keyless.CertificateIdentityRegExp == "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: certificate identity or identity regex pattern is required", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: certificate identity or identity regex pattern is required", config.Name))
 		}
 		// validate certificate OIDC issuer specified
 		if config.Keyless.CertificateOIDCIssuer == "" && config.Keyless.CertificateOIDCIssuerRegExp == "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: certificate OIDC issuer or issuer regex pattern is required", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: certificate OIDC issuer or issuer regex pattern is required", config.Name))
 		}
 		// validate only expression or value is specified for certificate identity
 		if config.Keyless.CertificateIdentity != "" && config.Keyless.CertificateIdentityRegExp != "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: only one of certificate identity or identity regex pattern should be specified", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: only one of certificate identity or identity regex pattern should be specified", config.Name))
 		}
 		// validate only expression or value is specified for certificate OIDC issuer
 		if config.Keyless.CertificateOIDCIssuer != "" && config.Keyless.CertificateOIDCIssuerRegExp != "" {
-			return re.ErrorCodeConfigInvalid.WithComponentType(re.Verifier).WithPluginName(verifierName).WithDetail(fmt.Sprintf("trust policy %s failed: only one of certificate OIDC issuer or issuer regex pattern should be specified", config.Name))
+			return re.ErrorCodeConfigInvalid.WithDetail(fmt.Sprintf("Invalid trust policy %s: only one of certificate OIDC issuer or issuer regex pattern should be specified", config.Name))
 		}
 	}
 
diff --git a/pkg/verifier/notation/notation.go b/pkg/verifier/notation/notation.go
index f25b21c..e825db1 100644
--- a/pkg/verifier/notation/notation.go
+++ b/pkg/verifier/notation/notation.go
@@ -237,7 +237,10 @@ func normalizeVerificationCertsStores(conf *NotationPluginVerifierConfig) error
 		}
 	}
 	if isCertStoresByType && isLegacyCertStore {
-		return re.ErrorCodeConfigInvalid.WithDetail("The verificationCertStores is misconfigured with both legacy and new formats").WithRemediation("Please provide only one format for the VerificationCertStores. Refer to the Notation Verifier configuration guide: https://ratify.dev/docs/plugins/verifier/notation#configuration")
+		// 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 {


Test patch:
diff --git a/.github/workflows/e2e-aks.yml b/.github/workflows/e2e-aks.yml
index a202673..f6a2c1f 100644
--- a/.github/workflows/e2e-aks.yml
+++ b/.github/workflows/e2e-aks.yml
@@ -7,14 +7,14 @@ on:
   workflow_call:
     inputs:
       k8s_version:
-        description: 'Kubernetes version'
+        description: "Kubernetes version"
         required: true
-        default: '1.29.2'
+        default: "1.29.2"
         type: string
       gatekeeper_version:
-        description: 'Gatekeeper version'
+        description: "Gatekeeper version"
         required: true
-        default: '3.16.0'
+        default: "3.17.0"
         type: string
 
 jobs:
@@ -28,7 +28,7 @@ jobs:
       contents: read
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -37,7 +37,7 @@ jobs:
       - name: Set up Go 1.22
         uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
       - name: Az CLI login
         uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
         with:
@@ -69,4 +69,4 @@ jobs:
         with:
           name: e2e-logs-aks-${{ inputs.k8s_version }}-${{ inputs.gatekeeper_version }}
           path: |
-            logs-*.json
\ No newline at end of file
+            logs-*.json
diff --git a/.github/workflows/e2e-cli.yml b/.github/workflows/e2e-cli.yml
index 324de26..6703844 100644
--- a/.github/workflows/e2e-cli.yml
+++ b/.github/workflows/e2e-cli.yml
@@ -14,7 +14,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -29,13 +29,12 @@ jobs:
         uses: apache/skywalking-eyes/dependency@cd7b195c51fd3d6ad52afceb760719ddc6b3ee91
         with:
           config: .github/licenserc.yml
-          flags:
-            --weak-compatible=true
+          flags: --weak-compatible=true
   build:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -64,7 +63,7 @@ jobs:
       contents: read
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -89,10 +88,10 @@ jobs:
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
   markdown-link-check:
-      runs-on: ubuntu-latest
-      steps:
+    runs-on: ubuntu-latest
+    steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -103,7 +102,7 @@ jobs:
       - name: Run link check
         uses: gaurav-nelson/github-action-markdown-link-check@d53a906aa6b22b8979d33bc86170567e619495ec #3.10.3
         with:
-          use-quiet-mode: 'no'
-          use-verbose-mode: 'yes'
-          config-file: '.github/workflows/markdown.links.config.json'
-          folder-path: 'docs/'
\ No newline at end of file
+          use-quiet-mode: "no"
+          use-verbose-mode: "yes"
+          config-file: ".github/workflows/markdown.links.config.json"
+          folder-path: "docs/"
diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml
index 57a04b6..717ff93 100644
--- a/.github/workflows/e2e-k8s.yml
+++ b/.github/workflows/e2e-k8s.yml
@@ -7,14 +7,14 @@ on:
   workflow_call:
     inputs:
       k8s_version:
-        description: 'Kubernetes version'
+        description: "Kubernetes version"
         required: true
-        default: '1.29.2'
+        default: "1.29.2"
         type: string
       gatekeeper_version:
-        description: 'Gatekeeper version'
+        description: "Gatekeeper version"
         required: true
-        default: '3.16.0'
+        default: "3.17.0"
         type: string
 
 jobs:
@@ -26,7 +26,7 @@ jobs:
       contents: read
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
+        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
         with:
           egress-policy: audit
 
@@ -35,7 +35,7 @@ jobs:
       - name: Set up Go 1.22
         uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
         with:
-          go-version: '1.22'
+          go-version: "1.22"
 
       - name: Bootstrap e2e
         run: |
@@ -70,4 +70,4 @@ jobs:
         with:
           name: e2e-logs-${{ inputs.k8s_version }}-${{ inputs.gatekeeper_version }}
           path: |
-            logs-*.json
\ No newline at end of file
+            logs-*.json
diff --git a/pkg/controllers/clusterresource/keymanagementprovider_controller_test.go b/pkg/controllers/clusterresource/keymanagementprovider_controller_test.go
index d4129e2..60254ee 100644
--- a/pkg/controllers/clusterresource/keymanagementprovider_controller_test.go
+++ b/pkg/controllers/clusterresource/keymanagementprovider_controller_test.go
@@ -18,82 +18,357 @@ package clusterresource
 import (
 	"context"
 	"errors"
+	"fmt"
 	"reflect"
 	"testing"
 
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider/refresh"
+	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider/mocks"
 	test "github.com/ratify-project/ratify/pkg/utils"
+	"github.com/sirupsen/logrus"
+
+	re "github.com/ratify-project/ratify/errors"
+	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider/refresh"
+
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/types"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
-func TestKeyManagementProviderReconciler_ReconcileWithConfig(t *testing.T) {
+func init() {
+	refresh.Register("mockRefresher", &MockRefresher{})
+}
+
+type MockRefresher struct {
+	Result       ctrl.Result
+	RefreshError bool
+	ResultError  bool
+	StatusError  bool
+	Status       kmp.KeyManagementProviderStatus
+}
+
+func (mr *MockRefresher) Refresh(_ context.Context) error {
+	if mr.RefreshError {
+		return errors.New("error from refresh")
+	}
+	return nil
+}
+
+func (mr *MockRefresher) GetResult() interface{} {
+	if mr.ResultError {
+		return errors.New("error from result")
+	}
+	return mr.Result
+}
+
+func (mr *MockRefresher) GetStatus() interface{} {
+	if mr.StatusError {
+		return errors.New("error from status")
+	}
+	return mr.Status
+}
+
+func (mr *MockRefresher) Create(config refresh.RefresherConfig) (refresh.Refresher, error) {
+	if config.Resource == "refreshError" {
+		return &MockRefresher{
+			RefreshError: true,
+		}, nil
+	}
+	if config.Resource == "resultError" {
+		return &MockRefresher{
+			ResultError: true,
+		}, nil
+	}
+	if config.Resource == "statusError" {
+		return &MockRefresher{
+			StatusError: true,
+		}, nil
+	}
+	return &MockRefresher{}, nil
+}
+
+func TestKeyManagementProviderReconciler_ReconcileWithType(t *testing.T) {
 	tests := []struct {
-		name              string
-		refresherType     string
-		createConfigError bool
-		refreshError      bool
-		expectedError     bool
+		name           string
+		clientGetFunc  func(_ context.Context, key types.NamespacedName, obj client.Object) error
+		clientListFunc func(_ context.Context, list client.ObjectList) error
+		resourceName   string
+		refresherType  string
+		expectedResult ctrl.Result
+		expectedError  bool
 	}{
 		{
-			name:              "Successful Reconcile",
-			refresherType:     "mockRefresher",
-			createConfigError: false,
-			refreshError:      false,
-			expectedError:     false,
+			// TODO: Add SetLogger to internal/logger/logger.go to compare log messages
+			// https://maxchadwick.xyz/blog/testing-log-output-in-go-logrus
+			name: "api is not found",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				resource := schema.GroupResource{
+					Group:    "",     // Use an empty string for core resources (like Pod)
+					Resource: "pods", // Resource type, e.g., "pods" for Pod resources
+				}
+				return apierrors.NewNotFound(resource, "test")
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  false,
+		},
+		{
+			name: "unable to fetch key management provider",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				return fmt.Errorf("unable to fetch key management provider")
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  false,
+		},
+		{
+			name: "unable to list certificate stores",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return fmt.Errorf("unable to list certificate stores")
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
+		},
+		{
+			name: "certificate store already exists",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, list client.ObjectList) error {
+				certStoreList, ok := list.(*configv1beta1.CertificateStoreList)
+				if !ok {
+					return errors.New("expected CertificateStoreList")
+				}
+
+				certStoreList.Items = []configv1beta1.CertificateStore{
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "test",
+						},
+					},
+				}
+				return nil
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  false,
+		},
+		{
+			name: "cutils.SpecToKeyManagementProvider failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
+		},
+		{
+			name: "refresh.CreateRefresherFromConfig failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			refresherType:  "invalidRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
+		},
+		{
+			name: "refresh.Refresh failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceName:   "refreshError",
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
 		},
 		{
-			name:              "Refresher Error",
-			refresherType:     "mockRefresher",
-			createConfigError: false,
-			refreshError:      true,
-			expectedError:     true,
+			name: "refresher.GetResult failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceName:   "resultError",
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
 		},
 		{
-			name:              "Invalid Refresher Type",
-			refresherType:     "invalidRefresher",
-			createConfigError: true,
-			refreshError:      false,
-			expectedError:     true,
+			name: "refresher.GetStatus failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceName:   "statusError",
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  true,
+		},
+		{
+			name: "successfully reconciled",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.KeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.KeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			refresherType:  "mockRefresher",
+			expectedResult: ctrl.Result{},
+			expectedError:  false,
 		},
 	}
+
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			req := ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Name:      "fake-name",
-					Namespace: "fake-namespace",
-				},
-			}
-			scheme, _ := test.CreateScheme()
-			client := fake.NewClientBuilder().WithScheme(scheme).Build()
+		fmt.Println(tt.name)
+		mockClient := mocks.TestClient{
+			GetFunc:  tt.clientGetFunc,
+			ListFunc: tt.clientListFunc,
+		}
+		req := ctrl.Request{
+			NamespacedName: client.ObjectKey{
+				Name:      tt.resourceName,
+				Namespace: "test",
+			},
+		}
+		scheme, _ := test.CreateScheme()
 
-			r := &KeyManagementProviderReconciler{
-				Client: client,
-				Scheme: runtime.NewScheme(),
-			}
+		r := &KeyManagementProviderReconciler{
+			Client: &mockClient,
+			Scheme: scheme,
+		}
 
-			refresherConfig := map[string]interface{}{
-				"type":              tt.refresherType,
-				"client":            client,
-				"request":           req,
-				"createConfigError": tt.createConfigError,
-				"refreshError":      tt.refreshError,
-				"shouldError":       tt.expectedError,
-			}
+		result, err := r.ReconcileWithType(context.Background(), req, tt.refresherType)
 
-			_, err := r.ReconcileWithConfig(context.TODO(), refresherConfig)
-			if tt.expectedError && err == nil {
-				t.Errorf("Expected error, got nil")
-			}
-			if !tt.expectedError && err != nil {
-				t.Errorf("Expected no error, got %v", err)
-			}
-		})
+		if !reflect.DeepEqual(result, tt.expectedResult) {
+			t.Fatalf("Expected result %v, got %v", tt.expectedResult, result)
+		}
+		if tt.expectedError && err == nil {
+			t.Fatalf("Expected error, got nil")
+		}
 	}
 }
+
 func TestKeyManagementProviderReconciler_Reconcile(t *testing.T) {
 	req := ctrl.Request{
 		NamespacedName: client.ObjectKey{
@@ -124,36 +399,150 @@ func TestKeyManagementProviderReconciler_Reconcile(t *testing.T) {
 	}
 }
 
-type MockRefresher struct {
-	Results           ctrl.Result
-	CreateConfigError bool
-	RefreshError      bool
-	ShouldError       bool
-}
+// TestUpdateErrorStatus tests the updateErrorStatus method
+func TestKMProviderUpdateErrorStatus(t *testing.T) {
+	var parametersString = "{\"certs\":{\"name\":\"certName\"}}"
+	var kmProviderStatus = []byte(parametersString)
 
-func (mr *MockRefresher) Refresh(_ context.Context) error {
-	if mr.RefreshError {
-		return errors.New("refresh error")
+	status := configv1beta1.KeyManagementProviderStatus{
+		IsSuccess: true,
+		Properties: runtime.RawExtension{
+			Raw: kmProviderStatus,
+		},
+	}
+	keyManagementProvider := configv1beta1.KeyManagementProvider{
+		Status: status,
+	}
+	expectedErr := re.ErrorCodeUnknown.WithDetail("it's a long error from unit test")
+	lastFetchedTime := metav1.Now()
+	updateKMProviderErrorStatus(&keyManagementProvider, &expectedErr, &lastFetchedTime)
+
+	if keyManagementProvider.Status.IsSuccess != false {
+		t.Fatalf("Unexpected error, expected isSuccess to be false , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != expectedErr.Error() {
+		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr, keyManagementProvider.Status.Error)
+	}
+	if keyManagementProvider.Status.BriefError != expectedErr.GetConciseError(150) {
+		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr.GetConciseError(150), keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was not overridden
+	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
+		t.Fatalf("Unexpected properties,  expected %+v, got %+v", parametersString, string(keyManagementProvider.Status.Properties.Raw))
 	}
-	return nil
 }
 
-func (mr *MockRefresher) GetResult() interface{} {
-	return ctrl.Result{}
+// TestKMProviderUpdateSuccessStatus tests the updateSuccessStatus method
+func TestKMProviderUpdateSuccessStatus(t *testing.T) {
+	kmProviderStatus := keymanagementprovider.KeyManagementProviderStatus{}
+	properties := map[string]string{}
+	properties["Name"] = "wabbit"
+	properties["Version"] = "ABC"
+
+	kmProviderStatus["Certificates"] = properties
+
+	lastFetchedTime := metav1.Now()
+
+	status := configv1beta1.KeyManagementProviderStatus{
+		IsSuccess: false,
+		Error:     "error from last operation",
+	}
+	keyManagementProvider := configv1beta1.KeyManagementProvider{
+		Status: status,
+	}
+
+	updateKMProviderSuccessStatus(&keyManagementProvider, &lastFetchedTime, kmProviderStatus)
+
+	if keyManagementProvider.Status.IsSuccess != true {
+		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != "" {
+		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was updated
+	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
+		t.Fatalf("Properties should not be empty")
+	}
 }
 
-func (mr *MockRefresher) Create(config map[string]interface{}) (refresh.Refresher, error) {
-	createConfigError := config["createConfigError"].(bool)
-	refreshError := config["refreshError"].(bool)
-	if createConfigError {
-		return nil, errors.New("create error")
+// TestKMProviderUpdateSuccessStatus tests the updateSuccessStatus method with empty properties
+func TestKMProviderUpdateSuccessStatus_emptyProperties(t *testing.T) {
+	lastFetchedTime := metav1.Now()
+	status := configv1beta1.KeyManagementProviderStatus{
+		IsSuccess: false,
+		Error:     "error from last operation",
+	}
+	keyManagementProvider := configv1beta1.KeyManagementProvider{
+		Status: status,
+	}
+
+	updateKMProviderSuccessStatus(&keyManagementProvider, &lastFetchedTime, nil)
+
+	if keyManagementProvider.Status.IsSuccess != true {
+		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != "" {
+		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was updated
+	if len(keyManagementProvider.Status.Properties.Raw) != 0 {
+		t.Fatalf("Properties should be empty")
 	}
-	return &MockRefresher{
-		CreateConfigError: createConfigError,
-		RefreshError:      refreshError,
-	}, nil
 }
+func TestWriteKMProviderStatus(t *testing.T) {
+	logger := logrus.WithContext(context.Background())
+	lastFetchedTime := metav1.Now()
+	testCases := []struct {
+		name              string
+		isSuccess         bool
+		kmProvider        *configv1beta1.KeyManagementProvider
+		errString         string
+		expectedErrString string
+		reconciler        client.StatusClient
+	}{
+		{
+			name:       "success status",
+			isSuccess:  true,
+			errString:  "",
+			kmProvider: &configv1beta1.KeyManagementProvider{},
+			reconciler: &test.MockStatusClient{},
+		},
+		{
+			name:              "error status",
+			isSuccess:         false,
+			kmProvider:        &configv1beta1.KeyManagementProvider{},
+			errString:         "a long error string that exceeds the max length of 150 characters",
+			expectedErrString: "UNKNOWN: a long error string that exceeds the max length of 150 characters",
+			reconciler:        &test.MockStatusClient{},
+		},
+		{
+			name:       "status update failed",
+			isSuccess:  true,
+			kmProvider: &configv1beta1.KeyManagementProvider{},
+			reconciler: &test.MockStatusClient{
+				UpdateFailed: true,
+			},
+		},
+	}
 
-func init() {
-	refresh.Register("mockRefresher", &MockRefresher{})
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			err := re.ErrorCodeUnknown.WithDetail(tc.errString)
+			writeKMProviderStatus(context.Background(), tc.reconciler, tc.kmProvider, logger, tc.isSuccess, &err, lastFetchedTime, nil)
+
+			if tc.kmProvider.Status.IsSuccess != tc.isSuccess {
+				t.Fatalf("Expected isSuccess to be: %+v, actual: %+v", tc.isSuccess, tc.kmProvider.Status.IsSuccess)
+			}
+
+			if tc.kmProvider.Status.Error != tc.expectedErrString {
+				t.Fatalf("Expected Error to be: %+v, actual: %+v", tc.expectedErrString, tc.kmProvider.Status.Error)
+			}
+		})
+	}
 }
diff --git a/pkg/controllers/namespaceresource/keymanagementprovider_controller_test.go b/pkg/controllers/namespaceresource/keymanagementprovider_controller_test.go
index 7e4717a..d934754 100644
--- a/pkg/controllers/namespaceresource/keymanagementprovider_controller_test.go
+++ b/pkg/controllers/namespaceresource/keymanagementprovider_controller_test.go
@@ -18,80 +18,358 @@ package namespaceresource
 import (
 	"context"
 	"errors"
+	"fmt"
 	"reflect"
 	"testing"
 
+	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
+	re "github.com/ratify-project/ratify/errors"
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
+	kmp "github.com/ratify-project/ratify/pkg/keymanagementprovider"
+	"github.com/ratify-project/ratify/pkg/keymanagementprovider/mocks"
 	"github.com/ratify-project/ratify/pkg/keymanagementprovider/refresh"
 	test "github.com/ratify-project/ratify/pkg/utils"
+	"github.com/sirupsen/logrus"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/types"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
-func TestKeyManagementProviderReconciler_ReconcileWithConfig(t *testing.T) {
+func init() {
+	refresh.Register("mockRefresher", &MockRefresher{})
+}
+
+type MockRefresher struct {
+	Result       ctrl.Result
+	RefreshError bool
+	ResultError  bool
+	StatusError  bool
+	Status       kmp.KeyManagementProviderStatus
+}
+
+func (mr *MockRefresher) Refresh(_ context.Context) error {
+	if mr.RefreshError {
+		return errors.New("error from refresh")
+	}
+	return nil
+}
+
+func (mr *MockRefresher) GetResult() interface{} {
+	if mr.ResultError {
+		return errors.New("error from result")
+	}
+	return mr.Result
+}
+
+func (mr *MockRefresher) GetStatus() interface{} {
+	if mr.StatusError {
+		return errors.New("error from status")
+	}
+	return mr.Status
+}
+
+func (mr *MockRefresher) Create(config refresh.RefresherConfig) (refresh.Refresher, error) {
+	if config.Resource == "refreshError/test" {
+		return &MockRefresher{
+			RefreshError: true,
+		}, nil
+	}
+	if config.Resource == "resultError/test" {
+		return &MockRefresher{
+			ResultError: true,
+		}, nil
+	}
+	if config.Resource == "statusError/test" {
+		return &MockRefresher{
+			StatusError: true,
+		}, nil
+	}
+	return &MockRefresher{}, nil
+}
+func TestKeyManagementProviderReconciler_ReconcileWithType(t *testing.T) {
 	tests := []struct {
 		name              string
+		clientGetFunc     func(_ context.Context, key types.NamespacedName, obj client.Object) error
+		clientListFunc    func(_ context.Context, list client.ObjectList) error
+		resourceNamespace string
 		refresherType     string
-		createConfigError bool
-		refreshError      bool
+		expectedResult    ctrl.Result
 		expectedError     bool
 	}{
 		{
-			name:              "Successful Reconcile",
+			// TODO: Add SetLogger to internal/logger/logger.go to compare log messages
+			// https://maxchadwick.xyz/blog/testing-log-output-in-go-logrus
+			name: "api is not found",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				resource := schema.GroupResource{
+					Group:    "",     // Use an empty string for core resources (like Pod)
+					Resource: "pods", // Resource type, e.g., "pods" for Pod resources
+				}
+				return apierrors.NewNotFound(resource, "test")
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "test",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     false,
+		},
+		{
+			name: "unable to fetch key management provider",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				return fmt.Errorf("unable to fetch key management provider")
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "test",
 			refresherType:     "mockRefresher",
-			createConfigError: false,
-			refreshError:      false,
+			expectedResult:    ctrl.Result{},
 			expectedError:     false,
 		},
 		{
-			name:              "Refresher Error",
+			name: "unable to list certificate stores",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, _ client.Object) error {
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return fmt.Errorf("unable to list certificate stores")
+			},
+			resourceNamespace: "test",
 			refresherType:     "mockRefresher",
-			createConfigError: false,
-			refreshError:      true,
+			expectedResult:    ctrl.Result{},
 			expectedError:     true,
 		},
 		{
-			name:              "Invalid Refresher Type",
+			name: "certificate store already exists",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, list client.ObjectList) error {
+				certStoreList, ok := list.(*configv1beta1.CertificateStoreList)
+				if !ok {
+					return errors.New("expected CertificateStoreList")
+				}
+
+				certStoreList.Items = []configv1beta1.CertificateStore{
+					{
+						ObjectMeta: metav1.ObjectMeta{
+							Name: "test",
+						},
+					},
+				}
+				return nil
+			},
+			resourceNamespace: "test",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     false,
+		},
+		{
+			name: "cutils.SpecToKeyManagementProvider failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "test",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     true,
+		},
+		{
+			name: "refresh.CreateRefresherFromConfig failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "test",
 			refresherType:     "invalidRefresher",
-			createConfigError: true,
-			refreshError:      false,
+			expectedResult:    ctrl.Result{},
+			expectedError:     true,
+		},
+		{
+			name: "refresh.Refresh failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "refreshError",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     true,
+		},
+		{
+			name: "refresher.GetResult failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "resultError",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     true,
+		},
+		{
+			name: "refresher.GetStatus failed",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "statusError",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
 			expectedError:     true,
 		},
+		{
+			name: "successfully reconciled",
+			clientGetFunc: func(_ context.Context, _ types.NamespacedName, obj client.Object) error {
+				getKMP, ok := obj.(*configv1beta1.NamespacedKeyManagementProvider)
+				if !ok {
+					return errors.New("expected KeyManagementProvider")
+				}
+				getKMP.ObjectMeta = metav1.ObjectMeta{
+					Namespace: "test",
+					Name:      "test",
+				}
+				getKMP.Spec = configv1beta1.NamespacedKeyManagementProviderSpec{
+					Type: "inline",
+					Parameters: runtime.RawExtension{
+						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
+					},
+				}
+				return nil
+			},
+			clientListFunc: func(_ context.Context, _ client.ObjectList) error {
+				return nil
+			},
+			resourceNamespace: "test",
+			refresherType:     "mockRefresher",
+			expectedResult:    ctrl.Result{},
+			expectedError:     false,
+		},
 	}
+
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			req := ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Name:      "fake-name",
-					Namespace: "fake-namespace",
-				},
-			}
-			scheme, _ := test.CreateScheme()
-			client := fake.NewClientBuilder().WithScheme(scheme).Build()
+		fmt.Println(tt.name)
+		mockClient := mocks.TestClient{
+			GetFunc:  tt.clientGetFunc,
+			ListFunc: tt.clientListFunc,
+		}
+		req := ctrl.Request{
+			NamespacedName: client.ObjectKey{
+				Name:      "test",
+				Namespace: tt.resourceNamespace,
+			},
+		}
+		scheme, _ := test.CreateScheme()
 
-			r := &KeyManagementProviderReconciler{
-				Client: client,
-				Scheme: runtime.NewScheme(),
-			}
+		r := &KeyManagementProviderReconciler{
+			Client: &mockClient,
+			Scheme: scheme,
+		}
 
-			refresherConfig := map[string]interface{}{
-				"type":              tt.refresherType,
-				"client":            client,
-				"request":           req,
-				"createConfigError": tt.createConfigError,
-				"refreshError":      tt.refreshError,
-				"shouldError":       tt.expectedError,
-			}
+		result, err := r.ReconcileWithType(context.Background(), req, tt.refresherType)
 
-			_, err := r.ReconcileWithConfig(context.TODO(), refresherConfig)
-			if tt.expectedError && err == nil {
-				t.Errorf("Expected error, got nil")
-			}
-			if !tt.expectedError && err != nil {
-				t.Errorf("Expected no error, got %v", err)
-			}
-		})
+		if !reflect.DeepEqual(result, tt.expectedResult) {
+			t.Fatalf("Expected result %v, got %v", tt.expectedResult, result)
+		}
+		if tt.expectedError && err == nil {
+			t.Fatalf("Expected error, got nil")
+		}
 	}
 }
 
@@ -124,37 +402,148 @@ func TestKeyManagementProviderReconciler_Reconcile(t *testing.T) {
 		t.Errorf("Expected result %v, got %v", expectedResult, result)
 	}
 }
+func TestKMProviderUpdateErrorStatusNamespaced(t *testing.T) {
+	var parametersString = "{\"certs\":{\"name\":\"certName\"}}"
+	var kmProviderStatus = []byte(parametersString)
 
-type MockRefresher struct {
-	Results           ctrl.Result
-	CreateConfigError bool
-	RefreshError      bool
-	ShouldError       bool
-}
+	status := configv1beta1.NamespacedKeyManagementProviderStatus{
+		IsSuccess: true,
+		Properties: runtime.RawExtension{
+			Raw: kmProviderStatus,
+		},
+	}
+	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
+		Status: status,
+	}
+	expectedErr := re.ErrorCodeUnknown.WithDetail("it's a long error from unit test")
+	lastFetchedTime := metav1.Now()
+	updateKMProviderErrorStatusNamespaced(&keyManagementProvider, &expectedErr, &lastFetchedTime)
 
-func (mr *MockRefresher) Refresh(_ context.Context) error {
-	if mr.RefreshError {
-		return errors.New("refresh error")
+	if keyManagementProvider.Status.IsSuccess != false {
+		t.Fatalf("Unexpected error, expected isSuccess to be false , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != expectedErr.Error() {
+		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr, keyManagementProvider.Status.Error)
+	}
+	if keyManagementProvider.Status.BriefError != expectedErr.GetConciseError(150) {
+		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr.GetConciseError(150), keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was not overridden
+	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
+		t.Fatalf("Unexpected properties,  expected %+v, got %+v", parametersString, string(keyManagementProvider.Status.Properties.Raw))
 	}
-	return nil
 }
 
-func (mr *MockRefresher) GetResult() interface{} {
-	return ctrl.Result{}
+func TestKMProviderUpdateSuccessStatusNamespaced(t *testing.T) {
+	kmProviderStatus := keymanagementprovider.KeyManagementProviderStatus{}
+	properties := map[string]string{}
+	properties["Name"] = "wabbit"
+	properties["Version"] = "ABC"
+
+	kmProviderStatus["Certificates"] = properties
+
+	lastFetchedTime := metav1.Now()
+
+	status := configv1beta1.NamespacedKeyManagementProviderStatus{
+		IsSuccess: false,
+		Error:     "error from last operation",
+	}
+	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
+		Status: status,
+	}
+
+	updateKMProviderSuccessStatusNamespaced(&keyManagementProvider, &lastFetchedTime, kmProviderStatus)
+
+	if keyManagementProvider.Status.IsSuccess != true {
+		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != "" {
+		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was updated
+	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
+		t.Fatalf("Properties should not be empty")
+	}
 }
 
-func (mr *MockRefresher) Create(config map[string]interface{}) (refresh.Refresher, error) {
-	createConfigError := config["shouldError"].(bool)
-	refreshError := config["refreshError"].(bool)
-	if createConfigError {
-		return nil, errors.New("create error")
+func TestKMProviderUpdateSuccessStatusNamespaced_emptyProperties(t *testing.T) {
+	lastFetchedTime := metav1.Now()
+	status := configv1beta1.NamespacedKeyManagementProviderStatus{
+		IsSuccess: false,
+		Error:     "error from last operation",
+	}
+	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
+		Status: status,
+	}
+
+	updateKMProviderSuccessStatusNamespaced(&keyManagementProvider, &lastFetchedTime, nil)
+
+	if keyManagementProvider.Status.IsSuccess != true {
+		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
+	}
+
+	if keyManagementProvider.Status.Error != "" {
+		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
+	}
+
+	//make sure properties of last cached cert was updated
+	if len(keyManagementProvider.Status.Properties.Raw) != 0 {
+		t.Fatalf("Properties should be empty")
 	}
-	return &MockRefresher{
-		CreateConfigError: createConfigError,
-		RefreshError:      refreshError,
-	}, nil
 }
 
-func init() {
-	refresh.Register("mockRefresher", &MockRefresher{})
+func TestWriteKMProviderStatusNamespaced(t *testing.T) {
+	logger := logrus.WithContext(context.Background())
+	lastFetchedTime := metav1.Now()
+	testCases := []struct {
+		name              string
+		isSuccess         bool
+		kmProvider        *configv1beta1.NamespacedKeyManagementProvider
+		errString         string
+		expectedErrString string
+		reconciler        client.StatusClient
+	}{
+		{
+			name:       "success status",
+			isSuccess:  true,
+			errString:  "",
+			kmProvider: &configv1beta1.NamespacedKeyManagementProvider{},
+			reconciler: &test.MockStatusClient{},
+		},
+		{
+			name:              "error status",
+			isSuccess:         false,
+			kmProvider:        &configv1beta1.NamespacedKeyManagementProvider{},
+			errString:         "a long error string that exceeds the max length of 30 characters",
+			expectedErrString: "UNKNOWN: a long error string that exceeds the max length of 30 characters",
+			reconciler:        &test.MockStatusClient{},
+		},
+		{
+			name:       "status update failed",
+			isSuccess:  true,
+			kmProvider: &configv1beta1.NamespacedKeyManagementProvider{},
+			reconciler: &test.MockStatusClient{
+				UpdateFailed: true,
+			},
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			err := re.ErrorCodeUnknown.WithDetail(tc.errString)
+			writeKMProviderStatusNamespaced(context.Background(), tc.reconciler, tc.kmProvider, logger, tc.isSuccess, &err, lastFetchedTime, nil)
+
+			if tc.kmProvider.Status.IsSuccess != tc.isSuccess {
+				t.Fatalf("Expected isSuccess to be %+v , actual %+v", tc.isSuccess, tc.kmProvider.Status.IsSuccess)
+			}
+
+			if tc.kmProvider.Status.Error != tc.expectedErrString {
+				t.Fatalf("Expected Error to be %+v , actual %+v", tc.expectedErrString, tc.kmProvider.Status.Error)
+			}
+		})
+	}
 }
diff --git a/pkg/controllers/utils/verifier_test.go b/pkg/controllers/utils/verifier_test.go
index 8ccf9a6..349653a 100644
--- a/pkg/controllers/utils/verifier_test.go
+++ b/pkg/controllers/utils/verifier_test.go
@@ -119,3 +119,46 @@ func TestSpecToVerifierConfig(t *testing.T) {
 func resetVerifierMap() {
 	controllers.NamespacedVerifiers = verifiers.NewActiveVerifiers()
 }
+
+func TestGetType(t *testing.T) {
+	tests := []struct {
+		name     string
+		input    interface{}
+		expected string
+	}{
+		{
+			name:     "cluster verifier spec with name",
+			input:    configv1beta1.VerifierSpec{Name: "clusterV"},
+			expected: "clusterV",
+		},
+		{
+			name:     "cluster verifier spec with type",
+			input:    configv1beta1.VerifierSpec{Type: "clusterV"},
+			expected: "clusterV",
+		},
+		{
+			name:     "namespaced verifier spec with name",
+			input:    configv1beta1.NamespacedVerifierSpec{Name: "namespacedV"},
+			expected: "namespacedV",
+		},
+		{
+			name:     "namespaced verifier spec with type",
+			input:    configv1beta1.NamespacedVerifierSpec{Type: "namespacedV"},
+			expected: "namespacedV",
+		},
+		{
+			name:     "verifier spec with no name or type",
+			input:    "",
+			expected: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			output := GetVerifierType(tt.input)
+			if tt.expected != output {
+				t.Fatalf("GetType() expected %v, actual %v", tt.expected, output)
+			}
+		})
+	}
+}
diff --git a/pkg/keymanagementprovider/refresh/factory_test.go b/pkg/keymanagementprovider/refresh/factory_test.go
index a4a267c..e8762a4 100644
--- a/pkg/keymanagementprovider/refresh/factory_test.go
+++ b/pkg/keymanagementprovider/refresh/factory_test.go
@@ -22,7 +22,7 @@ import (
 
 type MockRefresher struct{}
 
-func (f *MockRefresher) Create(_ map[string]interface{}) (Refresher, error) {
+func (f *MockRefresher) Create(_ RefresherConfig) (Refresher, error) {
 	return &MockRefresher{}, nil
 }
 
@@ -34,10 +34,14 @@ func (f *MockRefresher) GetResult() interface{} {
 	return nil
 }
 
+func (f *MockRefresher) GetStatus() interface{} {
+	return nil
+}
+
 func TestRefreshFactory_Create(t *testing.T) {
 	Register("mockRefresher", &MockRefresher{})
-	refresherConfig := map[string]interface{}{
-		"type": "mockRefresher",
+	refresherConfig := RefresherConfig{
+		RefresherType: "mockRefresher",
 	}
 	factory := refresherFactories["mockRefresher"]
 	refresher, err := factory.Create(refresherConfig)
@@ -104,8 +108,8 @@ func TestCreateRefresherFromConfig(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			refresherConfig := map[string]interface{}{
-				"type": tt.refresherType,
+			refresherConfig := RefresherConfig{
+				RefresherType: tt.refresherType,
 			}
 			_, err := CreateRefresherFromConfig(refresherConfig)
 			if tt.expectedError && err == nil {
diff --git a/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced_test.go b/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced_test.go
deleted file mode 100644
index 944f548..0000000
--- a/pkg/keymanagementprovider/refresh/kubeRefreshNamespaced_test.go
+++ /dev/null
@@ -1,378 +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"
-	"reflect"
-	"testing"
-	"time"
-
-	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
-	re "github.com/ratify-project/ratify/errors"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider/mocks"
-	test "github.com/ratify-project/ratify/pkg/utils"
-	"github.com/sirupsen/logrus"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/client"
-	"sigs.k8s.io/controller-runtime/pkg/client/fake"
-)
-
-func TestKubeRefresherNamespaced_Refresh(t *testing.T) {
-	tests := []struct {
-		name           string
-		provider       *configv1beta1.NamespacedKeyManagementProvider
-		request        ctrl.Request
-		mockClient     bool
-		expectedResult ctrl.Result
-		expectedError  bool
-	}{
-		{
-			name: "Non-refreshable",
-			provider: &configv1beta1.NamespacedKeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.NamespacedKeyManagementProviderSpec{
-					Type: "inline",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  false,
-		},
-		{
-			name: "Disabled",
-			provider: &configv1beta1.NamespacedKeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.NamespacedKeyManagementProviderSpec{
-					Type:            "test-kmp",
-					RefreshInterval: "",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  false,
-		},
-		{
-			name: "Refreshable",
-			provider: &configv1beta1.NamespacedKeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.NamespacedKeyManagementProviderSpec{
-					Type:            "test-kmp",
-					RefreshInterval: "1m",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{RequeueAfter: time.Minute},
-			expectedError:  false,
-		},
-		{
-			name: "Invalid Interval",
-			provider: &configv1beta1.NamespacedKeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.NamespacedKeyManagementProviderSpec{
-					Type:            "",
-					RefreshInterval: "1mm",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  true,
-		},
-		{
-			name: "IsNotFound",
-			provider: &configv1beta1.NamespacedKeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.NamespacedKeyManagementProviderSpec{
-					Type:            "",
-					RefreshInterval: "",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  false,
-		},
-		{
-			name:          "UnableToFetchKMP",
-			mockClient:    true,
-			expectedError: true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			var client client.Client
-
-			if tt.mockClient {
-				client = mocks.TestClient{}
-			} else {
-				scheme, _ := test.CreateScheme()
-				client = fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.provider).Build()
-			}
-
-			kr := &KubeRefresherNamespaced{
-				Client:  client,
-				Request: tt.request,
-			}
-			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")
-			}
-		})
-	}
-}
-
-func TestKubeRefresherNamespaced_Create(t *testing.T) {
-	tests := []struct {
-		name          string
-		config        map[string]interface{}
-		expectedError bool
-	}{
-		{
-			name: "Success",
-			config: map[string]interface{}{
-				"client":  &mocks.TestClient{},
-				"request": ctrl.Request{},
-			},
-			expectedError: false,
-		},
-		{
-			name: "ClientMissing",
-			config: map[string]interface{}{
-				"request": ctrl.Request{},
-			},
-			expectedError: true,
-		},
-		{
-			name: "RequestMissing",
-			config: map[string]interface{}{
-				"client": &mocks.TestClient{},
-			},
-			expectedError: true,
-		},
-	}
-
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			kr := &KubeRefresherNamespaced{}
-			_, err := kr.Create(tt.config)
-			if tt.expectedError && err == nil {
-				t.Fatalf("Expected error but got nil")
-			}
-		})
-	}
-}
-
-func TestKMProviderUpdateErrorStatusNamespaced(t *testing.T) {
-	var parametersString = "{\"certs\":{\"name\":\"certName\"}}"
-	var kmProviderStatus = []byte(parametersString)
-
-	status := configv1beta1.NamespacedKeyManagementProviderStatus{
-		IsSuccess: true,
-		Properties: runtime.RawExtension{
-			Raw: kmProviderStatus,
-		},
-	}
-	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
-		Status: status,
-	}
-	expectedErr := re.ErrorCodeUnknown.WithDetail("it's a long error from unit test")
-	lastFetchedTime := metav1.Now()
-	updateKMProviderErrorStatusNamespaced(&keyManagementProvider, &expectedErr, &lastFetchedTime)
-
-	if keyManagementProvider.Status.IsSuccess != false {
-		t.Fatalf("Unexpected error, expected isSuccess to be false , actual %+v", keyManagementProvider.Status.IsSuccess)
-	}
-
-	if keyManagementProvider.Status.Error != expectedErr.Error() {
-		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr, keyManagementProvider.Status.Error)
-	}
-	if keyManagementProvider.Status.BriefError != expectedErr.GetConciseError(150) {
-		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr.GetConciseError(150), keyManagementProvider.Status.Error)
-	}
-
-	//make sure properties of last cached cert was not overridden
-	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
-		t.Fatalf("Unexpected properties,  expected %+v, got %+v", parametersString, string(keyManagementProvider.Status.Properties.Raw))
-	}
-}
-
-func TestKMProviderUpdateSuccessStatusNamespaced(t *testing.T) {
-	kmProviderStatus := keymanagementprovider.KeyManagementProviderStatus{}
-	properties := map[string]string{}
-	properties["Name"] = "wabbit"
-	properties["Version"] = "ABC"
-
-	kmProviderStatus["Certificates"] = properties
-
-	lastFetchedTime := metav1.Now()
-
-	status := configv1beta1.NamespacedKeyManagementProviderStatus{
-		IsSuccess: false,
-		Error:     "error from last operation",
-	}
-	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
-		Status: status,
-	}
-
-	updateKMProviderSuccessStatusNamespaced(&keyManagementProvider, &lastFetchedTime, kmProviderStatus)
-
-	if keyManagementProvider.Status.IsSuccess != true {
-		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
-	}
-
-	if keyManagementProvider.Status.Error != "" {
-		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
-	}
-
-	//make sure properties of last cached cert was updated
-	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
-		t.Fatalf("Properties should not be empty")
-	}
-}
-
-func TestKMProviderUpdateSuccessStatusNamespaced_emptyProperties(t *testing.T) {
-	lastFetchedTime := metav1.Now()
-	status := configv1beta1.NamespacedKeyManagementProviderStatus{
-		IsSuccess: false,
-		Error:     "error from last operation",
-	}
-	keyManagementProvider := configv1beta1.NamespacedKeyManagementProvider{
-		Status: status,
-	}
-
-	updateKMProviderSuccessStatusNamespaced(&keyManagementProvider, &lastFetchedTime, nil)
-
-	if keyManagementProvider.Status.IsSuccess != true {
-		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
-	}
-
-	if keyManagementProvider.Status.Error != "" {
-		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
-	}
-
-	//make sure properties of last cached cert was updated
-	if len(keyManagementProvider.Status.Properties.Raw) != 0 {
-		t.Fatalf("Properties should be empty")
-	}
-}
-
-func TestWriteKMProviderStatusNamespaced(t *testing.T) {
-	logger := logrus.WithContext(context.Background())
-	lastFetchedTime := metav1.Now()
-	testCases := []struct {
-		name              string
-		isSuccess         bool
-		kmProvider        *configv1beta1.NamespacedKeyManagementProvider
-		errString         string
-		expectedErrString string
-		reconciler        client.StatusClient
-	}{
-		{
-			name:       "success status",
-			isSuccess:  true,
-			errString:  "",
-			kmProvider: &configv1beta1.NamespacedKeyManagementProvider{},
-			reconciler: &test.MockStatusClient{},
-		},
-		{
-			name:              "error status",
-			isSuccess:         false,
-			kmProvider:        &configv1beta1.NamespacedKeyManagementProvider{},
-			errString:         "a long error string that exceeds the max length of 30 characters",
-			expectedErrString: "UNKNOWN: a long error string that exceeds the max length of 30 characters",
-			reconciler:        &test.MockStatusClient{},
-		},
-		{
-			name:       "status update failed",
-			isSuccess:  true,
-			kmProvider: &configv1beta1.NamespacedKeyManagementProvider{},
-			reconciler: &test.MockStatusClient{
-				UpdateFailed: true,
-			},
-		},
-	}
-
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			err := re.ErrorCodeUnknown.WithDetail(tc.errString)
-			writeKMProviderStatusNamespaced(context.Background(), tc.reconciler, tc.kmProvider, logger, tc.isSuccess, &err, lastFetchedTime, nil)
-
-			if tc.kmProvider.Status.IsSuccess != tc.isSuccess {
-				t.Fatalf("Expected isSuccess to be %+v , actual %+v", tc.isSuccess, tc.kmProvider.Status.IsSuccess)
-			}
-
-			if tc.kmProvider.Status.Error != tc.expectedErrString {
-				t.Fatalf("Expected Error to be %+v , actual %+v", tc.expectedErrString, tc.kmProvider.Status.Error)
-			}
-		})
-	}
-}
diff --git a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go b/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
index 29319ab..9875098 100644
--- a/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
+++ b/pkg/keymanagementprovider/refresh/kubeRefresh_test.go
@@ -18,168 +18,120 @@ package refresh
 
 import (
 	"context"
+	"crypto"
+	"crypto/x509"
+	"errors"
 	"reflect"
 	"testing"
 	"time"
 
-	configv1beta1 "github.com/ratify-project/ratify/api/v1beta1"
-	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"
-	"github.com/ratify-project/ratify/pkg/keymanagementprovider/mocks"
-	test "github.com/ratify-project/ratify/pkg/utils"
-	"github.com/sirupsen/logrus"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
+	mock "github.com/ratify-project/ratify/pkg/keymanagementprovider/mocks"
 	ctrl "sigs.k8s.io/controller-runtime"
-	"sigs.k8s.io/controller-runtime/pkg/client"
-	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 )
 
 func TestKubeRefresher_Refresh(t *testing.T) {
 	tests := []struct {
-		name           string
-		provider       *configv1beta1.KeyManagementProvider
-		request        ctrl.Request
-		mockClient     bool
-		expectedResult ctrl.Result
-		expectedError  bool
+		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
+		expectedResult          ctrl.Result
+		expectedError           bool
 	}{
 		{
-			name: "Non-refreshable",
-			provider: &configv1beta1.KeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.KeyManagementProviderSpec{
-					Type: "inline",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"type": "inline", "contentType": "certificate", "value": "-----BEGIN CERTIFICATE-----\nMIID2jCCAsKgAwIBAgIQXy2VqtlhSkiZKAGhsnkjbDANBgkqhkiG9w0BAQsFADBvMRswGQYDVQQD\nExJyYXRpZnkuZXhhbXBsZS5jb20xDzANBgNVBAsTBk15IE9yZzETMBEGA1UEChMKTXkgQ29tcGFu\neTEQMA4GA1UEBxMHUmVkbW9uZDELMAkGA1UECBMCV0ExCzAJBgNVBAYTAlVTMB4XDTIzMDIwMTIy\nNDUwMFoXDTI0MDIwMTIyNTUwMFowbzEbMBkGA1UEAxMScmF0aWZ5LmV4YW1wbGUuY29tMQ8wDQYD\nVQQLEwZNeSBPcmcxEzARBgNVBAoTCk15IENvbXBhbnkxEDAOBgNVBAcTB1JlZG1vbmQxCzAJBgNV\nBAgTAldBMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL10bM81\npPAyuraORABsOGS8M76Bi7Guwa3JlM1g2D8CuzSfSTaaT6apy9GsccxUvXd5cmiP1ffna5z+EFmc\nizFQh2aq9kWKWXDvKFXzpQuhyqD1HeVlRlF+V0AfZPvGt3VwUUjNycoUU44ctCWmcUQP/KShZev3\n6SOsJ9q7KLjxxQLsUc4mg55eZUThu8mGB8jugtjsnLUYvIWfHhyjVpGrGVrdkDMoMn+u33scOmrt\nsBljvq9WVo4T/VrTDuiOYlAJFMUae2Ptvo0go8XTN3OjLblKeiK4C+jMn9Dk33oGIT9pmX0vrDJV\nX56w/2SejC1AxCPchHaMuhlwMpftBGkCAwEAAaNyMHAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQC\nMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU0eaKkZj+MS9jCp9Dg1zdv3v/aKww\nHQYDVR0OBBYEFNHmipGY/jEvYwqfQ4Nc3b97/2isMA0GCSqGSIb3DQEBCwUAA4IBAQBNDcmSBizF\nmpJlD8EgNcUCy5tz7W3+AAhEbA3vsHP4D/UyV3UgcESx+L+Nye5uDYtTVm3lQejs3erN2BjW+ds+\nXFnpU/pVimd0aYv6mJfOieRILBF4XFomjhrJOLI55oVwLN/AgX6kuC3CJY2NMyJKlTao9oZgpHhs\nLlxB/r0n9JnUoN0Gq93oc1+OLFjPI7gNuPXYOP1N46oKgEmAEmNkP1etFrEjFRgsdIFHksrmlOlD\nIed9RcQ087VLjmuymLgqMTFX34Q3j7XgN2ENwBSnkHotE9CcuGRW+NuiOeJalL8DBmFXXWwHTKLQ\nPp5g6m1yZXylLJaFLKz7tdMmO355\n-----END CERTIFICATE-----\n"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  false,
+			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 },
+			expectedResult:        ctrl.Result{},
+			expectedError:         false,
 		},
 		{
-			name: "Disabled",
-			provider: &configv1beta1.KeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.KeyManagementProviderSpec{
-					Type:            "test-kmp",
-					RefreshInterval: "",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			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: "",
+			IsRefreshableFunc:       func() bool { return true },
+			expectedResult:          ctrl.Result{},
+			expectedError:           false,
 		},
 		{
-			name: "Refreshable",
-			provider: &configv1beta1.KeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.KeyManagementProviderSpec{
-					Type:            "test-kmp",
-					RefreshInterval: "1m",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{RequeueAfter: time.Minute},
-			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",
+			IsRefreshableFunc:       func() bool { return true },
+			expectedResult:          ctrl.Result{RequeueAfter: time.Minute},
+			expectedError:           false,
 		},
 		{
-			name: "Invalid Interval",
-			provider: &configv1beta1.KeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.KeyManagementProviderSpec{
-					Type:            "",
-					RefreshInterval: "1mm",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
-			},
-			request: ctrl.Request{
-				NamespacedName: client.ObjectKey{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-			},
-			expectedResult: ctrl.Result{},
-			expectedError:  true,
+			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",
+			IsRefreshableFunc:       func() bool { return true },
+			expectedResult:          ctrl.Result{},
+			expectedError:           true,
 		},
 		{
-			name: "IsNotFound",
-			provider: &configv1beta1.KeyManagementProvider{
-				ObjectMeta: metav1.ObjectMeta{
-					Namespace: "",
-					Name:      "kmpName",
-				},
-				Spec: configv1beta1.KeyManagementProviderSpec{
-					Type:            "",
-					RefreshInterval: "",
-					Parameters: runtime.RawExtension{
-						Raw: []byte(`{"vaultURI": "https://yourkeyvault.vault.azure.net/", "certificates": [{"name": "cert1", "version": "1"}], "tenantID": "yourtenantID", "clientID": "yourclientID"}`),
-					},
-				},
+			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")
 			},
-			expectedResult: ctrl.Result{},
-			expectedError:  false,
+			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 },
+			expectedError:         true,
 		},
 		{
-			name:          "UnableToFetchKMP",
-			mockClient:    true,
-			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 },
+			expectedError:         true,
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			var client client.Client
-
-			if tt.mockClient {
-				client = mocks.TestClient{}
+			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 {
-				scheme, _ := test.CreateScheme()
-				client = fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.provider).Build()
+				factory = mock.TestKeyManagementProviderFactory{
+					IsRefreshableFunc: tt.IsRefreshableFunc,
+				}
 			}
 
+			provider, _ := factory.Create("", config.KeyManagementProviderConfig{}, "")
+
 			kr := &KubeRefresher{
-				Client:  client,
-				Request: tt.request,
+				Provider:                provider,
+				ProviderType:            tt.providerType,
+				ProviderRefreshInterval: tt.providerRefreshInterval,
+				Resource:                "kmpname",
 			}
+
 			err := kr.Refresh(context.Background())
 			result := kr.GetResult()
 			if !reflect.DeepEqual(result, tt.expectedResult) {
@@ -192,190 +144,93 @@ func TestKubeRefresher_Refresh(t *testing.T) {
 	}
 }
 
-func TestKubeRefresher_Create(t *testing.T) {
-	tests := []struct {
-		name          string
-		config        map[string]interface{}
-		expectedError bool
-	}{
-		{
-			name: "Success",
-			config: map[string]interface{}{
-				"client":  &mocks.TestClient{},
-				"request": ctrl.Request{},
-			},
-			expectedError: false,
-		},
-		{
-			name: "ClientMissing",
-			config: map[string]interface{}{
-				"request": ctrl.Request{},
-			},
-			expectedError: true,
-		},
-		{
-			name: "RequestMissing",
-			config: map[string]interface{}{
-				"client": &mocks.TestClient{},
-			},
-			expectedError: true,
-		},
+func TestKubeRefresher_GetResult(t *testing.T) {
+	kr := &KubeRefresher{
+		Result: ctrl.Result{RequeueAfter: time.Minute},
 	}
 
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			kr := &KubeRefresher{}
-			_, err := kr.Create(tt.config)
-			if tt.expectedError && err == nil {
-				t.Fatalf("Expected error but got nil")
-			}
-		})
-	}
-}
+	result := kr.GetResult()
+	expectedResult := ctrl.Result{RequeueAfter: time.Minute}
 
-func TestKMProviderUpdateErrorStatus(t *testing.T) {
-	var parametersString = "{\"certs\":{\"name\":\"certName\"}}"
-	var kmProviderStatus = []byte(parametersString)
-
-	status := configv1beta1.KeyManagementProviderStatus{
-		IsSuccess: true,
-		Properties: runtime.RawExtension{
-			Raw: kmProviderStatus,
-		},
-	}
-	keyManagementProvider := configv1beta1.KeyManagementProvider{
-		Status: status,
-	}
-	expectedErr := re.ErrorCodeUnknown.WithDetail("it's a long error from unit test")
-	lastFetchedTime := metav1.Now()
-	updateKMProviderErrorStatus(&keyManagementProvider, &expectedErr, &lastFetchedTime)
-
-	if keyManagementProvider.Status.IsSuccess != false {
-		t.Fatalf("Unexpected error, expected isSuccess to be false , actual %+v", keyManagementProvider.Status.IsSuccess)
-	}
-
-	if keyManagementProvider.Status.Error != expectedErr.Error() {
-		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr, keyManagementProvider.Status.Error)
-	}
-	if keyManagementProvider.Status.BriefError != expectedErr.GetConciseError(150) {
-		t.Fatalf("Unexpected error string, expected %+v, got %+v", expectedErr.GetConciseError(150), keyManagementProvider.Status.Error)
-	}
-
-	//make sure properties of last cached cert was not overridden
-	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
-		t.Fatalf("Unexpected properties,  expected %+v, got %+v", parametersString, string(keyManagementProvider.Status.Properties.Raw))
+	if !reflect.DeepEqual(result, expectedResult) {
+		t.Fatalf("Expected result %v, but got %v", expectedResult, result)
 	}
 }
-
-// TestKMProviderUpdateSuccessStatus tests the updateSuccessStatus method
-func TestKMProviderUpdateSuccessStatus(t *testing.T) {
-	kmProviderStatus := keymanagementprovider.KeyManagementProviderStatus{}
-	properties := map[string]string{}
-	properties["Name"] = "wabbit"
-	properties["Version"] = "ABC"
-
-	kmProviderStatus["Certificates"] = properties
-
-	lastFetchedTime := metav1.Now()
-
-	status := configv1beta1.KeyManagementProviderStatus{
-		IsSuccess: false,
-		Error:     "error from last operation",
-	}
-	keyManagementProvider := configv1beta1.KeyManagementProvider{
-		Status: status,
-	}
-
-	updateKMProviderSuccessStatus(&keyManagementProvider, &lastFetchedTime, kmProviderStatus)
-
-	if keyManagementProvider.Status.IsSuccess != true {
-		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
-	}
-
-	if keyManagementProvider.Status.Error != "" {
-		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
-	}
-
-	//make sure properties of last cached cert was updated
-	if len(keyManagementProvider.Status.Properties.Raw) == 0 {
-		t.Fatalf("Properties should not be empty")
-	}
-}
-
-// TestKMProviderUpdateSuccessStatus tests the updateSuccessStatus method with empty properties
-func TestKMProviderUpdateSuccessStatus_emptyProperties(t *testing.T) {
-	lastFetchedTime := metav1.Now()
-	status := configv1beta1.KeyManagementProviderStatus{
-		IsSuccess: false,
-		Error:     "error from last operation",
-	}
-	keyManagementProvider := configv1beta1.KeyManagementProvider{
-		Status: status,
-	}
-
-	updateKMProviderSuccessStatus(&keyManagementProvider, &lastFetchedTime, nil)
-
-	if keyManagementProvider.Status.IsSuccess != true {
-		t.Fatalf("Expected isSuccess to be true , actual %+v", keyManagementProvider.Status.IsSuccess)
+func TestKubeRefresher_GetStatus(t *testing.T) {
+	kr := &KubeRefresher{
+		Status: keymanagementprovider.KeyManagementProviderStatus{
+			"attribute1": "value1",
+			"attribute2": "value2",
+		},
 	}
 
-	if keyManagementProvider.Status.Error != "" {
-		t.Fatalf("Unexpected error string, actual %+v", keyManagementProvider.Status.Error)
+	status := kr.GetStatus()
+	expectedStatus := keymanagementprovider.KeyManagementProviderStatus{
+		"attribute1": "value1",
+		"attribute2": "value2",
 	}
 
-	//make sure properties of last cached cert was updated
-	if len(keyManagementProvider.Status.Properties.Raw) != 0 {
-		t.Fatalf("Properties should be empty")
+	if !reflect.DeepEqual(status, expectedStatus) {
+		t.Fatalf("Expected status %v, but got %v", expectedStatus, status)
 	}
 }
-
-func TestWriteKMProviderStatus(t *testing.T) {
-	logger := logrus.WithContext(context.Background())
-	lastFetchedTime := metav1.Now()
-	testCases := []struct {
-		name              string
-		isSuccess         bool
-		kmProvider        *configv1beta1.KeyManagementProvider
-		errString         string
-		expectedErrString string
-		reconciler        client.StatusClient
+func TestKubeRefresher_Create(t *testing.T) {
+	tests := []struct {
+		name                    string
+		config                  RefresherConfig
+		expectedProviderType    string
+		expectedRefreshInterval string
+		expectedResource        string
 	}{
 		{
-			name:       "success status",
-			isSuccess:  true,
-			errString:  "",
-			kmProvider: &configv1beta1.KeyManagementProvider{},
-			reconciler: &test.MockStatusClient{},
-		},
-		{
-			name:              "error status",
-			isSuccess:         false,
-			kmProvider:        &configv1beta1.KeyManagementProvider{},
-			errString:         "a long error string that exceeds the max length of 150 characters",
-			expectedErrString: "UNKNOWN: a long error string that exceeds the max length of 150 characters",
-			reconciler:        &test.MockStatusClient{},
+			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:       "status update failed",
-			isSuccess:  true,
-			kmProvider: &configv1beta1.KeyManagementProvider{},
-			reconciler: &test.MockStatusClient{
-				UpdateFailed: true,
+			name: "Empty Config",
+			config: RefresherConfig{
+				Provider:                nil,
+				ProviderType:            "",
+				ProviderRefreshInterval: "",
+				Resource:                "",
 			},
+			expectedProviderType:    "",
+			expectedRefreshInterval: "",
+			expectedResource:        "",
 		},
 	}
 
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			err := re.ErrorCodeUnknown.WithDetail(tc.errString)
-			writeKMProviderStatus(context.Background(), tc.reconciler, tc.kmProvider, logger, tc.isSuccess, &err, lastFetchedTime, nil)
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			kr := &KubeRefresher{}
+			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 tc.kmProvider.Status.IsSuccess != tc.isSuccess {
-				t.Fatalf("Expected isSuccess to be: %+v, actual: %+v", tc.isSuccess, tc.kmProvider.Status.IsSuccess)
+			if kubeRefresher.ProviderRefreshInterval != tt.expectedRefreshInterval {
+				t.Fatalf("Expected ProviderRefreshInterval %v, but got %v", tt.expectedRefreshInterval, kubeRefresher.ProviderRefreshInterval)
 			}
 
-			if tc.kmProvider.Status.Error != tc.expectedErrString {
-				t.Fatalf("Expected Error to be: %+v, actual: %+v", tc.expectedErrString, tc.kmProvider.Status.Error)
+			if kubeRefresher.Resource != tt.expectedResource {
+				t.Fatalf("Expected Resource %v, but got %v", tt.expectedResource, kubeRefresher.Resource)
 			}
 		})
 	}
diff --git a/pkg/verifier/cosign/cosign_test.go b/pkg/verifier/cosign/cosign_test.go
index b4e3686..aea1cf5 100644
--- a/pkg/verifier/cosign/cosign_test.go
+++ b/pkg/verifier/cosign/cosign_test.go
@@ -23,6 +23,7 @@ import (
 	"crypto/elliptic"
 	"crypto/rand"
 	"crypto/rsa"
+	"encoding/base64"
 	"fmt"
 	"io"
 	"slices"
@@ -114,6 +115,26 @@ func TestCreate(t *testing.T) {
 			},
 			wantErr: false,
 		},
+		{
+			name: "duplicate trust policies in config",
+			config: config.VerifierConfig{
+				"name":          "test",
+				"artifactTypes": "testtype",
+				"trustPolicies": []TrustPolicyConfig{
+					{
+						Name:    "test",
+						Keyless: KeylessConfig{CertificateIdentity: testIdentity, CertificateOIDCIssuer: testIssuer},
+						Scopes:  []string{"*"},
+					},
+					{
+						Name:    "test",
+						Keyless: KeylessConfig{CertificateIdentity: testIdentity, CertificateOIDCIssuer: testIssuer},
+						Scopes:  []string{"*"},
+					},
+				},
+			},
+			wantErr: true,
+		},
 		{
 			name: "invalid config with legacy and trust policies",
 			config: config.VerifierConfig{
@@ -407,8 +428,8 @@ func TestErrorToVerifyResult(t *testing.T) {
 	if verifierResult.Type != "cosign" {
 		t.Errorf("errorToVerifyResult() = %v, want %v", verifierResult.Type, "cosign")
 	}
-	if verifierResult.Message != "Verification failed" {
-		t.Errorf("errorToVerifyResult() = %v, want %v", verifierResult.Message, "Verification failed")
+	if verifierResult.Message != "Failed to validate the Cosign signature" {
+		t.Errorf("errorToVerifyResult() = %v, want %v", verifierResult.Message, "Failed to validate the Cosign signature")
 	}
 	if verifierResult.ErrorReason != "test error" {
 		t.Errorf("errorToVerifyResult() = %v, want %v", verifierResult.ErrorReason, "test error")
@@ -573,7 +594,7 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 			keys:                        map[PKKey]keymanagementprovider.PublicKey{},
 			getKeysError:                true,
 			store:                       &mocks.MemoryTestStore{},
-			expectedResultMessagePrefix: "Verification failed",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
 			expectedErrorReason:         "error",
 		},
 		{
@@ -581,8 +602,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 			keys:                        map[PKKey]keymanagementprovider.PublicKey{},
 			getKeysError:                false,
 			store:                       &mocks.MemoryTestStore{},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to get reference manifest: manifest not found",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "manifest not found",
 		},
 		{
 			name:         "incorrect reference manifest media type error",
@@ -595,8 +616,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					},
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "reference manifest is not an image",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "The artifact metadata is not an OCI image",
 		},
 		{
 			name:         "failed subject descriptor fetch",
@@ -609,8 +630,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					},
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to create subject hash: subject not found for sha256:5678",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "subject not found for sha256:5678",
 		},
 		{
 			name:         "failed to fetch blob",
@@ -636,8 +657,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					},
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to get blob content: blob not found",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "blob not found",
 		},
 		{
 			name: "invalid key type for AKV",
@@ -668,8 +689,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					blobDigest: validSignatureBlob,
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to verify with keys: failed to process AKV signature: unsupported public key type: *ecdh.PublicKey",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "unsupported public key type [*ecdh.PublicKey]",
 		},
 		{
 			name: "invalid RSA key size for AKV",
@@ -700,8 +721,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					blobDigest: validSignatureBlob,
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to verify with keys: failed to process AKV signature: RSA key check: unsupported key size: 128",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "RSA key check: unsupported key size: 128",
 		},
 		{
 			name: "invalid ECDSA curve type for AKV",
@@ -732,8 +753,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					blobDigest: validSignatureBlob,
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to verify with keys: failed to process AKV signature: ECDSA key check: unsupported key curve: P-224",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature",
+			expectedErrorReason:         "ECDSA key check: unsupported key curve [P-224]",
 		},
 		{
 			name: "valid hash: 256 keysize: 2048 RSA key AKV",
@@ -965,8 +986,8 @@ mmBwUAwwW0Uc+Nt3bDOCiB1nUsICv1ry
 					"sha256:d1226e36bc8502978324cb2cb2116c6aa48edb2ea8f15b1c6f6f256ed43388f6": []byte(`{"critical":{"identity":{"docker-reference":"wabbitnetworks.azurecr.io/test/cosign-image"},"image":{"docker-manifest-digest":"sha256:623621b56649b5e0c2c7cf3ffd987932f8f9a5a01036e00d6f3ae9480087621c"},"type":"cosign container image signature"},"optional":null}`),
 				},
 			},
-			expectedResultMessagePrefix: "Verification failed",
-			expectedErrorReason:         "failed to parse static signature opts: failed to unmarshal bundle from blob payload: illegal base64 data at input byte 91",
+			expectedResultMessagePrefix: "Failed to validate the Cosign signature:",
+			expectedErrorReason:         "failed to unmarshal bundle from blob payload: illegal base64 data at input byte 91",
 		},
 	}
 
@@ -1051,3 +1072,81 @@ func TestVerificationMessage(t *testing.T) {
 		})
 	}
 }
+
+func TestProcessAKVSignature_RSAKey(t *testing.T) {
+	tests := []struct {
+		name             string
+		keySize          int
+		encodedSig       string
+		expectedErr      bool
+		expectedHashType crypto.Hash
+		expectedSigOut   bool
+	}{
+		{
+			name:             "RSA 2048 bits",
+			keySize:          256,
+			expectedErr:      false,
+			expectedHashType: crypto.SHA256,
+			expectedSigOut:   true,
+		},
+		{
+			name:             "RSA 3072 bits",
+			keySize:          384,
+			expectedErr:      false,
+			expectedHashType: crypto.SHA384,
+			expectedSigOut:   true,
+		},
+		{
+			name:             "RSA 4096 bits",
+			keySize:          512,
+			expectedErr:      false,
+			expectedHashType: crypto.SHA512,
+			expectedSigOut:   true,
+		},
+		{
+			name:        "Unsupported key size",
+			keySize:     128,
+			expectedErr: true,
+		},
+		{
+			name:        "Invalid base64 encoded signature",
+			keySize:     256,
+			encodedSig:  "ThisIsNot@ValidBase64%String!",
+			expectedErr: true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			// Create a mock RSA public key
+			privateKey, err := rsa.GenerateKey(rand.Reader, tt.keySize*8)
+			if err != nil {
+				t.Fatalf("Failed to generate RSA key: %v", err)
+			}
+			rsaPublicKey := &privateKey.PublicKey
+
+			// Mock the signature as base64 encoded string
+			sig := "dummy_signature"
+			encodedSig := base64.StdEncoding.EncodeToString([]byte(sig))
+			if tt.encodedSig != "" {
+				encodedSig = tt.encodedSig
+			}
+
+			// Process the signature
+			hashType, sigOut, err := processAKVSignature(encodedSig, nil, rsaPublicKey, []byte("test payload"), []static.Option{})
+
+			if tt.expectedErr {
+				if err == nil {
+					t.Fatalf("Expected error but got nil")
+				}
+			} else {
+				if hashType != tt.expectedHashType {
+					t.Fatalf("Expected hash type %v but got %v", tt.expectedHashType, hashType)
+				}
+				if tt.expectedSigOut != (sigOut != nil) {
+					t.Fatalf("Expected signature output to be %v but got %v", tt.expectedSigOut, sigOut)
+				}
+			}
+		})
+	}
+}
diff --git a/pkg/verifier/cosign/trustpolicy_test.go b/pkg/verifier/cosign/trustpolicy_test.go
index ea720c5..65dcb84 100644
--- a/pkg/verifier/cosign/trustpolicy_test.go
+++ b/pkg/verifier/cosign/trustpolicy_test.go
@@ -21,6 +21,7 @@ import (
 	"crypto/ecdsa"
 	"crypto/x509"
 	"fmt"
+	"os"
 	"testing"
 
 	ctxUtils "github.com/ratify-project/ratify/internal/context"
@@ -204,6 +205,20 @@ func TestGetKeys(t *testing.T) {
 			},
 			wantErr: true,
 		},
+		{
+			name: "access nonexistent key from KMP",
+			cfg: TrustPolicyConfig{
+				Name:   "test",
+				Scopes: []string{"*"},
+				Keys: []KeyConfig{
+					{
+						Provider: "ns/kmp",
+						Name:     "nonexistent",
+					},
+				},
+			},
+			wantErr: true,
+		},
 		{
 			name: "valid KMP",
 			cfg: TrustPolicyConfig{
@@ -423,7 +438,7 @@ func TestValidate(t *testing.T) {
 
 	for _, tt := range tc {
 		t.Run(tt.name, func(t *testing.T) {
-			actual := validate(tt.policyConfig, "test-verifier")
+			actual := validate(tt.policyConfig)
 			if (actual != nil) != tt.wantErr {
 				t.Fatalf("expected %v, got %v", tt.wantErr, actual)
 			}
@@ -447,3 +462,76 @@ func TestLoadKeyFromPath(t *testing.T) {
 		t.Fatalf("expected ecdsa.PublicKey, got %v", keyType)
 	}
 }
+
+func TestGetCosignOpts(t *testing.T) {
+	testCases := []struct {
+		name           string
+		tlogVerify     bool
+		rekorURL       string
+		rekorPubKeyEnv string
+		isKeyless      bool
+		CTLogVerify    bool
+		CTLogPubKeyEnv string
+		expectedErr    bool
+	}{
+		{
+			name:        "invalid rekor url",
+			tlogVerify:  true,
+			rekorURL:    string([]byte{0x7f}),
+			expectedErr: true,
+		},
+		{
+			name:           "failed to get rekor public key",
+			tlogVerify:     true,
+			rekorURL:       "https://rekor.sigstore.dev",
+			rekorPubKeyEnv: "invalid",
+			expectedErr:    true,
+		},
+		{
+			name:           "failed to get CT log public key",
+			tlogVerify:     false,
+			isKeyless:      true,
+			CTLogVerify:    true,
+			CTLogPubKeyEnv: "invalid",
+			expectedErr:    true,
+		},
+	}
+
+	for _, tc := range testCases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			if tc.rekorPubKeyEnv != "" {
+				val := os.Getenv("SIGSTORE_REKOR_PUBLIC_KEY")
+				os.Setenv("SIGSTORE_REKOR_PUBLIC_KEY", tc.rekorPubKeyEnv)
+				t.Cleanup(func() {
+					os.Setenv("SIGSTORE_REKOR_PUBLIC_KEY", val)
+				})
+			}
+
+			if tc.CTLogPubKeyEnv != "" {
+				val := os.Getenv("SIGSTORE_CT_LOG_PUBLIC_KEY_FILE")
+				os.Setenv("SIGSTORE_CT_LOG_PUBLIC_KEY_FILE", tc.CTLogPubKeyEnv)
+				t.Cleanup(func() {
+					os.Setenv("SIGSTORE_CT_LOG_PUBLIC_KEY_FILE", val)
+				})
+			}
+
+			tp := trustPolicy{
+				config: TrustPolicyConfig{
+					TLogVerify: &tc.tlogVerify,
+					RekorURL:   tc.rekorURL,
+					Keyless: KeylessConfig{
+						CTLogVerify: &tc.CTLogVerify,
+					},
+				},
+				isKeyless: tc.isKeyless,
+			}
+			_, err := tp.GetCosignOpts(context.Background())
+			if tc.expectedErr {
+				if err == nil {
+					t.Fatalf("expected error, got nil")
+				}
+			}
+		})
+	}
+}
diff --git a/scripts/azure-ci-test.sh b/scripts/azure-ci-test.sh
index c5c7be9..b5ddce9 100755
--- a/scripts/azure-ci-test.sh
+++ b/scripts/azure-ci-test.sh
@@ -28,7 +28,7 @@ export KEYVAULT_NAME="${KEYVAULT_NAME:-ratify-akv-${SUFFIX}}"
 export USER_ASSIGNED_IDENTITY_NAME="${USER_ASSIGNED_IDENTITY_NAME:-ratify-e2e-identity-${SUFFIX}}"
 export LOCATION="westus2"
 export KUBERNETES_VERSION=${1:-1.29.2}
-GATEKEEPER_VERSION=${2:-3.16.0}
+GATEKEEPER_VERSION=${2:-3.17.0}
 TENANT_ID=$3
 export RATIFY_NAMESPACE=${4:-gatekeeper-system}
 CERT_DIR=${5:-"~/ratify/certs"}
diff --git a/test/bats/tests/config/config_v1beta1_verifier_notation.yaml b/test/bats/tests/config/config_v1beta1_verifier_notation.yaml
index bb1564a..2fdfc94 100644
--- a/test/bats/tests/config/config_v1beta1_verifier_notation.yaml
+++ b/test/bats/tests/config/config_v1beta1_verifier_notation.yaml
@@ -9,7 +9,7 @@ spec:
     verificationCertStores:
       ca:
         ca-certs:
-        - certstore-inline
+          - certstore-inline
     trustPolicyDoc:
       version: "1.0"
       trustPolicies: