Repository: deislabs/ratify
Pull request #349 (2022-10-13 18:35:13)

Ratify store and verifier CRD
# Description
Fixes # (282)

The goal of this PR is to bring feature parity with existing Ratify configuration file.  Customer no longer needs to interact with the configuration file, Customer will be able to interact with Store , Verifier, SecretStoreCSI driver CRDs instead.

Note: Initial configuration for store/verifier/policy/executor property will be loaded from config file. Policy and execution mode setting has not been converted to CRDs as there maybe futures changes to introduce a orchestrator layer. Policy and execution mode settings will come from configuration file, where store and verifier CRDs will override specifications defined in config file.
 
High level changes:

• migrate project to use Kubebuilder SDK to generate CRD boilerplate code
• Add Definition and controllers for verifier and Store CRDs  
• Unit tests for CRD controllers
• New entry point to initialize the CRD manager to spin up the HTTP server
• Add preinstall step to apply CRD definition before installation of ratify ( coming soon)
• Update documentation  ( WIP)

Future PRs:
* Update public package action to build CRD image, currently CRD install is turned off in values file as we don't have a image for CRDs. 
* Future e2e changes that covers CRUD for CRDs
• Implementing defaulting/validating webhooks

Changes at a directory level:
1.Makefile: adds new targets for crd and controller build/install, these targets are mostly generated from kubebuilder SDK
2.api/v1alpha1:
-  Store_types.go and verifier_types.go contains the struct for CRD. This is the crd SCAFFOLDING we own, other files are generated.
- SDK generated the observed state, 'StoreStatus'.  some gatekeeper [crd](https://github.com/open-policy-agent/gatekeeper/blob/master/apis/config/v1alpha1/config_types.go#L75) has left it as is, I have also left that untouched.

3. charts/ratify/crds:
- generated crd definition to be installed as a part of preinstall hook

4. charts/ratify/templates:
- add preinstall hook to install crd ( uses gatekeeper [preinstall step](https://github.com/open-policy-agent/gatekeeper/blob/master/charts/gatekeeper/templates/upgrade-crds-hook.yaml) as a reference)
- add manager role and role binding that is required for the crd controller

5. config/: 
- crd/default/manager/rbac folders are generated by kubebuilder SDK
- config/samples contains sample CRDs

6. pkg/controllers:
controllers for CRD to handle creation/update/delete, the Reconcile method keeps the map of verifiers and store up to date.

7. main.go
The new entry point for dockerFile, part of the file was enerated by kubebuilder SDK that contains logic to handles registration of CRD controllers, I have updated main.go to also spin up a http server so we could continue to listen to ratify verification requests.

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ X] This change requires a documentation update

# How Has This Been Tested?

Installed Ratify and Gatekeeper , ran e2e test locally to validate CRUD is handled correctly by the crd controller.
When there are errors in controller reconcile , the reconcile request gets requeued several times. In case of failures, the failed CRD will not appear in response of "kubectl get crd"

# Checklist:

- [x] Does the affected code have corresponding tests?
- [x] 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.
- [x] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [x] Do all new files have appropriate license header?


susanshi: Hi @etrexel , @binbin-li, Cara please review this change if you have previous experience with CRD/ kubebuilder/ controller gen. Please see high level changes in the PR description, let me know if you have any questions. Really appreciate all the feedback. thanks!
sajayantony: @susanshi to avoid merge issues can you rebase over main? 
sajayantony: Linking the design doc here - https://hackmd.io/esm0xHZqQR2_fs5MIOP20A?both

Patch:
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
index a4ed4e5..2d58787 100644
--- a/.github/workflows/build-pr.yml
+++ b/.github/workflows/build-pr.yml
@@ -57,6 +57,7 @@ jobs:
         run: |
           kubectl logs -n gatekeeper-system -l control-plane=controller-manager --tail=-1 > logs-externaldata-controller.json
           kubectl logs -n gatekeeper-system -l control-plane=audit-controller --tail=-1 > logs-externaldata-audit.json
+          kubectl logs -n ratify-service -l app=ratify --tail=-1 > logs-ratify-preinstall.json
           kubectl logs -n ratify-service -l app.kubernetes.io/name=ratify --tail=-1 > logs-ratify.json
       - name: Upload artifacts
         uses: actions/upload-artifact@v3
diff --git a/Makefile b/Makefile
index 7ac365a..5212f29 100644
--- a/Makefile
+++ b/Makefile
@@ -12,17 +12,22 @@ LDFLAGS += -X $(GO_PKG)/internal/version.GitTreeState=$(GIT_TREE_STATE)
 LDFLAGS += -X $(GO_PKG)/internal/version.GitTag=$(GIT_TAG)
 
 KIND_VERSION ?= 0.14.0
+KUBERNETES_VERSION ?= 1.25.0
+
 HELM_VERSION ?= 3.9.2
 BATS_TESTS_FILE ?= test/bats/test.bats
 BATS_VERSION ?= 1.7.0
 
+# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
+ENVTEST_K8S_VERSION = 1.24.2
+
 all: build test
 
 .PHONY: build
 build: build-cli build-plugins
 
 .PHONY: build-cli
-build-cli:
+build-cli: generate fmt vet
 	go build --ldflags="$(LDFLAGS)" \
 	-o ./bin/${BINARY_NAME} ./cmd/${BINARY_NAME}
 
@@ -42,7 +47,7 @@ install:
 .PHONY: test
 test:
 	go test -v ./...
-
+	
 .PHONY: clean
 clean:
 	go clean
@@ -122,7 +127,79 @@ e2e-deploy-gatekeeper: e2e-helm-install
     --set auditInterval=0
 
 e2e-deploy-ratify:
-	docker build -f ./httpserver/Dockerfile -t localbuild:test .
+	docker build --progress=plain --no-cache -f ./httpserver/Dockerfile -t localbuild:test .
 	kind load docker-image --name kind localbuild:test
+	
+	docker build --progress=plain --no-cache --build-arg KUBE_VERSION="1.25.0" --build-arg TARGETOS="linux" --build-arg TARGETARCH="amd64" -f crd.Dockerfile -t localbuildcrd:test ./charts/ratify/crds
+	kind load docker-image --name kind localbuildcrd:test
+
 	./.staging/helm/linux-amd64/helm install ratify \
-    ./charts/ratify --atomic --namespace ratify-service --create-namespace --set image.repository=localbuild --set image.tag=test
\ No newline at end of file
+    ./charts/ratify --atomic --namespace ratify-service --create-namespace --set image.repository=localbuild --set image.crdRepository=localbuildcrd --set image.tag=test
+
+##@ Development
+
+.PHONY: manifests
+manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
+	$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
+
+.PHONY: generate
+generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
+	$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
+
+.PHONY: fmt
+fmt: ## Run go fmt against code.
+	go fmt ./...
+
+.PHONY: vet
+vet: ## Run go vet against code.
+	go vet ./...
+
+##@ Deployment
+
+ifndef ignore-not-found
+  ignore-not-found = false
+endif
+
+.PHONY: install-crds
+install-crds: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
+	$(KUSTOMIZE) build config/crd | kubectl apply -f -
+
+.PHONY: uninstall-crds
+uninstall-crds: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
+	$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
+
+.PHONY: deploy
+deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
+	cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
+	$(KUSTOMIZE) build config/default | kubectl apply -f -
+
+.PHONY: undeploy
+undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
+	$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
+
+##@ Build Dependencies
+
+## Location to install dependencies to
+LOCALBIN ?= $(shell pwd)/bin
+$(LOCALBIN):
+	mkdir -p $(LOCALBIN)
+
+## Tool Binaries
+KUSTOMIZE ?= $(LOCALBIN)/kustomize
+CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
+ENVTEST ?= $(LOCALBIN)/setup-envtest
+
+## Tool Versions
+KUSTOMIZE_VERSION ?= v3.8.7
+CONTROLLER_TOOLS_VERSION ?= v0.9.2
+
+KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
+.PHONY: kustomize
+kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
+$(KUSTOMIZE): $(LOCALBIN)
+	test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); }
+
+.PHONY: controller-gen
+controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
+$(CONTROLLER_GEN): $(LOCALBIN)
+	test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
diff --git a/PROJECT b/PROJECT
new file mode 100644
index 0000000..b662049
--- /dev/null
+++ b/PROJECT
@@ -0,0 +1,25 @@
+domain: ratify.deislabs.io
+layout:
+- go.kubebuilder.io/v3
+projectName: ratify
+repo: github.com/deislabs/ratify
+resources:
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: ratify.deislabs.io
+  group: config
+  kind: Verifier
+  path: github.com/deislabs/ratify/api/v1alpha1
+  version: v1alpha1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: ratify.deislabs.io
+  group: config
+  kind: Store
+  path: github.com/deislabs/ratify/api/v1alpha1
+  version: v1alpha1
+version: "3"
diff --git a/api/v1alpha1/groupversion_info.go b/api/v1alpha1/groupversion_info.go
new file mode 100644
index 0000000..e10a5c6
--- /dev/null
+++ b/api/v1alpha1/groupversion_info.go
@@ -0,0 +1,36 @@
+/*
+Copyright 2022.
+
+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 v1alpha1 contains API Schema definitions for the config v1alpha1 API group
+//+kubebuilder:object:generate=true
+//+groupName=config.ratify.deislabs.io
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"sigs.k8s.io/controller-runtime/pkg/scheme"
+)
+
+var (
+	// GroupVersion is group version used to register these objects
+	GroupVersion = schema.GroupVersion{Group: "config.ratify.deislabs.io", Version: "v1alpha1"}
+
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
+	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+
+	// AddToScheme adds the types in this group-version to the given scheme.
+	AddToScheme = SchemeBuilder.AddToScheme
+)
diff --git a/api/v1alpha1/store_types.go b/api/v1alpha1/store_types.go
new file mode 100644
index 0000000..3650a06
--- /dev/null
+++ b/api/v1alpha1/store_types.go
@@ -0,0 +1,66 @@
+/*
+Copyright 2022.
+
+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 v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// StoreSpec defines the desired state of Store
+type StoreSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the verifier
+	Name string `json:"name,omitempty"`
+	// Plugin path, optional
+	Address string `json:"address,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// Parameters of the store
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// StoreStatus defines the observed state of Store
+type StoreStatus struct {
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+
+// Store is the Schema for the stores API
+type Store struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   StoreSpec   `json:"spec,omitempty"`
+	Status StoreStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// StoreList contains a list of Store
+type StoreList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Store `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&Store{}, &StoreList{})
+}
diff --git a/api/v1alpha1/verifier_types.go b/api/v1alpha1/verifier_types.go
new file mode 100644
index 0000000..ec11565
--- /dev/null
+++ b/api/v1alpha1/verifier_types.go
@@ -0,0 +1,71 @@
+/*
+Copyright 2022.
+
+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 v1alpha1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// VerifierSpec defines the desired state of Verifier
+type VerifierSpec struct {
+	// Important: Run "make" to regenerate code after modifying this file
+
+	// Name of the verifier
+	Name string `json:"name,omitempty"`
+
+	// The type of artifact this verifier handles
+	ArtifactTypes string `json:"artifactTypes,omitempty"`
+
+	// # Optional. URL/file path
+	Address string `json:"address,omitempty"`
+
+	// +kubebuilder:pruning:PreserveUnknownFields
+	// Parameters for this verifier
+	Parameters runtime.RawExtension `json:"parameters,omitempty"`
+}
+
+// VerifierStatus defines the observed state of Verifier
+type VerifierStatus struct {
+	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+	// Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:scope="Cluster"
+
+// Verifier is the Schema for the verifiers API
+type Verifier struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   VerifierSpec   `json:"spec,omitempty"`
+	Status VerifierStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// VerifierList contains a list of Verifier
+type VerifierList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []Verifier `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&Verifier{}, &VerifierList{})
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
new file mode 100644
index 0000000..c4ab93a
--- /dev/null
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,206 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright 2022.
+
+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.
+*/
+
+// Code generated by controller-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Store) DeepCopyInto(out *Store) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Store.
+func (in *Store) DeepCopy() *Store {
+	if in == nil {
+		return nil
+	}
+	out := new(Store)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Store) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreList) DeepCopyInto(out *StoreList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Store, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreList.
+func (in *StoreList) DeepCopy() *StoreList {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *StoreList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreSpec) DeepCopyInto(out *StoreSpec) {
+	*out = *in
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreSpec.
+func (in *StoreSpec) DeepCopy() *StoreSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StoreStatus) DeepCopyInto(out *StoreStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StoreStatus.
+func (in *StoreStatus) DeepCopy() *StoreStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(StoreStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Verifier) DeepCopyInto(out *Verifier) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Verifier.
+func (in *Verifier) DeepCopy() *Verifier {
+	if in == nil {
+		return nil
+	}
+	out := new(Verifier)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Verifier) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierList) DeepCopyInto(out *VerifierList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Verifier, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierList.
+func (in *VerifierList) DeepCopy() *VerifierList {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *VerifierList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierSpec) DeepCopyInto(out *VerifierSpec) {
+	*out = *in
+	in.Parameters.DeepCopyInto(&out.Parameters)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierSpec.
+func (in *VerifierSpec) DeepCopy() *VerifierSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VerifierStatus) DeepCopyInto(out *VerifierStatus) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerifierStatus.
+func (in *VerifierStatus) DeepCopy() *VerifierStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(VerifierStatus)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/charts/ratify/crds/store-customresourcedefinition.yaml b/charts/ratify/crds/store-customresourcedefinition.yaml
new file mode 100644
index 0000000..0d49145
--- /dev/null
+++ b/charts/ratify/crds/store-customresourcedefinition.yaml
@@ -0,0 +1,48 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.9.2
+  name: stores.config.ratify.deislabs.io
+spec:
+  group: config.ratify.deislabs.io
+  names:
+    kind: Store
+    listKind: StoreList
+    plural: stores
+    singular: store
+  scope: Cluster
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Store is the Schema for the stores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: StoreSpec defines the desired state of Store
+            properties:
+              address:
+                description: Plugin path, optional
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters of this store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+            type: object
+          status:
+            description: StoreStatus defines the observed state of Store
+            type: object
+        type: object
+    served: true
+    storage: true
\ No newline at end of file
diff --git a/charts/ratify/crds/verifier-customresourcedefinition.yaml b/charts/ratify/crds/verifier-customresourcedefinition.yaml
new file mode 100644
index 0000000..a436879
--- /dev/null
+++ b/charts/ratify/crds/verifier-customresourcedefinition.yaml
@@ -0,0 +1,51 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.9.2
+  name: verifiers.config.ratify.deislabs.io
+spec:
+  group: config.ratify.deislabs.io
+  names:
+    kind: Verifier
+    listKind: VerifierList
+    plural: verifiers
+    singular: verifier
+  scope: Cluster
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Verifier is the Schema for the verifiers API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: VerifierSpec defines the desired state of Verifier
+            properties:
+              address:
+                description: '# Optional. URL/file path'
+                type: string
+              artifactTypes:
+                description: The type of artifact this verifier handles
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters of this verifier
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+            type: object
+          status:
+            description: VerifierStatus defines the observed state of Verifier
+            type: object
+        type: object
+    served: true
+    storage: true
\ No newline at end of file
diff --git a/charts/ratify/templates/_helpers.tpl b/charts/ratify/templates/_helpers.tpl
index ee52a02..a328932 100644
--- a/charts/ratify/templates/_helpers.tpl
+++ b/charts/ratify/templates/_helpers.tpl
@@ -12,6 +12,12 @@ Define secret provider class name.
 {{ include "ratify.fullname" . }}-akv-secret-provider
 {{- end }}
 
+{{- define "ratify.podLabels" -}}
+{{- if .Values.podLabels }}
+{{- toYaml .Values.podLabels | nindent 8 }}
+{{- end }}
+{{- end }}
+
 {{/*
 Create a default fully qualified app name.
 We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
diff --git a/charts/ratify/templates/deployment.yaml b/charts/ratify/templates/deployment.yaml
index c2aff77..0068ff2 100644
--- a/charts/ratify/templates/deployment.yaml
+++ b/charts/ratify/templates/deployment.yaml
@@ -41,6 +41,7 @@ spec:
             - ":6001"
             - "-c"
             - "/usr/local/ratify/config.json"
+            - "--enable-crd-manager"
             {{- if eq .Values.provider.auth "tls" }}
             - --cert-dir=/usr/local/tls
             {{- end }}
diff --git a/charts/ratify/templates/ratify_manager-role-clusterrole.yaml b/charts/ratify/templates/ratify_manager-role-clusterrole.yaml
new file mode 100644
index 0000000..8e182a7
--- /dev/null
+++ b/charts/ratify/templates/ratify_manager-role-clusterrole.yaml
@@ -0,0 +1,60 @@
+{{- if .Values.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  creationTimestamp: null
+  name: ratify-manager-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/finalizers
+  verbs:
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/status
+  verbs:
+  - get
+  - patch
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/finalizers
+  verbs:
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/status
+  verbs:
+  - get
+  - patch
+  - update
+  {{- end }}
diff --git a/charts/ratify/templates/ratify_manager-rolebinding-clusterrolebinding.yaml b/charts/ratify/templates/ratify_manager-rolebinding-clusterrolebinding.yaml
new file mode 100644
index 0000000..d160195
--- /dev/null
+++ b/charts/ratify/templates/ratify_manager-rolebinding-clusterrolebinding.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  labels:
+    heritage: '{{ .Release.Service }}'
+    release: '{{ .Release.Name }}'
+  name: ratify-manager-rolebinding
+subjects:
+- kind: ServiceAccount
+  name: {{ include "ratify.serviceAccountName" . }} 
+  namespace: '{{ .Release.Namespace }}'
+roleRef:
+  kind: ClusterRole
+  name: ratify-manager-role
+  apiGroup: rbac.authorization.k8s.io
+  {{- end }}
\ No newline at end of file
diff --git a/charts/ratify/templates/store.yaml b/charts/ratify/templates/store.yaml
new file mode 100644
index 0000000..545e2d2
--- /dev/null
+++ b/charts/ratify/templates/store.yaml
@@ -0,0 +1,24 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Store
+metadata:
+  name: store-oras
+spec:
+  name: oras
+  parameters:
+    {{- if .Values.cosign.enabled }}
+    cosign-enabled: true
+    {{- end }}
+    {{- if .Values.oras.authProviders.azureWorkloadIdentityEnabled }}
+    authProvider:
+      name: azureWorkloadIdentity
+    {{- end }}
+    {{- if .Values.oras.authProviders.k8secretsEnabled }}
+    authProvider:
+      name: k8Secrets
+      secrets: 
+      - secretName: myregistrykey 
+    {{- end }}
+    {{- if .Values.oras.authProviders.awsEcrBasicEnabled }}
+    authProvider:
+      name: awsEcrBasic
+    {{- end }}
\ No newline at end of file
diff --git a/charts/ratify/templates/upgrade-crds-hook.yaml b/charts/ratify/templates/upgrade-crds-hook.yaml
new file mode 100644
index 0000000..a843c66
--- /dev/null
+++ b/charts/ratify/templates/upgrade-crds-hook.yaml
@@ -0,0 +1,118 @@
+{{- if .Values.upgradeCRDs.enabled }}
+{{- if .Values.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: ratify-admin-upgrade-crds
+  labels:
+    release: {{ .Release.Name }}
+    heritage: {{ .Release.Service }}
+  annotations:
+    helm.sh/hook: pre-install,pre-upgrade
+    helm.sh/hook-delete-policy: "hook-succeeded,before-hook-creation"
+    helm.sh/hook-weight: "1"
+rules:
+  - apiGroups: ["apiextensions.k8s.io"]
+    resources: ["customresourcedefinitions"]
+    verbs: ["get", "create", "update", "patch"]
+{{- with .Values.upgradeCRDs.extraRules }}
+  {{- toYaml . | nindent 2 }}
+{{- end }}
+{{- end }}
+---
+{{- if .Values.rbac.create }}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: ratify-admin-upgrade-crds
+  labels:
+    release: {{ .Release.Name }}
+    heritage: {{ .Release.Service }}
+  annotations:
+    helm.sh/hook: pre-install,pre-upgrade
+    helm.sh/hook-delete-policy: "hook-succeeded,before-hook-creation"
+    helm.sh/hook-weight: "1"
+subjects:
+  - kind: ServiceAccount
+    name: ratify-admin-upgrade-crds
+    namespace: {{ .Release.Namespace }}
+roleRef:
+  kind: ClusterRole
+  name: ratify-admin-upgrade-crds
+  apiGroup: rbac.authorization.k8s.io
+{{- end }}
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    release: {{ .Release.Name }}
+    heritage: {{ .Release.Service }}
+  name: ratify-admin-upgrade-crds
+  namespace: '{{ .Release.Namespace }}'
+  annotations:
+    helm.sh/hook: pre-install,pre-upgrade
+    helm.sh/hook-delete-policy: "hook-succeeded,before-hook-creation"
+    helm.sh/hook-weight: "1"
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: ratify-update-crds-hook
+  namespace: {{ .Release.Namespace }}
+  labels:
+    app: {{ template "ratify.name" . }}
+    chart: {{ template "ratify.name" . }}
+    ratify.sh/system: "yes"
+    heritage: {{ .Release.Service }}
+    release: {{ .Release.Name }}
+  annotations:
+    helm.sh/hook: pre-install,pre-upgrade
+    helm.sh/hook-weight: "1"
+    helm.sh/hook-delete-policy: "hook-succeeded,before-hook-creation"
+spec:
+  backoffLimit: 0
+  template:
+    metadata:
+      name: ratify-update-crds-hook
+      annotations:
+        {{- toYaml .Values.podAnnotations | trim | nindent 8 }}
+      labels:
+        {{- include "ratify.podLabels" . }}
+        app: '{{ template "ratify.name" . }}'
+        chart: '{{ template "ratify.name" . }}'
+        ratify.sh/system: "yes"
+        heritage: '{{ .Release.Service }}'
+        release: '{{ .Release.Name }}'
+    spec:
+      serviceAccountName: ratify-admin-upgrade-crds
+      restartPolicy: Never      
+      containers:
+      - name: crds-upgrade
+        {{- if not .Values.image.tag }}
+        image: '{{ .Values.image.crdRepository }}'
+        {{- else }}
+        image: '{{ .Values.image.crdRepository }}:{{ .Values.image.tag }}'
+        {{- end }}
+        imagePullPolicy: '{{ .Values.image.pullPolicy }}'
+        args:
+        - apply
+        - -f
+        - crds/
+        resources:
+          {{- toYaml .Values.crds.resources | nindent 10 }}
+        securityContext:
+          {{- if .Values.enableRuntimeDefaultSeccompProfile }}
+          seccompProfile:
+            type: RuntimeDefault
+          {{- end }}
+          {{- toYaml .Values.crds.securityContext | nindent 10 }}
+      {{- with .Values.crds }}
+      affinity:
+        {{- toYaml .affinity | nindent 8 }}
+      tolerations:
+        {{- toYaml .tolerations | nindent 8 }}
+      nodeSelector:
+        {{- toYaml .nodeSelector | nindent 8 }}
+      {{- end }}
+{{- end }}
diff --git a/charts/ratify/templates/verifier.yaml b/charts/ratify/templates/verifier.yaml
new file mode 100644
index 0000000..63cc591
--- /dev/null
+++ b/charts/ratify/templates/verifier.yaml
@@ -0,0 +1,22 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-notary
+spec:
+  name: notaryv2
+  artifactTypes: application/vnd.cncf.notary.v2.signature
+  parameters:
+    verificationCerts: 
+    - /usr/local/ratify-certs/notary
+---
+{{- if .Values.cosign.enabled }}
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-cosign
+spec:
+  name: cosign
+  artifactTypes: org.sigstore.cosign.v1
+  parameters:
+    key: /usr/local/ratify-certs/cosign/cosign.pub
+{{- end }}
\ No newline at end of file
diff --git a/charts/ratify/values.yaml b/charts/ratify/values.yaml
index 0de19d2..9597ebe 100644
--- a/charts/ratify/values.yaml
+++ b/charts/ratify/values.yaml
@@ -2,6 +2,7 @@ image:
   repository: ghcr.io/deislabs/ratify
   tag: v1.0.0-alpha.3
   pullPolicy: IfNotPresent
+
 nameOverride: ""
 fullnameOverride: ""
 ratifyTestCert: |
@@ -63,4 +64,28 @@ provider:
     key: ""                 # key used by ratify (httpserver)
     cabundle: ""            # base64 encoded CA bundle used for the 'caBundle' property for the ratify provider within gatekeeper
 
+podAnnotations: {}
+podLabels: {}
+enableRuntimeDefaultSeccompProfile: true
+
+rbac:
+  create: true
+  
+upgradeCRDs:
+  enabled: true
+  extraRules: []
 
+crds:
+  affinity: {}
+  tolerations: []
+  nodeSelector: {kubernetes.io/os: linux}
+  resources: {}
+  securityContext:
+    allowPrivilegeEscalation: false
+    capabilities:
+      drop:
+      - ALL
+    readOnlyRootFilesystem: true
+    runAsGroup: 65532
+    runAsNonRoot: true
+    runAsUser: 65532
diff --git a/cmd/ratify/cmd/serve.go b/cmd/ratify/cmd/serve.go
index e5934e1..fa54988 100644
--- a/cmd/ratify/cmd/serve.go
+++ b/cmd/ratify/cmd/serve.go
@@ -20,6 +20,7 @@ import (
 
 	"github.com/deislabs/ratify/config"
 	"github.com/deislabs/ratify/httpserver"
+	"github.com/deislabs/ratify/pkg/manager"
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
@@ -33,6 +34,7 @@ type serveCmdOptions struct {
 	httpServerAddress string
 	certDirectory     string
 	caCertFile        string
+	enableCrdManager  bool
 }
 
 func NewCmdServe(argv ...string) *cobra.Command {
@@ -55,11 +57,21 @@ func NewCmdServe(argv ...string) *cobra.Command {
 	flags.StringVarP(&opts.configFilePath, "config", "c", "", "Config File Path")
 	flags.StringVar(&opts.certDirectory, "cert-dir", "", "Path to ratify certs")
 	flags.StringVar(&opts.caCertFile, "ca-cert-file", "", "Path to CA cert file")
+	flags.BoolVar(&opts.enableCrdManager, "enable-crd-manager", false, "Start crd manager if enabled")
 	return cmd
 }
 
 func serve(opts serveCmdOptions) error {
 
+	// in crd mode, the manager gets latest store/verifier from crd and pass on to the http server
+	if opts.enableCrdManager {
+		logrus.Infof("starting crd manager")
+		go manager.StartManager()
+		manager.StartServer(opts.httpServerAddress, opts.certDirectory, opts.caCertFile)
+
+		return nil
+	}
+
 	getExecutor, err := config.GetExecutorAndWatchForUpdate(opts.configFilePath)
 	if err != nil {
 		return err
diff --git a/config/config.go b/config/config.go
index 3cd3866..2de6324 100644
--- a/config/config.go
+++ b/config/config.go
@@ -27,9 +27,17 @@ import (
 
 	exConfig "github.com/deislabs/ratify/pkg/executor/config"
 	"github.com/deislabs/ratify/pkg/homedir"
+	"github.com/deislabs/ratify/pkg/policyprovider"
 	pcConfig "github.com/deislabs/ratify/pkg/policyprovider/config"
+	pf "github.com/deislabs/ratify/pkg/policyprovider/factory"
+	"github.com/deislabs/ratify/pkg/referrerstore"
 	rsConfig "github.com/deislabs/ratify/pkg/referrerstore/config"
+	sf "github.com/deislabs/ratify/pkg/referrerstore/factory"
+	"github.com/deislabs/ratify/pkg/verifier"
 	vfConfig "github.com/deislabs/ratify/pkg/verifier/config"
+	vf "github.com/deislabs/ratify/pkg/verifier/factory"
+	"github.com/pkg/errors"
+	"github.com/sirupsen/logrus"
 )
 
 const (
@@ -74,6 +82,34 @@ func getHomeDir() string {
 	return homeDir
 }
 
+// Returns created referer store, verifier, policyprovider objects from config
+func CreateFromConfig(cf Config) ([]referrerstore.ReferrerStore, []verifier.ReferenceVerifier, policyprovider.PolicyProvider, error) {
+	stores, err := sf.CreateStoresFromConfig(cf.StoresConfig, GetDefaultPluginPath())
+
+	if err != nil {
+		return nil, nil, nil, errors.Wrap(err, "failed to load store from config")
+	}
+	logrus.Infof("stores successfully created. number of stores %d", len(stores))
+
+	verifiers, err := vf.CreateVerifiersFromConfig(cf.VerifiersConfig, GetDefaultPluginPath())
+
+	if err != nil {
+		return nil, nil, nil, errors.Wrap(err, "failed to load verifiers from config")
+	}
+
+	logrus.Infof("verifiers successfully created. number of verifiers %d", len(verifiers))
+
+	policyEnforcer, err := pf.CreatePolicyProviderFromConfig(cf.PoliciesConfig)
+
+	if err != nil {
+		return nil, nil, nil, errors.Wrap(err, "failed to load policy provider from config")
+	}
+
+	logrus.Infof("policies successfully created.")
+
+	return stores, verifiers, policyEnforcer, nil
+}
+
 // Load the config from file path provided, read from default path if configFilePath is empty
 func Load(configFilePath string) (Config, error) {
 
diff --git a/config/configManager.go b/config/configManager.go
index 4b51735..734e8e6 100644
--- a/config/configManager.go
+++ b/config/configManager.go
@@ -20,12 +20,6 @@ import (
 	"time"
 
 	ef "github.com/deislabs/ratify/pkg/executor/core"
-	"github.com/deislabs/ratify/pkg/policyprovider"
-	pf "github.com/deislabs/ratify/pkg/policyprovider/factory"
-	"github.com/deislabs/ratify/pkg/referrerstore"
-	sf "github.com/deislabs/ratify/pkg/referrerstore/factory"
-	"github.com/deislabs/ratify/pkg/verifier"
-	vf "github.com/deislabs/ratify/pkg/verifier/factory"
 	"github.com/fsnotify/fsnotify"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -50,7 +44,7 @@ func GetExecutorAndWatchForUpdate(configFilePath string) (GetExecutor, error) {
 
 	configHash = cf.fileHash
 
-	stores, verifiers, policyEnforcer, err := createFromConfig(cf)
+	stores, verifiers, policyEnforcer, err := CreateFromConfig(cf)
 
 	if err != nil {
 		return func() *ef.Executor { return &ef.Executor{} }, err
@@ -74,34 +68,6 @@ func GetExecutorAndWatchForUpdate(configFilePath string) (GetExecutor, error) {
 	return func() *ef.Executor { return &executor }, nil
 }
 
-// Returns created referer store, verifier, policyprovider objects from config
-func createFromConfig(cf Config) ([]referrerstore.ReferrerStore, []verifier.ReferenceVerifier, policyprovider.PolicyProvider, error) {
-	stores, err := sf.CreateStoresFromConfig(cf.StoresConfig, GetDefaultPluginPath())
-
-	if err != nil {
-		return nil, nil, nil, errors.Wrap(err, "failed to load store from config")
-	}
-	logrus.Infof("stores successfully created. number of stores %d", len(stores))
-
-	verifiers, err := vf.CreateVerifiersFromConfig(cf.VerifiersConfig, GetDefaultPluginPath())
-
-	if err != nil {
-		return nil, nil, nil, errors.Wrap(err, "failed to load verifiers from config")
-	}
-
-	logrus.Infof("verifiers successfully created. number of verifiers %d", len(verifiers))
-
-	policyEnforcer, err := pf.CreatePolicyProviderFromConfig(cf.PoliciesConfig)
-
-	if err != nil {
-		return nil, nil, nil, errors.Wrap(err, "failed to load policy provider from config")
-	}
-
-	logrus.Infof("policies successfully created.")
-
-	return stores, verifiers, policyEnforcer, nil
-}
-
 func reloadExecutor(configFilePath string) {
 
 	cf, err := Load(configFilePath)
@@ -112,7 +78,7 @@ func reloadExecutor(configFilePath string) {
 	}
 
 	if configHash != cf.fileHash {
-		stores, verifiers, policyEnforcer, err := createFromConfig(cf)
+		stores, verifiers, policyEnforcer, err := CreateFromConfig(cf)
 
 		newExecutor := ef.Executor{
 			Verifiers:      verifiers,
diff --git a/config/crd/bases/config.ratify.deislabs.io_stores.yaml b/config/crd/bases/config.ratify.deislabs.io_stores.yaml
new file mode 100644
index 0000000..bc484f7
--- /dev/null
+++ b/config/crd/bases/config.ratify.deislabs.io_stores.yaml
@@ -0,0 +1,54 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.9.2
+  creationTimestamp: null
+  name: stores.config.ratify.deislabs.io
+spec:
+  group: config.ratify.deislabs.io
+  names:
+    kind: Store
+    listKind: StoreList
+    plural: stores
+    singular: store
+  scope: Cluster
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Store is the Schema for the stores API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: StoreSpec defines the desired state of Store
+            properties:
+              address:
+                description: Plugin path, optional
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters of the store
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+            type: object
+          status:
+            description: StoreStatus defines the observed state of Store
+            type: object
+        type: object
+    served: true
+    storage: true
diff --git a/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
new file mode 100644
index 0000000..8c30590
--- /dev/null
+++ b/config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
@@ -0,0 +1,57 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.9.2
+  creationTimestamp: null
+  name: verifiers.config.ratify.deislabs.io
+spec:
+  group: config.ratify.deislabs.io
+  names:
+    kind: Verifier
+    listKind: VerifierList
+    plural: verifiers
+    singular: verifier
+  scope: Cluster
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: Verifier is the Schema for the verifiers API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: VerifierSpec defines the desired state of Verifier
+            properties:
+              address:
+                description: '# Optional. URL/file path'
+                type: string
+              artifactTypes:
+                description: The type of artifact this verifier handles
+                type: string
+              name:
+                description: Name of the verifier
+                type: string
+              parameters:
+                description: Parameters for this verifier
+                type: object
+                x-kubernetes-preserve-unknown-fields: true
+            type: object
+          status:
+            description: VerifierStatus defines the observed state of Verifier
+            type: object
+        type: object
+    served: true
+    storage: true
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
new file mode 100644
index 0000000..ba983ce
--- /dev/null
+++ b/config/crd/kustomization.yaml
@@ -0,0 +1,24 @@
+# This kustomization.yaml is not intended to be run by itself,
+# since it depends on service name and namespace that are out of this kustomize package.
+# It should be run by config/default
+resources:
+- bases/config.ratify.deislabs.io_verifiers.yaml
+- bases/config.ratify.deislabs.io_stores.yaml
+#+kubebuilder:scaffold:crdkustomizeresource
+
+patchesStrategicMerge:
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# patches here are for enabling the conversion webhook for each CRD
+#- patches/webhook_in_verifiers.yaml
+#- patches/webhook_in_stores.yaml
+#+kubebuilder:scaffold:crdkustomizewebhookpatch
+
+# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
+# patches here are for enabling the CA injection for each CRD
+#- patches/cainjection_in_verifiers.yaml
+#- patches/cainjection_in_stores.yaml
+#+kubebuilder:scaffold:crdkustomizecainjectionpatch
+
+# the following config is for teaching kustomize how to do kustomization for CRDs.
+configurations:
+- kustomizeconfig.yaml
diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml
new file mode 100644
index 0000000..ec5c150
--- /dev/null
+++ b/config/crd/kustomizeconfig.yaml
@@ -0,0 +1,19 @@
+# This file is for teaching kustomize how to substitute name and namespace reference in CRD
+nameReference:
+- kind: Service
+  version: v1
+  fieldSpecs:
+  - kind: CustomResourceDefinition
+    version: v1
+    group: apiextensions.k8s.io
+    path: spec/conversion/webhook/clientConfig/service/name
+
+namespace:
+- kind: CustomResourceDefinition
+  version: v1
+  group: apiextensions.k8s.io
+  path: spec/conversion/webhook/clientConfig/service/namespace
+  create: false
+
+varReference:
+- path: metadata/annotations
diff --git a/config/crd/patches/cainjection_in_stores.yaml b/config/crd/patches/cainjection_in_stores.yaml
new file mode 100644
index 0000000..09a382b
--- /dev/null
+++ b/config/crd/patches/cainjection_in_stores.yaml
@@ -0,0 +1,7 @@
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: stores.config.ratify.deislabs.io
diff --git a/config/crd/patches/cainjection_in_verifiers.yaml b/config/crd/patches/cainjection_in_verifiers.yaml
new file mode 100644
index 0000000..13ec9e1
--- /dev/null
+++ b/config/crd/patches/cainjection_in_verifiers.yaml
@@ -0,0 +1,7 @@
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: verifiers.config.ratify.deislabs.io
diff --git a/config/crd/patches/webhook_in_stores.yaml b/config/crd/patches/webhook_in_stores.yaml
new file mode 100644
index 0000000..5c9222a
--- /dev/null
+++ b/config/crd/patches/webhook_in_stores.yaml
@@ -0,0 +1,16 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: stores.config.ratify.deislabs.io
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/config/crd/patches/webhook_in_verifiers.yaml b/config/crd/patches/webhook_in_verifiers.yaml
new file mode 100644
index 0000000..95dad9b
--- /dev/null
+++ b/config/crd/patches/webhook_in_verifiers.yaml
@@ -0,0 +1,16 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: verifiers.config.ratify.deislabs.io
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml
new file mode 100644
index 0000000..2524949
--- /dev/null
+++ b/config/default/kustomization.yaml
@@ -0,0 +1,74 @@
+# Adds namespace to all resources.
+namespace: ratify-system
+
+# Value of this field is prepended to the
+# names of all resources, e.g. a deployment named
+# "wordpress" becomes "alices-wordpress".
+# Note that it should also match with the prefix (text before '-') of the namespace
+# field above.
+namePrefix: ratify-
+
+# Labels to add to all resources and selectors.
+#commonLabels:
+#  someName: someValue
+
+bases:
+- ../crd
+- ../rbac
+- ../manager
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+#- ../webhook
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
+#- ../certmanager
+# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
+#- ../prometheus
+
+patchesStrategicMerge:
+# Protect the /metrics endpoint by putting it behind auth.
+# If you want your controller-manager to expose the /metrics
+# endpoint w/o any authn/z, please comment the following line.
+- manager_auth_proxy_patch.yaml
+
+# Mount the controller config file for loading manager configurations
+# through a ComponentConfig type
+#- manager_config_patch.yaml
+
+# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
+# crd/kustomization.yaml
+#- manager_webhook_patch.yaml
+
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
+# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
+# 'CERTMANAGER' needs to be enabled to use ca injection
+#- webhookcainjection_patch.yaml
+
+# the following config is for teaching kustomize how to do var substitution
+vars:
+# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
+#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
+#  objref:
+#    kind: Certificate
+#    group: cert-manager.io
+#    version: v1
+#    name: serving-cert # this name should match the one in certificate.yaml
+#  fieldref:
+#    fieldpath: metadata.namespace
+#- name: CERTIFICATE_NAME
+#  objref:
+#    kind: Certificate
+#    group: cert-manager.io
+#    version: v1
+#    name: serving-cert # this name should match the one in certificate.yaml
+#- name: SERVICE_NAMESPACE # namespace of the service
+#  objref:
+#    kind: Service
+#    version: v1
+#    name: webhook-service
+#  fieldref:
+#    fieldpath: metadata.namespace
+#- name: SERVICE_NAME
+#  objref:
+#    kind: Service
+#    version: v1
+#    name: webhook-service
diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml
new file mode 100644
index 0000000..cec149a
--- /dev/null
+++ b/config/default/manager_auth_proxy_patch.yaml
@@ -0,0 +1,39 @@
+# This patch inject a sidecar container which is a HTTP proxy for the
+# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller-manager
+  namespace: system
+spec:
+  template:
+    spec:
+      containers:
+      - name: kube-rbac-proxy
+        securityContext:
+          allowPrivilegeEscalation: false
+          capabilities:
+            drop:
+              - "ALL"
+        image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0
+        args:
+        - "--secure-listen-address=0.0.0.0:8443"
+        - "--upstream=http://127.0.0.1:8080/"
+        - "--logtostderr=true"
+        - "--v=0"
+        ports:
+        - containerPort: 8443
+          protocol: TCP
+          name: https
+        resources:
+          limits:
+            cpu: 500m
+            memory: 128Mi
+          requests:
+            cpu: 5m
+            memory: 64Mi
+      - name: manager
+        args:
+        - "--health-probe-bind-address=:8081"
+        - "--metrics-bind-address=127.0.0.1:8080"
+        - "--leader-elect"
diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml
new file mode 100644
index 0000000..6c40015
--- /dev/null
+++ b/config/default/manager_config_patch.yaml
@@ -0,0 +1,20 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller-manager
+  namespace: system
+spec:
+  template:
+    spec:
+      containers:
+      - name: manager
+        args:
+        - "--config=controller_manager_config.yaml"
+        volumeMounts:
+        - name: manager-config
+          mountPath: /controller_manager_config.yaml
+          subPath: controller_manager_config.yaml
+      volumes:
+      - name: manager-config
+        configMap:
+          name: manager-config
diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml
new file mode 100644
index 0000000..717c97d
--- /dev/null
+++ b/config/manager/controller_manager_config.yaml
@@ -0,0 +1,21 @@
+apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
+kind: ControllerManagerConfig
+health:
+  healthProbeBindAddress: :8081
+metrics:
+  bindAddress: 127.0.0.1:8080
+webhook:
+  port: 9443
+leaderElection:
+  leaderElect: true
+  resourceName: 909057b5.ratify.deislabs.io
+# leaderElectionReleaseOnCancel defines if the leader should step down volume
+# when the Manager ends. This requires the binary to immediately end when the
+# Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
+# speeds up voluntary leader transitions as the new leader don't have to wait
+# LeaseDuration time first.
+# In the default scaffold provided, the program ends immediately after
+# the manager stops, so would be fine to enable this option. However,
+# if you are doing or is intended to do any operation such as perform cleanups
+# after the manager stops then its usage might be unsafe.
+# leaderElectionReleaseOnCancel: true
diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml
new file mode 100644
index 0000000..2bcd3ee
--- /dev/null
+++ b/config/manager/kustomization.yaml
@@ -0,0 +1,10 @@
+resources:
+- manager.yaml
+
+generatorOptions:
+  disableNameSuffixHash: true
+
+configMapGenerator:
+- name: manager-config
+  files:
+  - controller_manager_config.yaml
diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml
new file mode 100644
index 0000000..878ad48
--- /dev/null
+++ b/config/manager/manager.yaml
@@ -0,0 +1,70 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  labels:
+    control-plane: controller-manager
+  name: system
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller-manager
+  namespace: system
+  labels:
+    control-plane: controller-manager
+spec:
+  selector:
+    matchLabels:
+      control-plane: controller-manager
+  replicas: 1
+  template:
+    metadata:
+      annotations:
+        kubectl.kubernetes.io/default-container: manager
+      labels:
+        control-plane: controller-manager
+    spec:
+      securityContext:
+        runAsNonRoot: true
+        # TODO(user): For common cases that do not require escalating privileges
+        # it is recommended to ensure that all your Pods/Containers are restrictive.
+        # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
+        # Please uncomment the following code if your project does NOT have to work on old Kubernetes
+        # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
+        # seccompProfile:
+        #   type: RuntimeDefault
+      containers:
+      - command:
+        - /manager
+        args:
+        - --leader-elect
+        image: controller:latest
+        name: manager
+        securityContext:
+          allowPrivilegeEscalation: false
+          capabilities:
+            drop:
+              - "ALL"
+        livenessProbe:
+          httpGet:
+            path: /healthz
+            port: 8081
+          initialDelaySeconds: 15
+          periodSeconds: 20
+        readinessProbe:
+          httpGet:
+            path: /readyz
+            port: 8081
+          initialDelaySeconds: 5
+          periodSeconds: 10
+        # TODO(user): Configure the resources accordingly based on the project requirements.
+        # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
+        resources:
+          limits:
+            cpu: 500m
+            memory: 128Mi
+          requests:
+            cpu: 10m
+            memory: 64Mi
+      serviceAccountName: controller-manager
+      terminationGracePeriodSeconds: 10
diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml
new file mode 100644
index 0000000..51a75db
--- /dev/null
+++ b/config/rbac/auth_proxy_client_clusterrole.yaml
@@ -0,0 +1,9 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: metrics-reader
+rules:
+- nonResourceURLs:
+  - "/metrics"
+  verbs:
+  - get
diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml
new file mode 100644
index 0000000..80e1857
--- /dev/null
+++ b/config/rbac/auth_proxy_role.yaml
@@ -0,0 +1,17 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: proxy-role
+rules:
+- apiGroups:
+  - authentication.k8s.io
+  resources:
+  - tokenreviews
+  verbs:
+  - create
+- apiGroups:
+  - authorization.k8s.io
+  resources:
+  - subjectaccessreviews
+  verbs:
+  - create
diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml
new file mode 100644
index 0000000..ec7acc0
--- /dev/null
+++ b/config/rbac/auth_proxy_role_binding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: proxy-rolebinding
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: proxy-role
+subjects:
+- kind: ServiceAccount
+  name: controller-manager
+  namespace: system
diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml
new file mode 100644
index 0000000..71f1797
--- /dev/null
+++ b/config/rbac/auth_proxy_service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    control-plane: controller-manager
+  name: controller-manager-metrics-service
+  namespace: system
+spec:
+  ports:
+  - name: https
+    port: 8443
+    protocol: TCP
+    targetPort: https
+  selector:
+    control-plane: controller-manager
diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml
new file mode 100644
index 0000000..731832a
--- /dev/null
+++ b/config/rbac/kustomization.yaml
@@ -0,0 +1,18 @@
+resources:
+# All RBAC will be applied under this service account in
+# the deployment namespace. You may comment out this resource
+# if your manager will use a service account that exists at
+# runtime. Be sure to update RoleBinding and ClusterRoleBinding
+# subjects if changing service account names.
+- service_account.yaml
+- role.yaml
+- role_binding.yaml
+- leader_election_role.yaml
+- leader_election_role_binding.yaml
+# Comment the following 4 lines if you want to disable
+# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
+# which protects your /metrics endpoint.
+- auth_proxy_service.yaml
+- auth_proxy_role.yaml
+- auth_proxy_role_binding.yaml
+- auth_proxy_client_clusterrole.yaml
diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml
new file mode 100644
index 0000000..4190ec8
--- /dev/null
+++ b/config/rbac/leader_election_role.yaml
@@ -0,0 +1,37 @@
+# permissions to do leader election.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  name: leader-election-role
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - configmaps
+  verbs:
+  - get
+  - list
+  - watch
+  - create
+  - update
+  - patch
+  - delete
+- apiGroups:
+  - coordination.k8s.io
+  resources:
+  - leases
+  verbs:
+  - get
+  - list
+  - watch
+  - create
+  - update
+  - patch
+  - delete
+- apiGroups:
+  - ""
+  resources:
+  - events
+  verbs:
+  - create
+  - patch
diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml
new file mode 100644
index 0000000..1d1321e
--- /dev/null
+++ b/config/rbac/leader_election_role_binding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  name: leader-election-rolebinding
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: leader-election-role
+subjects:
+- kind: ServiceAccount
+  name: controller-manager
+  namespace: system
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
new file mode 100644
index 0000000..9f2e72a
--- /dev/null
+++ b/config/rbac/role.yaml
@@ -0,0 +1,59 @@
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  creationTimestamp: null
+  name: manager-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/finalizers
+  verbs:
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/status
+  verbs:
+  - get
+  - patch
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/finalizers
+  verbs:
+  - update
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/status
+  verbs:
+  - get
+  - patch
+  - update
diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml
new file mode 100644
index 0000000..2070ede
--- /dev/null
+++ b/config/rbac/role_binding.yaml
@@ -0,0 +1,12 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: manager-rolebinding
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: manager-role
+subjects:
+- kind: ServiceAccount
+  name: controller-manager
+  namespace: system
diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml
new file mode 100644
index 0000000..7cd6025
--- /dev/null
+++ b/config/rbac/service_account.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: controller-manager
+  namespace: system
diff --git a/config/rbac/store_editor_role.yaml b/config/rbac/store_editor_role.yaml
new file mode 100644
index 0000000..eb65008
--- /dev/null
+++ b/config/rbac/store_editor_role.yaml
@@ -0,0 +1,24 @@
+# permissions for end users to edit stores.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: store-editor-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/status
+  verbs:
+  - get
diff --git a/config/rbac/store_viewer_role.yaml b/config/rbac/store_viewer_role.yaml
new file mode 100644
index 0000000..79f4317
--- /dev/null
+++ b/config/rbac/store_viewer_role.yaml
@@ -0,0 +1,20 @@
+# permissions for end users to view stores.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: store-viewer-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - stores/status
+  verbs:
+  - get
diff --git a/config/rbac/verifier_editor_role.yaml b/config/rbac/verifier_editor_role.yaml
new file mode 100644
index 0000000..36b8a40
--- /dev/null
+++ b/config/rbac/verifier_editor_role.yaml
@@ -0,0 +1,24 @@
+# permissions for end users to edit verifiers.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: verifier-editor-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/status
+  verbs:
+  - get
diff --git a/config/rbac/verifier_viewer_role.yaml b/config/rbac/verifier_viewer_role.yaml
new file mode 100644
index 0000000..5b1ccf6
--- /dev/null
+++ b/config/rbac/verifier_viewer_role.yaml
@@ -0,0 +1,20 @@
+# permissions for end users to view verifiers.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: verifier-viewer-role
+rules:
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - config.ratify.deislabs.io
+  resources:
+  - verifiers/status
+  verbs:
+  - get
diff --git a/config/samples/config_v1alpha1_store_k8secretAuth.yaml b/config/samples/config_v1alpha1_store_k8secretAuth.yaml
new file mode 100644
index 0000000..d259c3c
--- /dev/null
+++ b/config/samples/config_v1alpha1_store_k8secretAuth.yaml
@@ -0,0 +1,12 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Store
+metadata:
+  name: store-orask8secret
+spec:
+  name: oras
+  parameters:
+    cosign-enabled: false    
+    authProvider:
+      name: k8Secrets
+      secrets: 
+      - secretName: myregistrykey
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_store_oras.yaml b/config/samples/config_v1alpha1_store_oras.yaml
new file mode 100644
index 0000000..faee740
--- /dev/null
+++ b/config/samples/config_v1alpha1_store_oras.yaml
@@ -0,0 +1,7 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Store
+metadata:
+  name: store-oras
+spec:
+  name: oras  
+    
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_verifier_cosign.yaml b/config/samples/config_v1alpha1_verifier_cosign.yaml
new file mode 100644
index 0000000..ec281d8
--- /dev/null
+++ b/config/samples/config_v1alpha1_verifier_cosign.yaml
@@ -0,0 +1,9 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-cosign
+spec:
+  name: cosign
+  artifactTypes: org.sigstore.cosign.v1
+  parameters:
+    key: /usr/local/ratify-certs/cosign.pub
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_verifier_licensechecker.yaml b/config/samples/config_v1alpha1_verifier_licensechecker.yaml
new file mode 100644
index 0000000..fd9fa87
--- /dev/null
+++ b/config/samples/config_v1alpha1_verifier_licensechecker.yaml
@@ -0,0 +1,10 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-license-checker
+spec:
+  name: licensechecker
+  artifactTypes: application/vnd.ratify.spdx.v0
+  parameters: 
+    allowedLicenses: 
+    - MIT
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_verifier_notary.yaml b/config/samples/config_v1alpha1_verifier_notary.yaml
new file mode 100644
index 0000000..5acaaa9
--- /dev/null
+++ b/config/samples/config_v1alpha1_verifier_notary.yaml
@@ -0,0 +1,11 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-notary
+spec:
+  name: notaryv2
+  artifactTypes: application/vnd.cncf.notary.v2.signature
+  parameters:
+    verificationCerts: 
+    - /usr/local/ratify-certs/notary
+     
\ No newline at end of file
diff --git a/config/samples/config_v1alpha1_verifier_sbom.yaml b/config/samples/config_v1alpha1_verifier_sbom.yaml
new file mode 100644
index 0000000..ac5f1ea
--- /dev/null
+++ b/config/samples/config_v1alpha1_verifier_sbom.yaml
@@ -0,0 +1,11 @@
+apiVersion: config.ratify.deislabs.io/v1alpha1
+kind: Verifier
+metadata:
+  name: verifier-sbom
+spec:
+  name: sbom
+  artifactTypes: org.example.sbom.v0
+  parameters: 
+    nestedReferences: application/vnd.cncf.notary.v2.signature
+ 
+     
\ No newline at end of file
diff --git a/crd.Dockerfile b/crd.Dockerfile
new file mode 100644
index 0000000..1abb651
--- /dev/null
+++ b/crd.Dockerfile
@@ -0,0 +1,15 @@
+FROM alpine as builder
+
+ARG TARGETOS
+ARG TARGETARCH
+ARG KUBE_VERSION
+
+RUN apk add --no-cache curl && \
+    curl -LO https://storage.googleapis.com/kubernetes-release/release/v${KUBE_VERSION}/bin/${TARGETOS}/${TARGETARCH}/kubectl && \
+    chmod +x kubectl
+
+FROM scratch as build
+USER 65532:65532
+COPY --chown=65532:65532 * /crds/
+COPY --from=builder /kubectl /kubectl
+ENTRYPOINT ["/kubectl"]
diff --git a/docs/ratify-configuration.md b/docs/ratify-configuration.md
new file mode 100644
index 0000000..a0478a0
--- /dev/null
+++ b/docs/ratify-configuration.md
@@ -0,0 +1,5 @@
+Ratify's configuration consist of [Store](store.md), [Verifier](verifier.md), [Policy](policy-provider.md) and [Executor](executor.md). 
+
+When Ratify runs in cli serve mode, configuration file can be dynamically updated while the server is running, subsequent verification will be based on the updated configuration.
+
+When running Ratify in a pod, configMap will be mounted to the pod at the default configuration file path. Ratify will initialize with specifications from the configuration file, CRDs will override store and verifier defined from the configuration file if they exist at runtime. Our team is in process converting configuration components into Ratify CRDS to support a more native k8s experience. Please review ratify CRDs in the [charts](../charts/ratify/crds/) directory.
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 948b23f..5670999 100644
--- a/go.mod
+++ b/go.mod
@@ -81,12 +81,14 @@ require (
 	github.com/emicklei/go-restful v2.9.5+incompatible // indirect
 	github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
 	github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
+	github.com/evanphx/json-patch v4.12.0+incompatible // indirect
 	github.com/fullstorydev/grpcurl v1.8.7 // indirect
 	github.com/fxamacker/cbor/v2 v2.4.0 // indirect
 	github.com/ghodss/yaml v1.0.0 // indirect
 	github.com/go-chi/chi v4.1.2+incompatible // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
+	github.com/go-logr/zapr v1.2.0 // indirect
 	github.com/go-openapi/analysis v0.21.4 // indirect
 	github.com/go-openapi/errors v0.20.3 // indirect
 	github.com/go-openapi/jsonpointer v0.19.5 // indirect
@@ -120,6 +122,7 @@ require (
 	github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
+	github.com/imdario/mergo v0.3.12 // indirect
 	github.com/in-toto/in-toto-golang v0.3.4-0.20220709202702-fa494aaa0add // indirect
 	github.com/inconshreveable/mousetrap v1.0.1 // indirect
 	github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect
@@ -216,6 +219,7 @@ require (
 	golang.org/x/text v0.4.0 // indirect
 	golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
 	golang.org/x/tools v0.1.12 // indirect
+	gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
 	google.golang.org/appengine v1.6.7 // indirect
 	google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a // indirect
 	gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
@@ -225,10 +229,12 @@ require (
 	gopkg.in/square/go-jose.v2 v2.6.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
+	k8s.io/apiextensions-apiserver v0.24.2 // indirect
+	k8s.io/component-base v0.24.2 // indirect
 	k8s.io/klog/v2 v2.60.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
 	k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
-	sigs.k8s.io/controller-runtime v0.12.2 // indirect
+	sigs.k8s.io/controller-runtime v0.12.2
 	sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
 	sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
 	sigs.k8s.io/yaml v1.3.0 // indirect
diff --git a/go.sum b/go.sum
index aa4d50a..6cb7134 100644
--- a/go.sum
+++ b/go.sum
@@ -75,6 +75,8 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4Sath
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY=
 github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
@@ -101,14 +103,17 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
 github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
 github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
 github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
 github.com/apache/beam/sdks/v2 v2.0.0-20211012030016-ef4364519c94/go.mod h1:/kOom7hCyHVzAC/Z7HbZywkZZv6ywF+wb4CvgDVdcB8=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -163,6 +168,7 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
 github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
 github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
 github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
 github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@@ -205,6 +211,7 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -261,6 +268,8 @@ github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4
 github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE=
 github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
 github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE=
+github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
+github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
 github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
 github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
@@ -268,6 +277,7 @@ github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 h1:IeaD1VDVB
 github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 h1:a4DFiKFJiDRGFD1qIcqGLX/WlUMD9dyLSLDt+9QZgt8=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
 github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@@ -301,6 +311,7 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
 github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -309,6 +320,8 @@ github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV
 github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
+github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
 github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
 github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
 github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
@@ -448,6 +461,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
 github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
 github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
 github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
+github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
+github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
 github.com/google/certificate-transparency-go v1.1.3 h1:WEb38wcTe0EuAvg7USzgklnOjjnlMaahYO3faaqnCn8=
 github.com/google/certificate-transparency-go v1.1.3/go.mod h1:S9FT/VzOUzhOGG0iLrzDs+f5Ml/zm7IYY/w+IlHz01M=
 github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
@@ -510,6 +525,8 @@ github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pf
 github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
 github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
 github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
+github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
+github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
 github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
@@ -562,6 +579,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
 github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
+github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/in-toto/in-toto-golang v0.3.4-0.20220709202702-fa494aaa0add h1:DAh7mHiRT7wc6kKepYdCpH16ElPciMPQWJaJ7H3l/ng=
 github.com/in-toto/in-toto-golang v0.3.4-0.20220709202702-fa494aaa0add/go.mod h1:DQI8vlV6h6qSY/tCOoYKtxjWrkyiNpJ3WTV/WoBllmQ=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -591,6 +609,7 @@ github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQy
 github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -611,6 +630,7 @@ github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B
 github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -674,6 +694,8 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
 github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
+github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
+github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -761,15 +783,18 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
 github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
 github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
 github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
 github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
 github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
@@ -816,7 +841,9 @@ github.com/sigstore/sigstore v1.4.5/go.mod h1:mg/+e74CCjEdJpWNjWRAlxMUd39VWh5t1+
 github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -849,6 +876,7 @@ github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUq
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
+github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@@ -935,10 +963,12 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
 go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 h1:se+XckWlVTTfwjZSsAZJ2zGPzmIMq3j7fKBCmHoB9UA=
 go.etcd.io/etcd/api/v3 v3.6.0-alpha.0/go.mod h1:z13pg39zewDLZeXIKeM0xELOeFKcqjLocfwl5M820+w=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 h1:2UyRzFWbZZzgu/xzxoRukgixvafiJtGyxO+3IKUyJ6c=
 go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0/go.mod h1:Vl/FkH40bHqmBFwhr8WVKtV47neyts36zl1voccRq8s=
@@ -946,6 +976,8 @@ go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsX
 go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
 go.etcd.io/etcd/client/v2 v2.306.0-alpha.0 h1:9VRJ698EFIMfjOQtcjKMM7CWXOIxp9R4I8JA1mk+WT4=
 go.etcd.io/etcd/client/v2 v2.306.0-alpha.0/go.mod h1:eW78BCfOzS1HJgTNzDrb2E6xV1p6kqlpLpKkz7ErzCs=
+go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
+go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q=
 go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
 go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 h1:hHaJ8CvTPJ9iv7xPz3G0gxt3csEqJW8evgty/kYICwo=
 go.etcd.io/etcd/client/v3 v3.6.0-alpha.0/go.mod h1:a9JuChoQBDnw7WclHYBYCtTOIC12Wwj+Fw0LX4TI/Gs=
@@ -955,12 +987,15 @@ go.etcd.io/etcd/etcdctl/v3 v3.6.0-alpha.0/go.mod h1:0ugckElRKx3OrV15/WAylLv2Ji67
 go.etcd.io/etcd/etcdutl/v3 v3.5.4/go.mod h1:eK9eZfI/BxDQCztpuaJ1E/ufYpMw2Y16dPX1azGWrBU=
 go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0 h1:DZwDkrq/z5nHxXtovJMk9fyR6Nc+pwCJt25ptlFta24=
 go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0/go.mod h1:0ILo94EKC+jgp/IMfxePlfJD1OVtMVfgTQ/xM8+joOA=
+go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
 go.etcd.io/etcd/pkg/v3 v3.5.4/go.mod h1:OI+TtO+Aa3nhQSppMbwE4ld3uF1/fqqwbpfndbbrEe0=
 go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 h1:cV/VsaYde/tcc2G9aHN5DQwx6CtUsWSEW4UqYzXuyyk=
 go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0/go.mod h1:tXqWms0MpOJAS6L0B9nhFqZr0C/WEYzj/OtN90G8xzo=
+go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
 go.etcd.io/etcd/raft/v3 v3.5.4/go.mod h1:SCuunjYvZFC0fBX0vxMSPjuZmpcSk+XaAcMrD6Do03w=
 go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0 h1:BQ6CnNP4pIpy5rusFlTBxAacDgPXhuiHFwoTsBNsVpI=
 go.etcd.io/etcd/raft/v3 v3.6.0-alpha.0/go.mod h1:/kZdrBXlc5fUgYXfIEQ0B5sb7ejXPKbtF4jWzF1exiQ=
+go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
 go.etcd.io/etcd/server/v3 v3.5.4/go.mod h1:S5/YTU15KxymM5l3T6b09sNOHPXqGYIZStpuuGbb65c=
 go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 h1:BQUVqBqNFZZyrRbfydrRLzq9hYvCcRj97SsX1YwD7CA=
 go.etcd.io/etcd/server/v3 v3.6.0-alpha.0/go.mod h1:3QM2rLq3B3hSXmVEvgVt3vEEbG/AumSs0Is7EgrlKzU=
@@ -987,6 +1022,7 @@ go.opentelemetry.io/contrib v1.6.0/go.mod h1:FlyPNX9s4U6MCsWEc5YAK4KzKNHFDsjrDUZ
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0 h1:Ky1MObd188aGbgb5OgNnwGuEEwI9MVIcc7rBW6zk5Ak=
 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4=
 go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
 go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
 go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
@@ -1027,6 +1063,7 @@ go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
 go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
 go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
 go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
@@ -1048,6 +1085,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200930160638-afb6bcd081ae/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -1151,8 +1189,10 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
 golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -1242,7 +1282,9 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1273,6 +1315,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1293,6 +1336,7 @@ golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
 golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1312,6 +1356,7 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
@@ -1334,6 +1379,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1385,6 +1431,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
@@ -1394,6 +1441,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
+gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -1476,6 +1525,7 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
 google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -1516,6 +1566,7 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
+google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
 google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
@@ -1606,6 +1657,7 @@ gopkg.in/linkedin/goavro.v1 v1.0.5/go.mod h1:Aw5GdAbizjOEl0kAMHV9iHmA8reZzW/OKuJ
 gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
 gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
+gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
 gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
@@ -1629,6 +1681,8 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
 gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1637,21 +1691,38 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs=
+k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg=
 k8s.io/api v0.24.7 h1:UU9XB38BLUEzGoC45387FiblblIbRQkEUAG6nZoddqE=
 k8s.io/api v0.24.7/go.mod h1:tt+TFsvj8um6tsywVsTdwGdPvQ4IDCMLZXFH5C2BRlU=
 k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k=
+k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ=
+k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U=
+k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
 k8s.io/apimachinery v0.24.7 h1:CYJ+iRJkNFWWdUz5XodHkA6Yk5nRTbudvvQDVGxtuqc=
 k8s.io/apimachinery v0.24.7/go.mod h1:WR5z9Lpw2mOAeDg20iSSrEBRQMY0p2YXVdYpUIgSr4o=
+k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ=
+k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y=
+k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30=
 k8s.io/client-go v0.24.7 h1:K4rTkxc94ctXfaDXfa5IflsflPYmguG/3zb3iJY4dQA=
 k8s.io/client-go v0.24.7/go.mod h1:UoQaKAGHRRE77THP0jGUehwqt5javBlv1AoKdpfz3JA=
+k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
+k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI=
+k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU=
+k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM=
+k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
+k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
 k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
 k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU=
 k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
 k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 oras.land/oras-go/v2 v2.0.0-rc.3 h1:O4GeIwJ9Ge7rbCkqa/M7DLrL55ww+ZEc+Rhc63OYitU=
@@ -1659,11 +1730,13 @@ oras.land/oras-go/v2 v2.0.0-rc.3/go.mod h1:PrY+cCglzK/DrQoJUtxbYVbL94ZHecVS3eJR0
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 sigs.k8s.io/controller-runtime v0.12.2 h1:nqV02cvhbAj7tbt21bpPpTByrXGn2INHRsi39lXy9sE=
 sigs.k8s.io/controller-runtime v0.12.2/go.mod h1:qKsk4WE6zW2Hfj0G4v10EnNB2jMG1C+NTb8h+DwCoU0=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
 sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
 sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt
new file mode 100644
index 0000000..29c55ec
--- /dev/null
+++ b/hack/boilerplate.go.txt
@@ -0,0 +1,15 @@
+/*
+Copyright 2022.
+
+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.
+*/
\ No newline at end of file
diff --git a/httpserver/Dockerfile b/httpserver/Dockerfile
index 6d11978..06b7057 100644
--- a/httpserver/Dockerfile
+++ b/httpserver/Dockerfile
@@ -43,3 +43,4 @@ EXPOSE 6001
 USER 65532:65532
 
 ENTRYPOINT ["/app/ratify", "serve", "--http", ":6001"]
+
diff --git a/pkg/common/plugin/os_unix.go b/pkg/common/plugin/os_unix.go
index cd41d2e..bfa3e87 100644
--- a/pkg/common/plugin/os_unix.go
+++ b/pkg/common/plugin/os_unix.go
@@ -1,3 +1,4 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 /*
diff --git a/pkg/controllers/store_controller.go b/pkg/controllers/store_controller.go
new file mode 100644
index 0000000..1f14239
--- /dev/null
+++ b/pkg/controllers/store_controller.go
@@ -0,0 +1,131 @@
+/*
+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 controllers
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/runtime"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/log"
+
+	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	"github.com/deislabs/ratify/pkg/referrerstore"
+	"github.com/deislabs/ratify/pkg/referrerstore/config"
+	sf "github.com/deislabs/ratify/pkg/referrerstore/factory"
+	"github.com/deislabs/ratify/pkg/referrerstore/types"
+)
+
+// StoreReconciler reconciles a Store object
+type StoreReconciler struct {
+	client.Client
+	Scheme *runtime.Scheme
+}
+
+var (
+	// a map to track active stores
+	StoreMap    = map[string]referrerstore.ReferrerStore{}
+	storeLogger = log.Log
+)
+
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=stores,verbs=get;list;watch;create;update;patch;delete
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=stores/status,verbs=get;update;patch
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=stores/finalizers,verbs=update
+
+// Reconcile is part of the main kubernetes reconciliation loop which aims to
+// move the current state of the cluster closer to the desired state.
+//
+// For more details, check Reconcile and its Result here:
+// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.2/pkg/reconcile
+func (r *StoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+	storeLogger := log.FromContext(ctx)
+
+	var store configv1alpha1.Store
+	var resource = req.Name
+	storeLogger.Info(fmt.Sprintf("reconciling store '%v'", resource))
+
+	if err := r.Get(ctx, req.NamespacedName, &store); err != nil {
+
+		if apierrors.IsNotFound(err) {
+			storeLogger.Info(fmt.Sprintf("deletion detected, removing store %v", req.Name))
+			storeRemove(resource)
+		} else {
+			storeLogger.Error(err, "unable to fetch store")
+		}
+
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	if err := storeAddOrReplace(store.Spec, resource); err != nil {
+		storeLogger.Error(err, "unable to create store from store crd")
+		return ctrl.Result{}, err
+	}
+
+	// returning empty result and no error to indicate we’ve successfully reconciled this object
+	return ctrl.Result{}, nil
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *StoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&configv1alpha1.Store{}).
+		Complete(r)
+}
+
+// Creates a store reference from CRD spec and add store to map
+func storeAddOrReplace(spec configv1alpha1.StoreSpec, fullname string) error {
+	storeConfig, err := specToStoreConfig(spec)
+
+	// factory only support a single version of configuration today
+	// when we support multi version store CRD, we will also pass in the corresponding config version so factory can create different version of the object
+	storeConfigVersion := "1.0.0"
+	storeReference, err := sf.CreateStoreFromConfig(storeConfig, storeConfigVersion, []string{spec.Address})
+
+	if err != nil || storeReference == nil {
+		storeLogger.Error(err, "store factory failed to create store from store config")
+		return fmt.Errorf("store factory failed to create store from store config, err: %q", err)
+	}
+
+	StoreMap[fullname] = storeReference
+	storeLogger.Info(fmt.Sprintf("store '%v' added to store map", storeReference.Name()))
+
+	return nil
+}
+
+// Remove store from map
+func storeRemove(resourceName string) {
+	delete(StoreMap, resourceName)
+}
+
+// Returns a store reference from spec
+func specToStoreConfig(storeSpec configv1alpha1.StoreSpec) (config.StorePluginConfig, error) {
+
+	storeConfig := config.StorePluginConfig{}
+
+	if string(storeSpec.Parameters.Raw) != "" {
+		if err := json.Unmarshal(storeSpec.Parameters.Raw, &storeConfig); err != nil {
+			storeLogger.Error(err, "unable to decode store parameters", "Parameters.Raw", storeSpec.Parameters.Raw)
+			return config.StorePluginConfig{}, err
+		}
+	}
+	storeConfig[types.Name] = storeSpec.Name
+
+	return storeConfig, nil
+}
diff --git a/pkg/controllers/verifier_controller.go b/pkg/controllers/verifier_controller.go
new file mode 100644
index 0000000..c92eb5a
--- /dev/null
+++ b/pkg/controllers/verifier_controller.go
@@ -0,0 +1,142 @@
+/*
+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 controllers
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	vr "github.com/deislabs/ratify/pkg/verifier"
+	"github.com/deislabs/ratify/pkg/verifier/config"
+	vf "github.com/deislabs/ratify/pkg/verifier/factory"
+	"github.com/deislabs/ratify/pkg/verifier/types"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/runtime"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/log"
+)
+
+// VerifierReconciler reconciles a Verifier object
+type VerifierReconciler struct {
+	client.Client
+	Scheme *runtime.Scheme
+}
+
+var (
+	// a map to track of active verifiers
+	VerifierMap    = map[string]vr.ReferenceVerifier{}
+	verifierLogger = log.Log
+)
+
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=verifiers,verbs=get;list;watch;create;update;patch;delete
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=verifiers/status,verbs=get;update;patch
+//+kubebuilder:rbac:groups=config.ratify.deislabs.io,resources=verifiers/finalizers,verbs=update
+
+// Reconcile is part of the main kubernetes reconciliation loop which aims to
+// move the current state of the cluster closer to the desired state.
+// TODO(user): Modify the Reconcile function to compare the state specified by
+// the Verifier object against the actual cluster state, and then
+// perform operations to make the cluster state reflect the state specified by
+// the user.
+//
+// For more details, check Reconcile and its Result here:
+// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.2/pkg/reconcile
+func (r *VerifierReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+
+	verifierLogger = log.FromContext(ctx)
+
+	var verifier configv1alpha1.Verifier
+	var resource = req.Name
+	storeLogger.Info(fmt.Sprintf("reconciling verifier '%v'", resource))
+
+	if err := r.Get(ctx, req.NamespacedName, &verifier); err != nil {
+
+		if apierrors.IsNotFound(err) {
+			verifierLogger.Info(fmt.Sprintf("delete event detected, removing verifier %v", resource))
+			verifierRemove(resource)
+		} else {
+			verifierLogger.Error(err, "unable to fetch verifier")
+		}
+
+		return ctrl.Result{}, client.IgnoreNotFound(err)
+	}
+
+	if err := verifierAddOrReplace(verifier.Spec, resource); err != nil {
+		verifierLogger.Error(err, "unable to create verifier from verifier crd")
+		return ctrl.Result{}, err
+	}
+
+	// returning empty result and no error to indicate we’ve successfully reconciled this object
+	return ctrl.Result{}, nil
+}
+
+// creates a verifier reference from CRD spec and add store to map
+func verifierAddOrReplace(spec configv1alpha1.VerifierSpec, objectName string) error {
+
+	verifierConfig, err := specToVerifierConfig(spec)
+
+	if err != nil {
+		verifierLogger.Error(err, "unable to convert crd specification to verifier config")
+		return fmt.Errorf("unable to convert crd specification to verifier config, err: %q", err)
+	}
+
+	// verifier factory only support a single version of configuration today
+	// when we support multi version verifier CRD, we will also pass in the corresponding config version so factory can create different version of the object
+	verifierConfigVersion := "1.0.0"
+	verifierReference, err := vf.CreateVerifierFromConfig(verifierConfig, verifierConfigVersion, []string{spec.Address})
+
+	if err != nil || verifierReference == nil {
+		verifierLogger.Error(err, "unable to create verifier from verifier config")
+		return err
+	}
+	VerifierMap[objectName] = verifierReference
+	verifierLogger.Info(fmt.Sprintf("verifier '%v' added to verifier map", verifierReference.Name()))
+
+	return nil
+}
+
+// remove verifier from map
+func verifierRemove(objectName string) {
+	delete(VerifierMap, objectName)
+}
+
+// returns a verifier reference from spec
+func specToVerifierConfig(verifierSpec configv1alpha1.VerifierSpec) (config.VerifierConfig, error) {
+
+	verifierConfig := config.VerifierConfig{}
+
+	if string(verifierSpec.Parameters.Raw) != "" {
+		if err := json.Unmarshal(verifierSpec.Parameters.Raw, &verifierConfig); err != nil {
+			verifierLogger.Error(err, "unable to decode verifier parameters", "Parameters.Raw", verifierSpec.Parameters.Raw)
+			return config.VerifierConfig{}, err
+		}
+	}
+
+	verifierConfig[types.Name] = verifierSpec.Name
+	verifierConfig[types.ArtifactTypes] = verifierSpec.ArtifactTypes
+
+	return verifierConfig, nil
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *VerifierReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&configv1alpha1.Verifier{}).
+		Complete(r)
+}
diff --git a/pkg/homedir/homedir_unix.go b/pkg/homedir/homedir_unix.go
index fa630a0..835ccca 100644
--- a/pkg/homedir/homedir_unix.go
+++ b/pkg/homedir/homedir_unix.go
@@ -1,3 +1,4 @@
+//go:build !windows
 // +build !windows
 
 /*
diff --git a/pkg/manager/manager.go b/pkg/manager/manager.go
new file mode 100644
index 0000000..e6f0f89
--- /dev/null
+++ b/pkg/manager/manager.go
@@ -0,0 +1,201 @@
+/*
+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 manager
+
+import (
+	"context"
+	"flag"
+	"os"
+
+	_ "github.com/deislabs/ratify/pkg/policyprovider/configpolicy"
+	_ "github.com/deislabs/ratify/pkg/referrerstore/oras"
+	_ "github.com/deislabs/ratify/pkg/verifier/notaryv2"
+	_ "k8s.io/client-go/plugin/pkg/client/auth"
+
+	// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
+	// to ensure that exec-entrypoint and run can make use of them.
+	"github.com/deislabs/ratify/config"
+	"github.com/deislabs/ratify/httpserver"
+	_ "github.com/deislabs/ratify/pkg/policyprovider/configpolicy"
+	_ "github.com/deislabs/ratify/pkg/referrerstore/oras"
+	_ "github.com/deislabs/ratify/pkg/verifier/notaryv2"
+	"github.com/sirupsen/logrus"
+	_ "k8s.io/client-go/plugin/pkg/client/auth"
+
+	"github.com/deislabs/ratify/pkg/verifier"
+
+	"k8s.io/apimachinery/pkg/runtime"
+	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
+	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/healthz"
+	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+
+	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	"github.com/deislabs/ratify/pkg/controllers"
+	ef "github.com/deislabs/ratify/pkg/executor/core"
+	"github.com/deislabs/ratify/pkg/policyprovider"
+	"github.com/deislabs/ratify/pkg/referrerstore"
+	vr "github.com/deislabs/ratify/pkg/verifier"
+	//+kubebuilder:scaffold:imports
+)
+
+var (
+	scheme   = runtime.NewScheme()
+	setupLog = ctrl.Log.WithName("setup")
+
+	configStores    []referrerstore.ReferrerStore
+	configVerifiers []verifier.ReferenceVerifier
+	policy          policyprovider.PolicyProvider
+)
+
+func init() {
+	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
+	utilruntime.Must(configv1alpha1.AddToScheme(scheme))
+	//+kubebuilder:scaffold:scheme
+}
+
+func StartServer(httpServerAddress string, certDirectory string, caCertFile string) {
+
+	logrus.Infof("initializing executor with config file at default config path")
+
+	configFilePath := ""
+	cf, err := config.Load(configFilePath)
+
+	configStores, configVerifiers, policy, err := config.CreateFromConfig(cf)
+
+	if err != nil {
+		logrus.Warnf("error initializing from config %v", err)
+		os.Exit(1)
+	}
+
+	// initialize server
+	server, err := httpserver.NewServer(context.Background(), httpServerAddress, func() *ef.Executor {
+
+		var activeVerifiers []vr.ReferenceVerifier
+		var activeStores []referrerstore.ReferrerStore
+
+		// check if there are active verifiers from crd controller
+		// else use verifiers from configuration
+		if len(controllers.VerifierMap) > 0 {
+			for _, value := range controllers.VerifierMap {
+				activeVerifiers = append(activeVerifiers, value)
+			}
+		} else {
+			activeVerifiers = configVerifiers
+		}
+
+		// check if there are active stores from crd controller
+		// else use stores from configuration
+		if len(controllers.StoreMap) > 0 {
+			for _, value := range controllers.StoreMap {
+				activeStores = append(activeStores, value)
+			}
+		} else {
+			activeStores = configStores
+		}
+
+		// return executor with latest configuration
+		executor := ef.Executor{
+			Verifiers:      activeVerifiers,
+			ReferrerStores: activeStores,
+			PolicyEnforcer: policy,
+			Config:         &cf.ExecutorConfig,
+		}
+		return &executor
+	}, certDirectory, caCertFile)
+
+	if err != nil {
+		os.Exit(1)
+	}
+	logrus.Infof("starting server at" + httpServerAddress)
+	if err := server.Run(); err != nil {
+		os.Exit(1)
+	}
+}
+
+func StartManager() {
+	var metricsAddr string
+	var enableLeaderElection bool
+	var probeAddr string
+	flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
+	flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
+	flag.BoolVar(&enableLeaderElection, "leader-elect", false,
+		"Enable leader election for controller manager. "+
+			"Enabling this will ensure there is only one active controller manager.")
+	opts := zap.Options{
+		Development: true,
+	}
+	opts.BindFlags(flag.CommandLine)
+	flag.Parse()
+
+	ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
+
+	mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
+		Scheme:                 scheme,
+		MetricsBindAddress:     metricsAddr,
+		Port:                   9443,
+		HealthProbeBindAddress: probeAddr,
+		LeaderElection:         enableLeaderElection,
+		LeaderElectionID:       "1a306109.github.com/deislabs/ratify",
+		// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
+		// when the Manager ends. This requires the binary to immediately end when the
+		// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
+		// speeds up voluntary leader transitions as the new leader don't have to wait
+		// LeaseDuration time first.
+		//
+		// In the default scaffold provided, the program ends immediately after
+		// the manager stops, so would be fine to enable this option. However,
+		// if you are doing or is intended to do any operation such as perform cleanups
+		// after the manager stops then its usage might be unsafe.
+		// LeaderElectionReleaseOnCancel: true,
+	})
+	if err != nil {
+		setupLog.Error(err, "unable to start manager")
+		os.Exit(1)
+	}
+
+	if err = (&controllers.VerifierReconciler{
+		Client: mgr.GetClient(),
+		Scheme: mgr.GetScheme(),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "Verifier")
+		os.Exit(1)
+	}
+	if err = (&controllers.StoreReconciler{
+		Client: mgr.GetClient(),
+		Scheme: mgr.GetScheme(),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "Store")
+		os.Exit(1)
+	}
+	//+kubebuilder:scaffold:builder
+
+	if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
+		setupLog.Error(err, "unable to set up health check")
+		os.Exit(1)
+	}
+	if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
+		setupLog.Error(err, "unable to set up ready check")
+		os.Exit(1)
+	}
+
+	setupLog.Info("starting manager")
+	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
+		setupLog.Error(err, "problem running manager")
+		os.Exit(1)
+	}
+}
diff --git a/pkg/referrerstore/factory/factory.go b/pkg/referrerstore/factory/factory.go
index 3a5c4bc..9cbe0da 100644
--- a/pkg/referrerstore/factory/factory.go
+++ b/pkg/referrerstore/factory/factory.go
@@ -46,6 +46,25 @@ func Register(name string, factory StoreFactory) {
 	builtInStores[name] = factory
 }
 
+func CreateStoreFromConfig(storeConfig config.StorePluginConfig, configVersion string, pluginBinDir []string) (referrerstore.ReferrerStore, error) {
+	storeName, ok := storeConfig[types.Name]
+	if !ok {
+		return nil, fmt.Errorf("failed to find store name in the stores config with key %s", "name")
+	}
+
+	storeNameStr := fmt.Sprintf("%s", storeName)
+	if strings.ContainsRune(storeNameStr, os.PathSeparator) {
+		return nil, fmt.Errorf("invalid plugin name for a store: %s", storeName)
+	}
+
+	storeFactory, ok := builtInStores[storeNameStr]
+	if ok {
+		return storeFactory.Create(configVersion, storeConfig)
+	} else {
+		return plugin.NewStore(configVersion, storeConfig, pluginBinDir)
+	}
+}
+
 // CreateStoresFromConfig creates a stores from the provided configuration
 func CreateStoresFromConfig(storesConfig config.StoresConfig, defaultPluginPath string) ([]referrerstore.ReferrerStore, error) {
 	if storesConfig.Version == "" {
@@ -65,34 +84,15 @@ func CreateStoresFromConfig(storesConfig config.StoresConfig, defaultPluginPath
 
 	if len(storesConfig.PluginBinDirs) == 0 {
 		storesConfig.PluginBinDirs = []string{defaultPluginPath}
+	} else {
+		storesConfig.PluginBinDirs = append(storesConfig.PluginBinDirs, defaultPluginPath)
 	}
-	for _, storeConfig := range storesConfig.Stores {
-		storeName, ok := storeConfig[types.Name]
-		if !ok {
-			return nil, fmt.Errorf("failed to find store name in the stores config with key %s", "name")
-		}
 
-		storeNameStr := fmt.Sprintf("%s", storeName)
-		if strings.ContainsRune(storeNameStr, os.PathSeparator) {
-			return nil, fmt.Errorf("invalid plugin name for a store: %s", storeName)
-		}
-
-		storeFactory, ok := builtInStores[storeNameStr]
-		if ok {
-			store, err := storeFactory.Create(storesConfig.Version, storeConfig)
-
-			if err != nil {
-				return nil, err
-			}
-
-			stores = append(stores, store)
+	for _, storeConfig := range storesConfig.Stores {
+		store, err := CreateStoreFromConfig(storeConfig, storesConfig.Version, storesConfig.PluginBinDirs)
+		if err != nil {
+			return nil, err
 		} else {
-			store, err := plugin.NewStore(storesConfig.Version, storeConfig, append(storesConfig.PluginBinDirs, defaultPluginPath))
-
-			if err != nil {
-				return nil, err
-			}
-
 			stores = append(stores, store)
 		}
 	}
diff --git a/pkg/verifier/factory/factory.go b/pkg/verifier/factory/factory.go
index 17d7d1a..a4d395c 100644
--- a/pkg/verifier/factory/factory.go
+++ b/pkg/verifier/factory/factory.go
@@ -45,7 +45,29 @@ func Register(name string, factory VerifierFactory) {
 	builtInVerifiers[name] = factory
 }
 
+// returns a single verifier from a verifierConfig
+func CreateVerifierFromConfig(verifierConfig config.VerifierConfig, configVersion string, pluginBinDir []string) (verifier.ReferenceVerifier, error) {
+
+	verifierName, ok := verifierConfig[types.Name]
+	if !ok {
+		return nil, fmt.Errorf("failed to find verifier name in the verifier config with key %s", "name")
+	}
+
+	verifierNameStr := fmt.Sprintf("%s", verifierName)
+	if strings.ContainsRune(verifierNameStr, os.PathSeparator) {
+		return nil, fmt.Errorf("invalid plugin name for a verifier: %s", verifierNameStr)
+	}
+
+	verifierFactory, ok := builtInVerifiers[verifierNameStr]
+	if ok {
+		return verifierFactory.Create(configVersion, verifierConfig)
+	} else {
+		return plugin.NewVerifier(configVersion, verifierConfig, pluginBinDir)
+	}
+}
+
 // TODO pointer to avoid copy
+// returns an array of verifiers from VerifiersConfig
 func CreateVerifiersFromConfig(verifiersConfig config.VerifiersConfig, defaultPluginPath string) ([]verifier.ReferenceVerifier, error) {
 	if verifiersConfig.Version == "" {
 		verifiersConfig.Version = types.SpecVersion
@@ -57,7 +79,7 @@ func CreateVerifiersFromConfig(verifiersConfig config.VerifiersConfig, defaultPl
 	}
 
 	if len(verifiersConfig.Verifiers) == 0 {
-		return nil, errors.New("verifiers config should have atleast one verifer")
+		return nil, errors.New("verifiers config should have at least one verifier")
 	}
 
 	var verifiers []verifier.ReferenceVerifier
@@ -65,36 +87,15 @@ func CreateVerifiersFromConfig(verifiersConfig config.VerifiersConfig, defaultPl
 	if len(verifiersConfig.PluginBinDirs) == 0 {
 		verifiersConfig.PluginBinDirs = []string{defaultPluginPath}
 	}
-	for _, verifierConfig := range verifiersConfig.Verifiers {
-		verifierName, ok := verifierConfig[types.Name]
-		if !ok {
-			return nil, fmt.Errorf("failed to find verifier name in the verifier config with key %s", "name")
-		}
 
-		verifierNameStr := fmt.Sprintf("%s", verifierName)
-		if strings.ContainsRune(verifierNameStr, os.PathSeparator) {
-			return nil, fmt.Errorf("invalid plugin name for a verifier: %s", verifierNameStr)
-		}
-
-		verifierFactory, ok := builtInVerifiers[verifierNameStr]
-		if ok {
-			verifier, err := verifierFactory.Create(verifiersConfig.Version, verifierConfig)
-
-			if err != nil {
-				return nil, err
-			}
-
-			verifiers = append(verifiers, verifier)
+	// TODO: do we need to append defaultPlugin path?
+	for _, verifierConfig := range verifiersConfig.Verifiers {
+		verifier, err := CreateVerifierFromConfig(verifierConfig, verifiersConfig.Version, verifiersConfig.PluginBinDirs)
+		if err != nil {
+			return nil, err
 		} else {
-			verifier, err := plugin.NewVerifier(verifiersConfig.Version, verifierConfig, verifiersConfig.PluginBinDirs)
-
-			if err != nil {
-				return nil, err
-			}
-
 			verifiers = append(verifiers, verifier)
 		}
-
 	}
 
 	return verifiers, nil


Test patch:
diff --git a/pkg/controllers/store_controller_test.go b/pkg/controllers/store_controller_test.go
new file mode 100644
index 0000000..960fa45
--- /dev/null
+++ b/pkg/controllers/store_controller_test.go
@@ -0,0 +1,99 @@
+/*
+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 controllers
+
+import (
+	"testing"
+
+	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	"github.com/deislabs/ratify/pkg/referrerstore"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+func TestStoreAdd_EmptyParameter(t *testing.T) {
+	resetStoreMap()
+	var testStoreSpec = configv1alpha1.StoreSpec{
+		Name: "oras",
+	}
+
+	storeAddOrReplace(testStoreSpec, "oras")
+	if len(StoreMap) != 1 {
+		t.Fatalf("Store map expected size 1, actual %v", len(StoreMap))
+	}
+}
+
+func TestStoreAdd_WithParameters(t *testing.T) {
+	resetStoreMap()
+	if len(StoreMap) != 0 {
+		t.Fatalf("Store map expected size 0, actual %v", len(StoreMap))
+	}
+
+	var testStoreSpec = getOrasStoreSpec()
+
+	storeAddOrReplace(testStoreSpec, "testObject")
+	if len(StoreMap) != 1 {
+		t.Fatalf("Store map expected size 1, actual %v", len(StoreMap))
+	}
+}
+
+func TestStore_UpdateAndDelete(t *testing.T) {
+	resetStoreMap()
+	// add a Store
+
+	var resource = "oras"
+
+	var testStoreSpec = getOrasStoreSpec()
+
+	storeAddOrReplace(testStoreSpec, resource)
+
+	if len(StoreMap) != 1 {
+		t.Fatalf("Store map expected size 1, actual %v", len(StoreMap))
+	}
+
+	// modify the Store
+	var updatedSpec = configv1alpha1.StoreSpec{
+		Name: "oras",
+	}
+
+	storeAddOrReplace(updatedSpec, resource)
+
+	// validate no Store has been added
+	if len(StoreMap) != 1 {
+		t.Fatalf("Store map should be 1 after replacement, actual %v", len(StoreMap))
+	}
+
+	storeRemove(resource)
+
+	if len(StoreMap) != 0 {
+		t.Fatalf("Store map should be 0 after deletion, actual %v", len(StoreMap))
+	}
+}
+
+func resetStoreMap() {
+	StoreMap = map[string]referrerstore.ReferrerStore{}
+}
+
+func getOrasStoreSpec() configv1alpha1.StoreSpec {
+	var parametersString = "{\"authProvider\":{\"name\":\"k8Secrets\",\"secrets\":[{\"secretName\":\"myregistrykey\"}]},\"cosign-enabled\":false,\"useHttp\":false}"
+	var storeParameters = []byte(parametersString)
+
+	return configv1alpha1.StoreSpec{
+		Name: "oras",
+		Parameters: runtime.RawExtension{
+			Raw: storeParameters,
+		},
+	}
+}
diff --git a/pkg/controllers/verifier_controller_test.go b/pkg/controllers/verifier_controller_test.go
new file mode 100644
index 0000000..c4ac3ac
--- /dev/null
+++ b/pkg/controllers/verifier_controller_test.go
@@ -0,0 +1,110 @@
+/*
+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 controllers
+
+import (
+	"os"
+	"testing"
+
+	configv1alpha1 "github.com/deislabs/ratify/api/v1alpha1"
+	vr "github.com/deislabs/ratify/pkg/verifier"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+func TestMain(m *testing.M) {
+	// make sure to reset verifierMap before each test run
+	VerifierMap = map[string]vr.ReferenceVerifier{}
+	code := m.Run()
+	os.Exit(code)
+}
+
+func TestVerifierAdd_EmptyParameter(t *testing.T) {
+	resetVerifierMap()
+	var testVerifierSpec = configv1alpha1.VerifierSpec{
+		Name:          "notaryv2",
+		ArtifactTypes: "application/vnd.cncf.notary.v2.signature",
+	}
+	var resource = "notaryv2"
+
+	verifierAddOrReplace(testVerifierSpec, resource)
+	if len(VerifierMap) != 1 {
+		t.Fatalf("Verifier map expected size 1, actual %v", len(VerifierMap))
+	}
+}
+
+func TestVerifierAdd_WithParameters(t *testing.T) {
+	resetVerifierMap()
+	if len(VerifierMap) != 0 {
+		t.Fatalf("Verifier map expected size 0, actual %v", len(VerifierMap))
+	}
+
+	var testVerifierSpec = getDefaultLicenseCheckerSpec()
+
+	verifierAddOrReplace(testVerifierSpec, "testObject")
+	if len(VerifierMap) != 1 {
+		t.Fatalf("Verifier map expected size 1, actual %v", len(VerifierMap))
+	}
+}
+
+func TestVerifier_UpdateAndDelete(t *testing.T) {
+	resetVerifierMap()
+
+	var resource = "licensechecker"
+	var testVerifierSpec = getDefaultLicenseCheckerSpec()
+
+	// add a verifier
+	verifierAddOrReplace(testVerifierSpec, resource)
+	if len(VerifierMap) != 1 {
+		t.Fatalf("Verifier map expected size 1, actual %v", len(VerifierMap))
+	}
+
+	// modify the verifier
+	var parametersString = "{\"allowedLicenses\":[\"MIT\",\"GNU\"]}"
+	testVerifierSpec = getLicenseCheckerFromParam(parametersString)
+	verifierAddOrReplace(testVerifierSpec, resource)
+
+	// validate no verifier has been added
+	if len(VerifierMap) != 1 {
+		t.Fatalf("Verifier map should be 1 after replacement, actual %v", len(VerifierMap))
+	}
+
+	verifierRemove(resource)
+
+	if len(VerifierMap) != 0 {
+		t.Fatalf("Verifier map should be 0 after deletion, actual %v", len(VerifierMap))
+	}
+}
+
+func resetVerifierMap() {
+	VerifierMap = map[string]vr.ReferenceVerifier{}
+}
+
+func getLicenseCheckerFromParam(parametersString string) configv1alpha1.VerifierSpec {
+	var allowedLicenses = []byte(parametersString)
+
+	return configv1alpha1.VerifierSpec{
+		Name:          "licensechecker",
+		ArtifactTypes: "application/vnd.ratify.spdx.v0",
+		Parameters: runtime.RawExtension{
+			Raw: allowedLicenses,
+		},
+	}
+}
+
+func getDefaultLicenseCheckerSpec() configv1alpha1.VerifierSpec {
+	var parametersString = "{\"allowedLicenses\":[\"MIT\",\"Apache\"]}"
+	return getLicenseCheckerFromParam(parametersString)
+}
diff --git a/test/bats/test.bats b/test/bats/test.bats
index f511642..af36d7c 100644
--- a/test/bats/test.bats
+++ b/test/bats/test.bats
@@ -13,13 +13,35 @@ SLEEP_TIME=1
     run kubectl apply -f ./library/default/samples/constraint.yaml
     assert_success
     sleep 5
-    run kubectl run demo --image=wabbitnetworks.azurecr.io/test/net-monitor:signed
+    run kubectl run demo --namespace default --image=wabbitnetworks.azurecr.io/test/net-monitor:signed
     assert_success
-    run kubectl run demo1 --image=wabbitnetworks.azurecr.io/test/net-monitor:unsigned
+    run kubectl run demo1 --namespace default --image=wabbitnetworks.azurecr.io/test/net-monitor:unsigned
     assert_failure
+
+    echo "cleaning up"
+    wait_for_process ${WAIT_TIME} ${SLEEP_TIME} kubectl delete pod demo
+}
+
+@test "validate crd add, replace and delete" {     
+    echo "adding license checker, delete notary verifier and validate deployment fails due to missing notary verifier"
+    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_licensechecker.yaml
+    run kubectl delete verifiers.config.ratify.deislabs.io/verifier-notary
+    run kubectl run crdtest --namespace default --image=wabbitnetworks.azurecr.io/test/net-monitor:signed
+    assert_failure
+
+    echo "Add notary verifier and validate deployment succeeds"
+    run kubectl apply -f ./config/samples/config_v1alpha1_verifier_notary.yaml
+    assert_success
+    
+    run kubectl run crdtest --namespace default --image=wabbitnetworks.azurecr.io/test/net-monitor:signed
+    assert_success
+
+    echo "cleaning up"
+    wait_for_process ${WAIT_TIME} ${SLEEP_TIME} kubectl delete pod crdtest
 }
 
 @test "configmap update test" {
+    skip "Skipping test for now as we are no longer watching for configfile update in a k8 environment.This test ensures we are watching config file updates in a non-kub scenario"
     run kubectl apply -f ./library/default/template.yaml
     assert_success
     sleep 5
@@ -43,4 +65,4 @@ SLEEP_TIME=1
     assert_failure
      
     wait_for_process ${WAIT_TIME} ${SLEEP_TIME} "kubectl replace --namespace=ratify-service -f currentConfig.yaml"
-}
+}
\ No newline at end of file