Repository: kyverno/kyverno
Pull request #1804 (2021-04-15 19:07:27)

Bug fix/1783 generate endlessly
## Related issue

closes https://github.com/kyverno/kyverno/issues/1783

## What type of PR is this

> /kind bug

## Proposed Changes
The issue is because of comparing a pattern with variables with an object where the variables are replaced by values.
To resolved the variables in the pattern is replaced by values using source resource. 
## Checklist

- [X] I have read the [contributing guidelines](https://github.com/kyverno/kyverno/blob/main/CONTRIBUTING.md).
- [] I have added tests that prove my fix is effective or that my feature works.
- [] My PR contains new or altered behavior to Kyverno and
  - [] I have added or changed [the documentation](https://github.com/kyverno/website) myself in an existing PR and the link is:
  <!-- Uncomment to link to the PR -->
  <!-- https://github.com/kyverno/website/pull/123 -->
  - [] I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update and the link is:
  <!-- Uncomment to link to the issue -->
  <!-- https://github.com/kyverno/website/issues/1 -->
  - [] I have read the [PR documentation guide](pr_documentation.md) and followed the process including adding proof manifests to this PR.



Patch:
diff --git a/charts/kyverno/Chart.yaml b/charts/kyverno/Chart.yaml
index bb4543cb1..5cc326d9a 100644
--- a/charts/kyverno/Chart.yaml
+++ b/charts/kyverno/Chart.yaml
@@ -1,7 +1,7 @@
 apiVersion: v1
 name: kyverno
-version: v1.3.5-rc4
-appVersion: v1.3.5-rc4
+version: v1.3.5
+appVersion: v1.3.5
 icon: https://github.com/kyverno/kyverno/raw/main/img/logo.png
 description: Kubernetes Native Policy Management
 keywords:
diff --git a/charts/kyverno/README.md b/charts/kyverno/README.md
index 4d73304eb..e1e3a3990 100644
--- a/charts/kyverno/README.md
+++ b/charts/kyverno/README.md
@@ -103,6 +103,7 @@ The following table lists the configurable parameters of the kyverno chart and t
 | `tolerations`                      | list of node taints to tolerate                                                                                                                                                                                                                              | `[]`                                                                                                                                                                              |
 | `securityContext`                  | security context configuration                                                                                                                                                                                                                               | `{}`                                                                                                                                                                              |
 | `podSecurityStandard`              | set desired pod security level `privileged`, `default`, `restricted`, `custom`. Set to `restricted` for maximum security for your cluster. See: https://kyverno.io/policies/pod-security/                                                                    | `default`                                                                                                                                                                         |
+| `podSecuritySeverity`              | set desired pod security severity `low`, `medium`, `high`. Used severity level in PolicyReportResults for the selected pod security policies.                                                                    | `medium`                                                                                                                                                                         |
 | `podSecurityPolicies`              | Policies to include when `podSecurityStandard` is set to `custom`                                                                                                                                                                                            | `[]`                                                                                                                                                                              |
 | `validationFailureAction`          | set to get response in failed validation check. Supported values- `audit`, `enforce`. See: https://kyverno.io/docs/writing-policies/validate/                                                                                                                | `audit`                                                                                                                                                                           |
 
diff --git a/charts/kyverno/templates/clusterrole.yaml b/charts/kyverno/templates/clusterrole.yaml
index ae9b6eea6..3cec33ff0 100644
--- a/charts/kyverno/templates/clusterrole.yaml
+++ b/charts/kyverno/templates/clusterrole.yaml
@@ -194,4 +194,4 @@ rules:
   - reportchangerequests
   - clusterreportchangerequests
   verbs:
-  - "*"
\ No newline at end of file
+  - "*"
diff --git a/charts/kyverno/templates/policies/default/disallow-adding-capabilities.yaml b/charts/kyverno/templates/policies/default/disallow-adding-capabilities.yaml
index 802f1adf9..680a28f9c 100644
--- a/charts/kyverno/templates/policies/default/disallow-adding-capabilities.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-adding-capabilities.yaml
@@ -1,4 +1,4 @@
-{{ $name := "disallow-add-capabilities" -}}
+{{- $name := "disallow-add-capabilities" }}
 {{- if eq (include "kyverno.podSecurityDefault" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Capabilities permit privileged actions without giving full root access.
       Adding capabilities beyond the default set must not be allowed.
@@ -33,4 +36,4 @@ spec:
           - =(securityContext):
               =(capabilities):
                 X(add): null
-{{- end -}}
\ No newline at end of file
+{{- end -}}
diff --git a/charts/kyverno/templates/policies/default/disallow-host-namespaces.yaml b/charts/kyverno/templates/policies/default/disallow-host-namespaces.yaml
index b99076ffe..59301ddf8 100644
--- a/charts/kyverno/templates/policies/default/disallow-host-namespaces.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-host-namespaces.yaml
@@ -1,4 +1,4 @@
-{{ $name := "disallow-host-namespaces" -}}
+{{- $name := "disallow-host-namespaces" }}
 {{- if eq (include "kyverno.podSecurityDefault" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >- 
       Host namespaces (Process ID namespace, Inter-Process Communication namespace, and
       network namespace) allow access to shared information and can be used to elevate
diff --git a/charts/kyverno/templates/policies/default/disallow-host-path.yaml b/charts/kyverno/templates/policies/default/disallow-host-path.yaml
index f0ae2f13a..ed1418f5b 100644
--- a/charts/kyverno/templates/policies/default/disallow-host-path.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-host-path.yaml
@@ -1,4 +1,4 @@
-{{ $name := "disallow-host-path" -}}
+{{- $name := "disallow-host-path" }}
 {{- if eq (include "kyverno.podSecurityDefault" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       HostPath volumes let pods use host directories and volumes in containers.
       Using host resources can be used to access shared data or escalate privileges
diff --git a/charts/kyverno/templates/policies/default/disallow-host-ports.yaml b/charts/kyverno/templates/policies/default/disallow-host-ports.yaml
index ac71ce3cc..c167ba569 100644
--- a/charts/kyverno/templates/policies/default/disallow-host-ports.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-host-ports.yaml
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Access to host ports allows potential snooping of network traffic and should not be
       allowed, or at minimum restricted to a known list.
diff --git a/charts/kyverno/templates/policies/default/disallow-privileged-containers.yaml b/charts/kyverno/templates/policies/default/disallow-privileged-containers.yaml
index 80e7c7eb3..1dfcc8cdc 100644
--- a/charts/kyverno/templates/policies/default/disallow-privileged-containers.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-privileged-containers.yaml
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Privileged mode disables most security mechanisms and must not be allowed.
 spec:
diff --git a/charts/kyverno/templates/policies/default/disallow-proc-mount.yaml b/charts/kyverno/templates/policies/default/disallow-proc-mount.yaml
index 0a0589ea3..9ab8447bf 100644
--- a/charts/kyverno/templates/policies/default/disallow-proc-mount.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-proc-mount.yaml
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       The default /proc masks are set up to reduce attack surface and should be required.
 spec:
diff --git a/charts/kyverno/templates/policies/default/disallow-selinux.yaml b/charts/kyverno/templates/policies/default/disallow-selinux.yaml
index ab9eab833..3ab24dde8 100644
--- a/charts/kyverno/templates/policies/default/disallow-selinux.yaml
+++ b/charts/kyverno/templates/policies/default/disallow-selinux.yaml
@@ -7,6 +7,9 @@ metadata:
   annotations:
     policies.kyverno.io/title: Disallow SELinux
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       SELinux options can be used to escalate privileges and should not be allowed.
 spec:
diff --git a/charts/kyverno/templates/policies/default/restrict-apparmor-profiles.yaml b/charts/kyverno/templates/policies/default/restrict-apparmor-profiles.yaml
index 792adc36e..9449c3e1f 100644
--- a/charts/kyverno/templates/policies/default/restrict-apparmor-profiles.yaml
+++ b/charts/kyverno/templates/policies/default/restrict-apparmor-profiles.yaml
@@ -1,4 +1,4 @@
-{{ $name := "restrict-apparmor-profiles" -}}
+{{- $name := "restrict-apparmor-profiles" }}
 {{- if eq (include "kyverno.podSecurityDefault" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -7,6 +7,9 @@ metadata:
   annotations:
     policies.kyverno.io/title: Restrict AppArmor
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       On supported hosts, the 'runtime/default' AppArmor profile is applied by default. 
       The default policy should prevent overriding or disabling the policy, or restrict 
diff --git a/charts/kyverno/templates/policies/default/restrict-sysctls.yaml b/charts/kyverno/templates/policies/default/restrict-sysctls.yaml
index ab3d2d7e9..e9aae2761 100644
--- a/charts/kyverno/templates/policies/default/restrict-sysctls.yaml
+++ b/charts/kyverno/templates/policies/default/restrict-sysctls.yaml
@@ -1,4 +1,4 @@
-{{ $name := "restrict-sysctls" -}}
+{{- $name := "restrict-sysctls" }}
 {{- if eq (include "kyverno.podSecurityDefault" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Default)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Sysctls can disable security mechanisms or affect all containers on a
       host, and should be disallowed except for an allowed "safe" subset. A
diff --git a/charts/kyverno/templates/policies/restricted/deny-privilege-escalation.yaml b/charts/kyverno/templates/policies/restricted/deny-privilege-escalation.yaml
index 9177b2f1a..b2850b3f7 100644
--- a/charts/kyverno/templates/policies/restricted/deny-privilege-escalation.yaml
+++ b/charts/kyverno/templates/policies/restricted/deny-privilege-escalation.yaml
@@ -1,4 +1,4 @@
-{{ $name := "deny-privilege-escalation" -}}
+{{- $name := "deny-privilege-escalation" }}
 {{- if eq (include "kyverno.podSecurityRestricted" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Restricted)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Privilege escalation, such as via set-user-ID or set-group-ID file mode, should not be allowed.
 spec:
diff --git a/charts/kyverno/templates/policies/restricted/require-non-root-groups.yaml b/charts/kyverno/templates/policies/restricted/require-non-root-groups.yaml
index 2fd0cc121..4b950c3a4 100644
--- a/charts/kyverno/templates/policies/restricted/require-non-root-groups.yaml
+++ b/charts/kyverno/templates/policies/restricted/require-non-root-groups.yaml
@@ -1,4 +1,4 @@
-{{ $name := "require-non-root-groups" -}}
+{{- $name := "require-non-root-groups" }}
 {{- if eq (include "kyverno.podSecurityRestricted" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Restricted)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       Containers should be forbidden from running with a root primary or supplementary GID.
 spec:
@@ -53,10 +56,10 @@ spec:
             - Pod
       validate:
         message: >-
-          Changing of file system groups is not allowed. The field	
-          spec.securityContext.fsGroup must not be defined.
+          Changing to root group ID is disallowed. The field
+          spec.securityContext.fsGroup must be empty or greater than zero.
         pattern:
           spec:
             =(securityContext):
-              X(fsGroup): "*"
+              =(fsGroup): ">0"
 {{- end -}}
\ No newline at end of file
diff --git a/charts/kyverno/templates/policies/restricted/require-run-as-nonroot.yaml b/charts/kyverno/templates/policies/restricted/require-run-as-nonroot.yaml
index 0d6eaba15..70e7dcb83 100644
--- a/charts/kyverno/templates/policies/restricted/require-run-as-nonroot.yaml
+++ b/charts/kyverno/templates/policies/restricted/require-run-as-nonroot.yaml
@@ -1,4 +1,4 @@
-{{ $name := "require-run-as-non-root" -}}
+{{- $name := "require-run-as-non-root" }}
 {{- if eq (include "kyverno.podSecurityRestricted" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Restricted)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: Containers must be required to run as non-root users.
 spec:
   background: true
diff --git a/charts/kyverno/templates/policies/restricted/restrict-seccomp.yaml b/charts/kyverno/templates/policies/restricted/restrict-seccomp.yaml
index 5b96246ab..1bc7ae63a 100644
--- a/charts/kyverno/templates/policies/restricted/restrict-seccomp.yaml
+++ b/charts/kyverno/templates/policies/restricted/restrict-seccomp.yaml
@@ -1,4 +1,4 @@
-{{ $name := "restrict-seccomp" -}}
+{{- $name := "restrict-seccomp" }}
 {{- if eq (include "kyverno.podSecurityRestricted" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -7,6 +7,9 @@ metadata:
   annotations:
     policies.kyverno.io/title: Restrict Seccomp
     policies.kyverno.io/category: Pod Security Standards (Restricted)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       The runtime default seccomp profile must be required, or only specific
       additional profiles should be allowed.
diff --git a/charts/kyverno/templates/policies/restricted/restrict-volume-types.yaml b/charts/kyverno/templates/policies/restricted/restrict-volume-types.yaml
index 8ef906a5b..bdd6b3529 100644
--- a/charts/kyverno/templates/policies/restricted/restrict-volume-types.yaml
+++ b/charts/kyverno/templates/policies/restricted/restrict-volume-types.yaml
@@ -1,4 +1,4 @@
-{{ $name := "restrict-volume-types" -}}
+{{- $name := "restrict-volume-types" }}
 {{- if eq (include "kyverno.podSecurityRestricted" (merge (dict "name" $name) .)) "true" }}
 apiVersion: kyverno.io/v1
 kind: ClusterPolicy
@@ -6,6 +6,9 @@ metadata:
   name: {{ $name }}
   annotations:
     policies.kyverno.io/category: Pod Security Standards (Restricted)
+    {{- if .Values.podSecuritySeverity }}
+    policies.kyverno.io/severity: {{ .Values.podSecuritySeverity | quote }}
+    {{- end }}
     policies.kyverno.io/description: >-
       In addition to restricting HostPath volumes, the restricted pod security profile
       limits usage of non-core volume types to those defined through PersistentVolumes.
diff --git a/charts/kyverno/values.yaml b/charts/kyverno/values.yaml
index fbeef11bc..6add45e1a 100644
--- a/charts/kyverno/values.yaml
+++ b/charts/kyverno/values.yaml
@@ -4,6 +4,8 @@ namespace:
 # Supported- default/restricted/privileged/custom
 # For more info- https://kyverno.io/policies/pod-security
 podSecurityStandard: default
+# Supported- low/medium/high
+podSecuritySeverity: medium
 # Policies to include when podSecurityStandard is custom
 podSecurityPolicies: []
 # Supported values- `audit`, `enforce`
diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index 80044f500..c54a1480b 100755
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -138,13 +138,14 @@ func main() {
 	if err != nil {
 		setupLog.Error(err, "ConfigMap lookup disabled: failed to create resource cache")
 	}
-
+	debug := serverIP != ""
 	webhookCfg := webhookconfig.NewRegister(
 		clientConfig,
 		client,
 		rCache,
 		serverIP,
 		int32(webhookTimeout),
+		debug,
 		log.Log)
 
 	// Resource Mutating Webhook Watcher
@@ -334,7 +335,6 @@ func main() {
 	// -- annotations on resources with update details on mutation JSON patches
 	// -- generate policy violation resource
 	// -- generate events on policy and resource
-	debug := serverIP != ""
 	server, err := webhooks.NewWebhookServer(
 		pclient,
 		client,
diff --git a/definitions/install.yaml b/definitions/install.yaml
index 40a29765e..5dd2dea71 100644
--- a/definitions/install.yaml
+++ b/definitions/install.yaml
@@ -2441,7 +2441,7 @@ spec:
               fieldPath: metadata.namespace
         - name: KYVERNO_SVC
           value: kyverno-svc
-        image: ghcr.io/kyverno/kyverno:v1.3.5-rc4
+        image: ghcr.io/kyverno/kyverno:v1.3.5
         imagePullPolicy: IfNotPresent
         livenessProbe:
           failureThreshold: 2
@@ -2483,7 +2483,7 @@ spec:
           readOnlyRootFilesystem: true
           runAsNonRoot: true
       initContainers:
-      - image: ghcr.io/kyverno/kyvernopre:v1.3.5-rc4
+      - image: ghcr.io/kyverno/kyvernopre:v1.3.5
         imagePullPolicy: IfNotPresent
         name: kyverno-pre
         securityContext:
diff --git a/definitions/kustomization.yaml b/definitions/kustomization.yaml
index 8a919df3b..5be95fbdd 100755
--- a/definitions/kustomization.yaml
+++ b/definitions/kustomization.yaml
@@ -8,7 +8,7 @@ resources:
 images:
 - name: ghcr.io/kyverno/kyverno
   newName: ghcr.io/kyverno/kyverno
-  newTag: v1.3.5-rc4
+  newTag: v1.3.5
 - name: ghcr.io/kyverno/kyvernopre
   newName: ghcr.io/kyverno/kyvernopre
-  newTag: v1.3.5-rc4
+  newTag: v1.3.5
diff --git a/definitions/release/install.yaml b/definitions/release/install.yaml
index 40a29765e..5dd2dea71 100755
--- a/definitions/release/install.yaml
+++ b/definitions/release/install.yaml
@@ -2441,7 +2441,7 @@ spec:
               fieldPath: metadata.namespace
         - name: KYVERNO_SVC
           value: kyverno-svc
-        image: ghcr.io/kyverno/kyverno:v1.3.5-rc4
+        image: ghcr.io/kyverno/kyverno:v1.3.5
         imagePullPolicy: IfNotPresent
         livenessProbe:
           failureThreshold: 2
@@ -2483,7 +2483,7 @@ spec:
           readOnlyRootFilesystem: true
           runAsNonRoot: true
       initContainers:
-      - image: ghcr.io/kyverno/kyvernopre:v1.3.5-rc4
+      - image: ghcr.io/kyverno/kyvernopre:v1.3.5
         imagePullPolicy: IfNotPresent
         name: kyverno-pre
         securityContext:
diff --git a/go.mod b/go.mod
index eea78ccce..bf382246e 100644
--- a/go.mod
+++ b/go.mod
@@ -13,11 +13,12 @@ require (
 	github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
 	github.com/go-git/go-billy/v5 v5.0.0
 	github.com/go-git/go-git/v5 v5.2.0
-	github.com/go-logr/logr v0.3.0
+	github.com/go-logr/logr v0.4.0
 	github.com/googleapis/gnostic v0.5.4
 	github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af
 	github.com/julienschmidt/httprouter v1.3.0
 	github.com/kataras/tablewriter v0.0.0-20180708051242-e063d29b7c23
+	github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
 	github.com/lensesio/tableprinter v0.0.0-20201125135848-89e81fc956e7
 	github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a
 	github.com/mattn/go-isatty v0.0.12 // indirect
@@ -25,23 +26,21 @@ require (
 	github.com/onsi/ginkgo v1.14.1
 	github.com/onsi/gomega v1.10.2
 	github.com/opencontainers/go-digest v1.0.0 // indirect
-	github.com/opencontainers/image-spec v1.0.1 // indirect
 	github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/errors v0.9.1
-	github.com/sirupsen/logrus v1.6.0 // indirect
 	github.com/spf13/cobra v1.1.1
 	github.com/stretchr/testify v1.6.1
-	gopkg.in/yaml.v2 v2.3.0
+	gopkg.in/yaml.v2 v2.4.0
 	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
 	gotest.tools v2.2.0+incompatible
-	k8s.io/api v0.20.2
-	k8s.io/apiextensions-apiserver v0.20.2
-	k8s.io/apimachinery v0.20.2
+	k8s.io/api v0.21.0
+	k8s.io/apiextensions-apiserver v0.21.0
+	k8s.io/apimachinery v0.21.0
 	k8s.io/cli-runtime v0.20.2
-	k8s.io/client-go v0.20.2
-	k8s.io/klog/v2 v2.4.0
-	k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd
+	k8s.io/client-go v0.21.0
+	k8s.io/klog/v2 v2.8.0
+	k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7
 	sigs.k8s.io/controller-runtime v0.8.1
 	sigs.k8s.io/kustomize/api v0.7.0
 	sigs.k8s.io/kustomize/kyaml v0.10.3
@@ -51,6 +50,7 @@ require (
 // Added for go1.13 migration https://github.com/golang/go/issues/32805
 replace (
 	github.com/gorilla/rpc v1.2.0+incompatible => github.com/gorilla/rpc v1.2.0
+	github.com/jmespath/go-jmespath => github.com/kyverno/go-jmespath v0.4.1-0.20210302163943-f30eab0a3ed6
 	k8s.io/code-generator => k8s.io/code-generator v0.0.0-20200306081859-6a048a382944
 	k8s.io/component-base => k8s.io/component-base v0.0.0-20190612130303-4062e14deebe
 )
diff --git a/go.sum b/go.sum
index faf5fd3ab..89faae839 100644
--- a/go.sum
+++ b/go.sum
@@ -33,6 +33,7 @@ github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
+github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
 github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
 github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
 github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
@@ -53,6 +54,7 @@ github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITg
 github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
 github.com/Masterminds/sprig v2.16.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/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
 github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
@@ -92,6 +94,7 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
@@ -237,6 +240,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs=
 github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
+github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
 github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU=
 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
 github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
@@ -316,6 +321,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -476,8 +483,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
 github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -498,6 +505,7 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v
 github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
@@ -523,6 +531,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU=
+github.com/kyverno/go-jmespath v0.4.1-0.20210302163943-f30eab0a3ed6 h1:9rJUAc/XxL6wV4i+3X56wcRM8tDhoo0l7DIieuXPGfk=
+github.com/kyverno/go-jmespath v0.4.1-0.20210302163943-f30eab0a3ed6/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
 github.com/lensesio/tableprinter v0.0.0-20201125135848-89e81fc956e7 h1:k/1ku0yehLCPqERCHkIHMDqDg1R02AcCScRuHbamU3s=
 github.com/lensesio/tableprinter v0.0.0-20201125135848-89e81fc956e7/go.mod h1:YR/zYthNdWfO8+0IOyHDcIDBBBS2JMnYUIwSsnwmRqU=
 github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@@ -592,8 +602,10 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
 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=
@@ -652,8 +664,6 @@ github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
 github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
-github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6 h1:lNCW6THrCKBiJBpz8kbVGjC7MgdCGKwuvBgc7LoD6sw=
 github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CFcDWnWD9XkenwhI=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -734,6 +744,7 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
 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/skyrings/skyring-common v0.0.0-20160929130248-d1c0bb1cbd5e/go.mod h1:d8hQseuYt4rJoOo21lFzYJdhMjmDqLY++ayArbgYjWI=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
@@ -808,6 +819,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q
 github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI=
 github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yujunz/go-getter v1.5.1-lite.0.20201201013212-6d9c071adddf/go.mod h1:bL0Pr07HEdsMZ1WBqZIxXj96r5LnFsY4LgPaPEGkw1k=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -859,6 +872,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
 golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -888,6 +903,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -926,8 +942,11 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM=
+golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -941,6 +960,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -993,6 +1013,13 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M=
+golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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 h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
+golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1008,6 +1035,8 @@ 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 h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
 golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
+golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1061,6 +1090,8 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
 golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1173,6 +1204,8 @@ gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -1192,11 +1225,15 @@ k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
 k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
 k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
 k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
+k8s.io/api v0.21.0 h1:gu5iGF4V6tfVCQ/R+8Hc0h7H1JuEhzyEi9S4R5LM8+Y=
+k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU=
 k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY=
 k8s.io/apiextensions-apiserver v0.16.4/go.mod h1:HYQwjujEkXmQNhap2C9YDdIVOSskGZ3et0Mvjcyjbto=
 k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
 k8s.io/apiextensions-apiserver v0.20.2 h1:rfrMWQ87lhd8EzQWRnbQ4gXrniL/yTRBgYH1x1+BLlo=
 k8s.io/apiextensions-apiserver v0.20.2/go.mod h1:F6TXp389Xntt+LUq3vw6HFOLttPa0V8821ogLGwb6Zs=
+k8s.io/apiextensions-apiserver v0.21.0 h1:Nd4uBuweg6ImzbxkC1W7xUNZcCV/8Vt10iTdTIVF3hw=
+k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc=
 k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA=
 k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4=
 k8s.io/apimachinery v0.16.4/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
@@ -1204,10 +1241,13 @@ k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZ
 k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
 k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
 k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
+k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA=
+k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
 k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg=
 k8s.io/apiserver v0.16.4/go.mod h1:kbLJOak655g6W7C+muqu1F76u9wnEycfKMqbVaXIdAc=
 k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
 k8s.io/apiserver v0.20.2/go.mod h1:2nKd93WyMhZx4Hp3RfgH2K5PhwyTrprrkWYnI7id7jA=
+k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg=
 k8s.io/cli-runtime v0.20.2 h1:W0/FHdbApnl9oB7xdG643c/Zaf7TZT+43I+zKxwqvhU=
 k8s.io/cli-runtime v0.20.2/go.mod h1:FjH6uIZZZP3XmwrXWeeYCbgxcrD6YXxoAykBaWH0VdM=
 k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
@@ -1216,6 +1256,8 @@ k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
 k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
 k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
 k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
+k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag=
+k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA=
 k8s.io/code-generator v0.0.0-20200306081859-6a048a382944/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
 k8s.io/component-base v0.0.0-20190612130303-4062e14deebe/go.mod h1:MmIDXnint3qMN0cqXHKrSiJ2XQKo3J1BPIz7in7NvO0=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -1232,12 +1274,16 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
 k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
+k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts=
+k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
 k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
 k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
 k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
 k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
 k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
+k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0=
+k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
 k8s.io/metrics v0.16.4/go.mod h1:dckkfqvaASo+NrzEmp8ST8yCc9hGt7lx9ABAILyDHx8=
 k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
 k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
@@ -1252,6 +1298,7 @@ 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.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
+sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
 sigs.k8s.io/controller-runtime v0.8.1 h1:O0K2CJ2JavK8/Tf4LfcpAwRxOFBhv8DjyrbmE6Qw59s=
 sigs.k8s.io/controller-runtime v0.8.1/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
 sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA=
@@ -1268,6 +1315,8 @@ sigs.k8s.io/structured-merge-diff v1.0.1/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8AP
 sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8=
+sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
 sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/pkg/engine/context/evaluate.go b/pkg/engine/context/evaluate.go
index 05bfec755..fb8181974 100644
--- a/pkg/engine/context/evaluate.go
+++ b/pkg/engine/context/evaluate.go
@@ -5,7 +5,7 @@ import (
 	"fmt"
 	"strings"
 
-	jmespath "github.com/jmespath/go-jmespath"
+	jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
 )
 
 //Query the JSON context with JMESPATH search path
@@ -25,7 +25,7 @@ func (ctx *Context) Query(query string) (interface{}, error) {
 	}
 
 	// compile the query
-	queryPath, err := jmespath.Compile(query)
+	queryPath, err := jmespath.New(query)
 	if err != nil {
 		ctx.log.Error(err, "incorrect query", "query", query)
 		return emptyResult, fmt.Errorf("incorrect query %s: %v", query, err)
diff --git a/pkg/engine/jmespath/functions.go b/pkg/engine/jmespath/functions.go
new file mode 100644
index 000000000..4bfad9f5f
--- /dev/null
+++ b/pkg/engine/jmespath/functions.go
@@ -0,0 +1,381 @@
+package jmespath
+
+import (
+	"errors"
+	"fmt"
+	"reflect"
+	"regexp"
+	"strconv"
+	"strings"
+
+	gojmespath "github.com/jmespath/go-jmespath"
+)
+
+var (
+	JpObject      = gojmespath.JpObject
+	JpString      = gojmespath.JpString
+	JpNumber      = gojmespath.JpNumber
+	JpArray       = gojmespath.JpArray
+	JpArrayString = gojmespath.JpArrayString
+)
+
+type (
+	JpType  = gojmespath.JpType
+	ArgSpec = gojmespath.ArgSpec
+)
+
+// function names
+var (
+	compare                = "compare"
+	contains               = "contains"
+	equalFold              = "equal_fold"
+	replace                = "replace"
+	replaceAll             = "replace_all"
+	toUpper                = "to_upper"
+	toLower                = "to_lower"
+	trim                   = "trim"
+	split                  = "split"
+	equals                 = "equals"
+	regexReplaceAll        = "regex_replace_all"
+	regexReplaceAllLiteral = "regex_replace_all_literal"
+	regexMatch             = "regex_match"
+)
+
+const errorPrefix = "JMESPath function '%s': "
+const invalidArgumentTypeError = errorPrefix + "%d argument is expected of %s type"
+const genericError = errorPrefix + "%s"
+
+func getFunctions() []*gojmespath.FunctionEntry {
+	return []*gojmespath.FunctionEntry{
+		{
+			Name: compare,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfCompare,
+		},
+		{
+			Name: contains,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfContains,
+		},
+		{
+			Name: equalFold,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfEqualFold,
+		},
+		{
+			Name: replace,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpNumber}},
+			},
+			Handler: jpfReplace,
+		},
+		{
+			Name: replaceAll,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfReplaceAll,
+		},
+		{
+			Name: toUpper,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfToUpper,
+		},
+		{
+			Name: toLower,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfToLower,
+		},
+		{
+			Name: trim,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfTrim,
+		},
+		{
+			Name: split,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString}},
+			},
+			Handler: jpfSplit,
+		},
+		{
+			Name: regexReplaceAll,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString, JpNumber}},
+				{Types: []JpType{JpString, JpNumber}},
+			},
+			Handler: jpRegexReplaceAll,
+		},
+		{
+			Name: regexReplaceAllLiteral,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString, JpNumber}},
+				{Types: []JpType{JpString, JpNumber}},
+			},
+			Handler: jpRegexReplaceAllLiteral,
+		},
+		{
+			Name: regexMatch,
+			Arguments: []ArgSpec{
+				{Types: []JpType{JpString}},
+				{Types: []JpType{JpString, JpNumber}},
+			},
+			Handler: jpRegexMatch,
+		},
+	}
+
+}
+
+func jpfCompare(arguments []interface{}) (interface{}, error) {
+	var err error
+	a, err := validateArg(compare, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	b, err := validateArg(compare, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.Compare(a.String(), b.String()), nil
+}
+
+func jpfContains(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(contains, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	substr, err := validateArg(contains, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.Contains(str.String(), substr.String()), nil
+}
+
+func jpfEqualFold(arguments []interface{}) (interface{}, error) {
+	var err error
+	a, err := validateArg(equalFold, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	b, err := validateArg(equalFold, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.EqualFold(a.String(), b.String()), nil
+}
+
+func jpfReplace(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(replace, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	old, err := validateArg(replace, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	new, err := validateArg(replace, arguments, 2, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	n, err := validateArg(replace, arguments, 3, reflect.Float64)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.Replace(str.String(), old.String(), new.String(), int(n.Float())), nil
+}
+
+func jpfReplaceAll(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(replaceAll, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	old, err := validateArg(replaceAll, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	new, err := validateArg(replaceAll, arguments, 2, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.ReplaceAll(str.String(), old.String(), new.String()), nil
+}
+
+func jpfToUpper(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(toUpper, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.ToUpper(str.String()), nil
+}
+
+func jpfToLower(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(toLower, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.ToLower(str.String()), nil
+}
+
+func jpfTrim(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(trim, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	cutset, err := validateArg(trim, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.Trim(str.String(), cutset.String()), nil
+}
+
+func jpfSplit(arguments []interface{}) (interface{}, error) {
+	var err error
+	str, err := validateArg(split, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	sep, err := validateArg(split, arguments, 1, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.Split(str.String(), sep.String()), nil
+}
+
+func jpRegexReplaceAll(arguments []interface{}) (interface{}, error) {
+	var err error
+	regex, err := validateArg(regexReplaceAll, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	src, err := ifaceToString(arguments[1])
+	if err != nil {
+		return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAll, 2, "String or Real")
+	}
+
+	repl, err := ifaceToString(arguments[2])
+	if err != nil {
+		return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAll, 3, "String or Real")
+	}
+
+	reg, err := regexp.Compile(regex.String())
+	if err != nil {
+		return nil, fmt.Errorf(genericError, regexReplaceAll, err.Error())
+	}
+	return string(reg.ReplaceAll([]byte(src), []byte(repl))), nil
+}
+
+func jpRegexReplaceAllLiteral(arguments []interface{}) (interface{}, error) {
+	var err error
+	regex, err := validateArg(regexReplaceAllLiteral, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	src, err := ifaceToString(arguments[1])
+	if err != nil {
+		return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAllLiteral, 2, "String or Real")
+	}
+
+	repl, err := ifaceToString(arguments[2])
+	if err != nil {
+		return nil, fmt.Errorf(invalidArgumentTypeError, regexReplaceAllLiteral, 3, "String or Real")
+	}
+
+	reg, err := regexp.Compile(regex.String())
+	if err != nil {
+		return nil, fmt.Errorf(genericError, regexReplaceAllLiteral, err.Error())
+	}
+	return string(reg.ReplaceAllLiteral([]byte(src), []byte(repl))), nil
+}
+
+func jpRegexMatch(arguments []interface{}) (interface{}, error) {
+	var err error
+	regex, err := validateArg(regexMatch, arguments, 0, reflect.String)
+	if err != nil {
+		return nil, err
+	}
+
+	src, err := ifaceToString(arguments[1])
+	if err != nil {
+		return nil, fmt.Errorf(invalidArgumentTypeError, regexMatch, 2, "String or Real")
+	}
+
+	return regexp.Match(regex.String(), []byte(src))
+}
+
+// InterfaceToString casts an interface to a string type
+func ifaceToString(iface interface{}) (string, error) {
+	switch iface.(type) {
+	case int:
+		return strconv.Itoa(iface.(int)), nil
+	case float64:
+		return strconv.FormatFloat(iface.(float64), 'f', -1, 32), nil
+	case float32:
+		return strconv.FormatFloat(iface.(float64), 'f', -1, 32), nil
+	case string:
+		return iface.(string), nil
+	case bool:
+		return strconv.FormatBool(iface.(bool)), nil
+	default:
+		return "", errors.New("error, undefined type cast")
+	}
+}
+
+func validateArg(f string, arguments []interface{}, index int, expectedType reflect.Kind) (reflect.Value, error) {
+	arg := reflect.ValueOf(arguments[index])
+	if arg.Type().Kind() != expectedType {
+		return reflect.Value{}, fmt.Errorf(invalidArgumentTypeError, equalFold, index+1, expectedType.String())
+	}
+
+	return arg, nil
+}
diff --git a/pkg/engine/jmespath/new.go b/pkg/engine/jmespath/new.go
new file mode 100644
index 000000000..5714de69d
--- /dev/null
+++ b/pkg/engine/jmespath/new.go
@@ -0,0 +1,18 @@
+package jmespath
+
+import (
+	gojmespath "github.com/jmespath/go-jmespath"
+)
+
+func New(query string) (*gojmespath.JMESPath, error) {
+	jp, err := gojmespath.Compile(query)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, function := range getFunctions() {
+		jp.Register(function)
+	}
+
+	return jp, nil
+}
diff --git a/pkg/engine/jsonContext.go b/pkg/engine/jsonContext.go
index 207086f14..7c5c8b08a 100644
--- a/pkg/engine/jsonContext.go
+++ b/pkg/engine/jsonContext.go
@@ -8,9 +8,9 @@ import (
 	"strings"
 
 	"github.com/go-logr/logr"
-	"github.com/jmespath/go-jmespath"
 	kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
 	"github.com/kyverno/kyverno/pkg/engine/context"
+	jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
 	"github.com/kyverno/kyverno/pkg/engine/variables"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
 	"k8s.io/client-go/dynamic/dynamiclister"
@@ -88,7 +88,7 @@ func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCont
 }
 
 func applyJMESPath(jmesPath string, jsonData []byte) (interface{}, error) {
-	jp, err := jmespath.Compile(jmesPath)
+	jp, err := jmespath.New(jmesPath)
 	if err != nil {
 		return nil, fmt.Errorf("failed to compile JMESPath: %s, error: %v", jmesPath, err)
 	}
diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go
index 9e84f7552..6b44cf130 100644
--- a/pkg/engine/mutation.go
+++ b/pkg/engine/mutation.go
@@ -58,7 +58,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
 
 		// check if the resource satisfies the filter conditions defined in the rule
 		//TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that
-		// dont satisfy a policy rule resource description
+		// don't satisfy a policy rule resource description
 		excludeResource := []string{}
 		if len(policyContext.ExcludeGroupRole) > 0 {
 			excludeResource = policyContext.ExcludeGroupRole
@@ -95,11 +95,13 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
 				Name:    rule.Name,
 				Type:    utils.Validation.String(),
 				Message: fmt.Sprintf("variable substitution failed for rule %s: %s", rule.Name, err.Error()),
-				Success: false,
+				Success: true,
 			}
 
 			incrementAppliedCount(resp)
 			resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResp)
+
+			logger.Error(err, "failed to substitute variables, skip current rule", "rule name", rule.Name)
 			continue
 		}
 
diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go
index 17ad9d5a3..353d9e4e5 100644
--- a/pkg/engine/validation.go
+++ b/pkg/engine/validation.go
@@ -121,12 +121,13 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
 				Name:    rule.Name,
 				Type:    utils.Validation.String(),
 				Message: fmt.Sprintf("variable substitution failed for rule %s: %s", rule.Name, err.Error()),
-				Success: false,
+				Success: true,
 			}
 
 			incrementAppliedCount(resp)
 			resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResp)
 
+			log.Error(err, "failed to substitute variables, skip current rule", "rule name", rule.Name)
 			continue
 		}
 
diff --git a/pkg/engine/variables/vars.go b/pkg/engine/variables/vars.go
index c8a2d005b..2711ce984 100644
--- a/pkg/engine/variables/vars.go
+++ b/pkg/engine/variables/vars.go
@@ -119,7 +119,7 @@ type NotFoundVariableErr struct {
 }
 
 func (n NotFoundVariableErr) Error() string {
-	return fmt.Sprintf("variable %s not resolved at path %s", n.variable, n.path)
+	return fmt.Sprintf("NotFoundVariableErr, variable %s not resolved at path %s", n.variable, n.path)
 }
 
 // NotResolvedReferenceErr is returned when it is impossible to resolve the variable
@@ -129,7 +129,7 @@ type NotResolvedReferenceErr struct {
 }
 
 func (n NotResolvedReferenceErr) Error() string {
-	return fmt.Sprintf("reference %s not resolved at path %s", n.reference, n.path)
+	return fmt.Sprintf("NotResolvedReferenceErr,reference %s not resolved at path %s", n.reference, n.path)
 }
 
 func substituteReferencesIfAny(log logr.Logger) jsonUtils.Action {
@@ -185,6 +185,11 @@ func substituteVariablesIfAny(log logr.Logger, ctx context.EvalInterface) jsonUt
 			for _, v := range vars {
 				variable := replaceBracesAndTrimSpaces(v)
 
+				if variable == "@" {
+					currentPath := getJMESPath(data.Path)
+					variable = strings.Replace(variable, "@", fmt.Sprintf("request.object%s", currentPath), -1)
+				}
+
 				operation, err := ctx.Query("request.operation")
 				if err == nil && operation == "DELETE" {
 					variable = strings.ReplaceAll(variable, "request.object", "request.oldObject")
@@ -228,6 +233,13 @@ func substituteVariablesIfAny(log logr.Logger, ctx context.EvalInterface) jsonUt
 	})
 }
 
+// getJMESPath converts path to JMES format
+func getJMESPath(rawPath string) string {
+	path := strings.ReplaceAll(rawPath, "/", ".")
+	regex := regexp.MustCompile(`\.([\d])\.`)
+	return string(regex.ReplaceAll([]byte(path), []byte("[$1].")))
+}
+
 func substituteVarInPattern(pattern, variable string, value interface{}) (string, error) {
 	var stringToSubstitute string
 
diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go
index bf80d13f4..aaa8db345 100644
--- a/pkg/generate/generate.go
+++ b/pkg/generate/generate.go
@@ -377,7 +377,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
 	newResource.SetAPIVersion(genAPIVersion)
 	// manage labels
 	// - app.kubernetes.io/managed-by: kyverno
-	// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
+	// "kyverno.io/generated-by-kind": kind (trigger resource)
+	// "kyverno.io/generated-by-namespace": namespace (trigger resource)
+	// "kyverno.io/generated-by-name": name (trigger resource)
 	manageLabels(newResource, resource)
 	// Add Synchronize label
 	label := newResource.GetLabels()
diff --git a/pkg/kyverno/crds/policy_crd.go b/pkg/kyverno/crds/policy_crd.go
new file mode 100644
index 000000000..9b7df79c4
--- /dev/null
+++ b/pkg/kyverno/crds/policy_crd.go
@@ -0,0 +1,709 @@
+package crds
+
+const PolicyCRD = `
+{
+	"group": "kyverno.io",
+	"names": {
+	  "kind": "Policy",
+	  "listKind": "PolicyList",
+	  "plural": "policies",
+	  "shortNames": [
+		"pol"
+	  ],
+	  "singular": "policy"
+	},
+	"scope": "Namespaced",
+	"versions": [
+	  {
+		"additionalPrinterColumns": [
+		  {
+			"jsonPath": ".spec.background",
+			"name": "Background",
+			"type": "string"
+		  },
+		  {
+			"jsonPath": ".spec.validationFailureAction",
+			"name": "Action",
+			"type": "string"
+		  }
+		],
+		"name": "v1",
+		"schema": {
+		  "openAPIV3Schema": {
+			"description": "Policy declares validation, mutation, and generation behaviors for matching resources. See: https://kyverno.io/docs/writing-policies/ for more information.",
+			"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": "Spec defines policy behaviors and contains one or rules.",
+				"properties": {
+				  "background": {
+					"description": "Background controls if rules are applied to existing resources during a background scan. Optional. Default value is \"true\". The value must be set to \"false\" if the policy rule uses variables that are only available in the admission review request (e.g. user name).",
+					"type": "boolean"
+				  },
+				  "rules": {
+					"description": "Rules is a list of Rule instances. A Policy contains multiple rules and each rule can validate, mutate, or generate resources.",
+					"items": {
+					  "schema": {
+						"description": "Rule defines a validation, mutation, or generation control for matching resources. Each rules contains a match declaration to select resources, and an optional exclude declaration to specify which resources to exclude.",
+						"properties": {
+						  "context": {
+							"description": "Context defines variables and data sources that can be used during rule execution.",
+							"items": {
+							  "schema": {
+								"description": "ContextEntry adds variables and data sources to a rule Context. Either a ConfigMap reference or a APILookup must be provided.",
+								"properties": {
+								  "apiCall": {
+									"description": "APICall defines an HTTP request to the Kubernetes API server. The JSON data retrieved is stored in the context.",
+									"properties": {
+									  "jmesPath": {
+										"description": "JMESPath is an optional JSON Match Expression that can be used to transform the JSON response returned from the API server. For example a JMESPath of \"items | length(@)\" applied to the API server response to the URLPath \"/apis/apps/v1/deployments\" will return the total count of deployments across all namespaces.",
+										"type": "string"
+									  },
+									  "urlPath": {
+										"description": "URLPath is the URL path to be used in the HTTP GET request to the Kubernetes API server (e.g. \"/api/v1/namespaces\" or  \"/apis/apps/v1/deployments\"). The format required is the same format used by the 'kubectl get --raw' command.",
+										"type": "string"
+									  }
+									},
+									"required": [
+									  "urlPath"
+									],
+									"type": "object"
+								  },
+								  "configMap": {
+									"description": "ConfigMap is the ConfigMap reference.",
+									"properties": {
+									  "name": {
+										"description": "Name is the ConfigMap name.",
+										"type": "string"
+									  },
+									  "namespace": {
+										"description": "Namespace is the ConfigMap namespace.",
+										"type": "string"
+									  }
+									},
+									"required": [
+									  "name"
+									],
+									"type": "object"
+								  },
+								  "name": {
+									"description": "Name is the variable name.",
+									"type": "string"
+								  }
+								},
+								"type": "object"
+							  }
+							},
+							"type": "array"
+						  },
+						  "exclude": {
+							"description": "ExcludeResources defines when this policy rule should not be applied. The exclude criteria can include resource information (e.g. kind, name, namespace, labels) and admission review request information like the name or role.",
+							"properties": {
+							  "clusterRoles": {
+								"description": "ClusterRoles is the list of cluster-wide role names for the user.",
+								"items": {
+								  "schema": {
+									"type": "string"
+								  }
+								},
+								"type": "array"
+							  },
+							  "resources": {
+								"description": "ResourceDescription contains information about the resource being created or modified.",
+								"properties": {
+								  "annotations": {
+									"additionalProperties": {
+									  "type": "string"
+									},
+									"description": "Annotations is a  map of annotations (key-value pairs of type string). Annotation keys and values support the wildcard characters \"*\" (matches zero or many characters) and \"?\" (matches at least one character).",
+									"type": "object"
+								  },
+								  "kinds": {
+									"description": "Kinds is a list of resource kinds.",
+									"items": {
+									  "schema": {
+										"type": "string"
+									  }
+									},
+									"type": "array"
+								  },
+								  "name": {
+									"description": "Name is the name of the resource. The name supports wildcard characters \"*\" (matches zero or many characters) and \"?\" (at least one character).",
+									"type": "string"
+								  },
+								  "namespaceSelector": {
+									"description": "NamespaceSelector is a label selector for the resource namespace. Label keys and values in 'matchLabels' support the wildcard characters '*' (matches zero or many characters) and '?' (matches one character).Wildcards allows writing label selectors like [\"storage.k8s.io/*\": \"*\"]. Note that using [\"*\" : \"*\"] matches any key and value but does not match an empty label set.",
+									"properties": {
+									  "matchExpressions": {
+										"description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
+										"items": {
+										  "schema": {
+											"description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
+											"properties": {
+											  "key": {
+												"description": "key is the label key that the selector applies to.",
+												"type": "string"
+											  },
+											  "operator": {
+												"description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.",
+												"type": "string"
+											  },
+											  "values": {
+												"description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
+												"items": {
+												  "schema": {
+													"type": "string"
+												  }
+												},
+												"type": "array"
+											  }
+											},
+											"required": [
+											  "key",
+											  "operator"
+											],
+											"type": "object"
+										  }
+										},
+										"type": "array"
+									  },
+									  "matchLabels": {
+										"additionalProperties": {
+										  "type": "string"
+										},
+										"description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
+										"type": "object"
+									  }
+									},
+									"type": "object"
+								  },
+								  "namespaces": {
+									"description": "Namespaces is a list of namespaces names. Each name supports wildcard characters \"*\" (matches zero or many characters) and \"?\" (at least one character).",
+									"items": {
+									  "schema": {
+										"type": "string"
+									  }
+									},
+									"type": "array"
+								  },
+								  "selector": {
+									"description": "Selector is a label selector. Label keys and values in 'matchLabels' support the wildcard characters '*' (matches zero or many characters) and '?' (matches one character). Wildcards allows writing label selectors like [\"storage.k8s.io/*\": \"*\"]. Note that using [\"*\" : \"*\"] matches any key and value but does not match an empty label set.",
+									"properties": {
+									  "matchExpressions": {
+										"description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
+										"items": {
+										  "schema": {
+											"description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
+											"properties": {
+											  "key": {
+												"description": "key is the label key that the selector applies to.",
+												"type": "string"
+											  },
+											  "operator": {
+												"description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.",
+												"type": "string"
+											  },
+											  "values": {
+												"description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
+												"items": {
+												  "schema": {
+													"type": "string"
+												  }
+												},
+												"type": "array"
+											  }
+											},
+											"required": [
+											  "key",
+											  "operator"
+											],
+											"type": "object"
+										  }
+										},
+										"type": "array"
+									  },
+									  "matchLabels": {
+										"additionalProperties": {
+										  "type": "string"
+										},
+										"description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
+										"type": "object"
+									  }
+									},
+									"type": "object"
+								  }
+								},
+								"type": "object"
+							  },
+							  "roles": {
+								"description": "Roles is the list of namespaced role names for the user.",
+								"items": {
+								  "schema": {
+									"type": "string"
+								  }
+								},
+								"type": "array"
+							  },
+							  "subjects": {
+								"description": "Subjects is the list of subject names like users, user groups, and service accounts.",
+								"items": {
+								  "schema": {
+									"description": "Subject contains a reference to the object or user identities a role binding applies to.  This can either hold a direct API object reference, or a value for non-objects such as user and group names.",
+									"properties": {
+									  "apiGroup": {
+										"description": "APIGroup holds the API group of the referenced subject. Defaults to \"\" for ServiceAccount subjects. Defaults to \"rbac.authorization.k8s.io\" for User and Group subjects.",
+										"type": "string"
+									  },
+									  "kind": {
+										"description": "Kind of object being referenced. Values defined by this API group are \"User\", \"Group\", and \"ServiceAccount\". If the Authorizer does not recognized the kind value, the Authorizer should report an error.",
+										"type": "string"
+									  },
+									  "name": {
+										"description": "Name of the object being referenced.",
+										"type": "string"
+									  },
+									  "namespace": {
+										"description": "Namespace of the referenced object.  If the object kind is non-namespace, such as \"User\" or \"Group\", and this value is not empty the Authorizer should report an error.",
+										"type": "string"
+									  }
+									},
+									"required": [
+									  "kind",
+									  "name"
+									],
+									"type": "object"
+								  }
+								},
+								"type": "array"
+							  }
+							},
+							"type": "object"
+						  },
+						  "generate": {
+							"description": "Generation is used to create new resources.",
+							"properties": {
+							  "apiVersion": {
+								"description": "APIVersion specifies resource apiVersion.",
+								"type": "string"
+							  },
+							  "clone": {
+								"description": "Clone specifies the source resource used to populate each generated resource. At most one of Data or Clone can be specified. If neither are provided, the generated resource will be created with default data only.",
+								"properties": {
+								  "name": {
+									"description": "Name specifies name of the resource.",
+									"type": "string"
+								  },
+								  "namespace": {
+									"description": "Namespace specifies source resource namespace.",
+									"type": "string"
+								  }
+								},
+								"type": "object"
+							  },
+							  "data": {
+								"description": "Data provides the resource declaration used to populate each generated resource. At most one of Data or Clone must be specified. If neither are provided, the generated resource will be created with default data only.",
+								"x-kubernetes-preserve-unknown-fields": true
+							  },
+							  "kind": {
+								"description": "Kind specifies resource kind.",
+								"type": "string"
+							  },
+							  "name": {
+								"description": "Name specifies the resource name.",
+								"type": "string"
+							  },
+							  "namespace": {
+								"description": "Namespace specifies resource namespace.",
+								"type": "string"
+							  },
+							  "synchronize": {
+								"description": "Synchronize controls if generated resources should be kept in-sync with their source resource. If Synchronize is set to \"true\" changes to generated resources will be overwritten with resource data from Data or the resource specified in the Clone declaration. Optional. Defaults to \"false\" if not specified.",
+								"type": "boolean"
+							  }
+							},
+							"type": "object"
+						  },
+						  "match": {
+							"description": "MatchResources defines when this policy rule should be applied. The match criteria can include resource information (e.g. kind, name, namespace, labels) and admission review request information like the user name or role. At least one kind is required.",
+							"properties": {
+							  "clusterRoles": {
+								"description": "ClusterRoles is the list of cluster-wide role names for the user.",
+								"items": {
+								  "schema": {
+									"type": "string"
+								  }
+								},
+								"type": "array"
+							  },
+							  "resources": {
+								"description": "ResourceDescription contains information about the resource being created or modified. Requires at least one tag to be specified when under MatchResources.",
+								"properties": {
+								  "annotations": {
+									"additionalProperties": {
+									  "type": "string"
+									},
+									"description": "Annotations is a  map of annotations (key-value pairs of type string). Annotation keys and values support the wildcard characters \"*\" (matches zero or many characters) and \"?\" (matches at least one character).",
+									"type": "object"
+								  },
+								  "kinds": {
+									"description": "Kinds is a list of resource kinds.",
+									"items": {
+									  "schema": {
+										"type": "string"
+									  }
+									},
+									"type": "array"
+								  },
+								  "name": {
+									"description": "Name is the name of the resource. The name supports wildcard characters \"*\" (matches zero or many characters) and \"?\" (at least one character).",
+									"type": "string"
+								  },
+								  "namespaceSelector": {
+									"description": "NamespaceSelector is a label selector for the resource namespace. Label keys and values in 'matchLabels' support the wildcard characters '*' (matches zero or many characters) and '?' (matches one character).Wildcards allows writing label selectors like [\"storage.k8s.io/*\": \"*\"]. Note that using [\"*\" : \"*\"] matches any key and value but does not match an empty label set.",
+									"properties": {
+									  "matchExpressions": {
+										"description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
+										"items": {
+										  "schema": {
+											"description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
+											"properties": {
+											  "key": {
+												"description": "key is the label key that the selector applies to.",
+												"type": "string"
+											  },
+											  "operator": {
+												"description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.",
+												"type": "string"
+											  },
+											  "values": {
+												"description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
+												"items": {
+												  "schema": {
+													"type": "string"
+												  }
+												},
+												"type": "array"
+											  }
+											},
+											"required": [
+											  "key",
+											  "operator"
+											],
+											"type": "object"
+										  }
+										},
+										"type": "array"
+									  },
+									  "matchLabels": {
+										"additionalProperties": {
+										  "type": "string"
+										},
+										"description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
+										"type": "object"
+									  }
+									},
+									"type": "object"
+								  },
+								  "namespaces": {
+									"description": "Namespaces is a list of namespaces names. Each name supports wildcard characters \"*\" (matches zero or many characters) and \"?\" (at least one character).",
+									"items": {
+									  "schema": {
+										"type": "string"
+									  }
+									},
+									"type": "array"
+								  },
+								  "selector": {
+									"description": "Selector is a label selector. Label keys and values in 'matchLabels' support the wildcard characters '*' (matches zero or many characters) and '?' (matches one character). Wildcards allows writing label selectors like [\"storage.k8s.io/*\": \"*\"]. Note that using [\"*\" : \"*\"] matches any key and value but does not match an empty label set.",
+									"properties": {
+									  "matchExpressions": {
+										"description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
+										"items": {
+										  "schema": {
+											"description": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
+											"properties": {
+											  "key": {
+												"description": "key is the label key that the selector applies to.",
+												"type": "string"
+											  },
+											  "operator": {
+												"description": "operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.",
+												"type": "string"
+											  },
+											  "values": {
+												"description": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
+												"items": {
+												  "schema": {
+													"type": "string"
+												  }
+												},
+												"type": "array"
+											  }
+											},
+											"required": [
+											  "key",
+											  "operator"
+											],
+											"type": "object"
+										  }
+										},
+										"type": "array"
+									  },
+									  "matchLabels": {
+										"additionalProperties": {
+										  "type": "string"
+										},
+										"description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
+										"type": "object"
+									  }
+									},
+									"type": "object"
+								  }
+								},
+								"type": "object"
+							  },
+							  "roles": {
+								"description": "Roles is the list of namespaced role names for the user.",
+								"items": {
+								  "schema": {
+									"type": "string"
+								  }
+								},
+								"type": "array"
+							  },
+							  "subjects": {
+								"description": "Subjects is the list of subject names like users, user groups, and service accounts.",
+								"items": {
+								  "schema": {
+									"description": "Subject contains a reference to the object or user identities a role binding applies to.  This can either hold a direct API object reference, or a value for non-objects such as user and group names.",
+									"properties": {
+									  "apiGroup": {
+										"description": "APIGroup holds the API group of the referenced subject. Defaults to \"\" for ServiceAccount subjects. Defaults to \"rbac.authorization.k8s.io\" for User and Group subjects.",
+										"type": "string"
+									  },
+									  "kind": {
+										"description": "Kind of object being referenced. Values defined by this API group are \"User\", \"Group\", and \"ServiceAccount\". If the Authorizer does not recognized the kind value, the Authorizer should report an error.",
+										"type": "string"
+									  },
+									  "name": {
+										"description": "Name of the object being referenced.",
+										"type": "string"
+									  },
+									  "namespace": {
+										"description": "Namespace of the referenced object.  If the object kind is non-namespace, such as \"User\" or \"Group\", and this value is not empty the Authorizer should report an error.",
+										"type": "string"
+									  }
+									},
+									"required": [
+									  "kind",
+									  "name"
+									],
+									"type": "object"
+								  }
+								},
+								"type": "array"
+							  }
+							},
+							"type": "object"
+						  },
+						  "mutate": {
+							"description": "Mutation is used to modify matching resources.",
+							"properties": {
+							  "overlay": {
+								"description": "Overlay specifies an overlay pattern to modify resources. DEPRECATED. Use PatchStrategicMerge instead. Scheduled for removal in release 1.5+.",
+								"x-kubernetes-preserve-unknown-fields": true
+							  },
+							  "patchStrategicMerge": {
+								"description": "PatchStrategicMerge is a strategic merge patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.",
+								"x-kubernetes-preserve-unknown-fields": true
+							  },
+							  "patches": {
+								"description": "Patches specifies a RFC 6902 JSON Patch to modify resources. DEPRECATED. Use PatchesJSON6902 instead. Scheduled for removal in release 1.5+.",
+								"items": {
+								  "schema": {
+									"description": "Patch is a RFC 6902 JSON Patch. See: https://tools.ietf.org/html/rfc6902",
+									"properties": {
+									  "op": {
+										"description": "Operation specifies operations supported by JSON Patch. i.e:- add, replace and delete.",
+										"type": "string"
+									  },
+									  "path": {
+										"description": "Path specifies path of the resource.",
+										"type": "string"
+									  },
+									  "value": {
+										"description": "Value specifies the value to be applied.",
+										"x-kubernetes-preserve-unknown-fields": true
+									  }
+									},
+									"type": "object"
+								  }
+								},
+								"nullable": true,
+								"type": "array",
+								"x-kubernetes-preserve-unknown-fields": true
+							  },
+							  "patchesJson6902": {
+								"description": "PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/.",
+								"type": "string"
+							  }
+							},
+							"type": "object"
+						  },
+						  "name": {
+							"description": "Name is a label to identify the rule, It must be unique within the policy.",
+							"maxLength": 63,
+							"type": "string"
+						  },
+						  "preconditions": {
+							"description": "AnyAllConditions enable variable-based conditional rule execution. This is useful for finer control of when an rule is applied. A condition can reference object data using JMESPath notation. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.",
+							"x-kubernetes-preserve-unknown-fields": true
+						  },
+						  "validate": {
+							"description": "Validation is used to validate matching resources.",
+							"properties": {
+							  "anyPattern": {
+								"description": "AnyPattern specifies list of validation patterns. At least one of the patterns must be satisfied for the validation rule to succeed.",
+								"x-kubernetes-preserve-unknown-fields": true
+							  },
+							  "deny": {
+								"description": "Deny defines conditions to fail the validation rule.",
+								"properties": {
+								  "conditions": {
+									"description": "specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.",
+									"x-kubernetes-preserve-unknown-fields": true
+								  }
+								},
+								"type": "object"
+							  },
+							  "message": {
+								"description": "Message specifies a custom message to be displayed on failure.",
+								"type": "string"
+							  },
+							  "pattern": {
+								"description": "Pattern specifies an overlay-style pattern used to check resources.",
+								"x-kubernetes-preserve-unknown-fields": true
+							  }
+							},
+							"type": "object"
+						  }
+						},
+						"type": "object"
+					  }
+					},
+					"type": "array"
+				  },
+				  "validationFailureAction": {
+					"description": "ValidationFailureAction controls if a validation policy rule failure should disallow the admission review request (enforce), or allow (audit) the admission review request and report an error in a policy report. Optional. The default value is \"audit\".",
+					"type": "string"
+				  }
+				},
+				"type": "object"
+			  },
+			  "status": {
+				"description": "Status contains policy runtime information.",
+				"properties": {
+				  "averageExecutionTime": {
+					"description": "AvgExecutionTime is the average time taken to process the policy rules on a resource.",
+					"type": "string"
+				  },
+				  "resourcesBlockedCount": {
+					"description": "ResourcesBlockedCount is the total count of admission review requests that were blocked by this policy.",
+					"type": "integer"
+				  },
+				  "resourcesGeneratedCount": {
+					"description": "ResourcesGeneratedCount is the total count of resources that were generated by this policy.",
+					"type": "integer"
+				  },
+				  "resourcesMutatedCount": {
+					"description": "ResourcesMutatedCount is the total count of resources that were mutated by this policy.",
+					"type": "integer"
+				  },
+				  "ruleStatus": {
+					"description": "Rules provides per rule statistics",
+					"items": {
+					  "schema": {
+						"description": "RuleStats provides statistics for an individual rule within a policy.",
+						"properties": {
+						  "appliedCount": {
+							"description": "AppliedCount is the total number of times this rule was applied.",
+							"type": "integer"
+						  },
+						  "averageExecutionTime": {
+							"description": "ExecutionTime is the average time taken to execute this rule.",
+							"type": "string"
+						  },
+						  "failedCount": {
+							"description": "FailedCount is the total count of policy error results for this rule.",
+							"type": "integer"
+						  },
+						  "resourcesBlockedCount": {
+							"description": "ResourcesBlockedCount is the total count of admission review requests that were blocked by this rule.",
+							"type": "integer"
+						  },
+						  "resourcesGeneratedCount": {
+							"description": "ResourcesGeneratedCount is the total count of resources that were generated by this rule.",
+							"type": "integer"
+						  },
+						  "resourcesMutatedCount": {
+							"description": "ResourcesMutatedCount is the total count of resources that were mutated by this rule.",
+							"type": "integer"
+						  },
+						  "ruleName": {
+							"description": "Name is the rule name.",
+							"type": "string"
+						  },
+						  "violationCount": {
+							"description": "ViolationCount is the total count of policy failure results for this rule.",
+							"type": "integer"
+						  }
+						},
+						"required": [
+						  "ruleName"
+						],
+						"type": "object"
+					  }
+					},
+					"type": "array"
+				  },
+				  "rulesAppliedCount": {
+					"description": "RulesAppliedCount is the total number of times this policy was applied.",
+					"type": "integer"
+				  },
+				  "rulesFailedCount": {
+					"description": "RulesFailedCount is the total count of policy execution errors for this policy.",
+					"type": "integer"
+				  },
+				  "violationCount": {
+					"description": "ViolationCount is the total count of policy failure results for this policy.",
+					"type": "integer"
+				  }
+				},
+				"type": "object"
+			  }
+			},
+			"required": [
+			  "spec"
+			],
+			"type": "object"
+		  }
+		},
+		"served": true,
+		"storage": true,
+		"subresources": {
+		  "status": {}
+		}
+	  }
+	]
+  }
+`
diff --git a/pkg/kyverno/validate/command.go b/pkg/kyverno/validate/command.go
index 9940f2bde..2736e8e4e 100644
--- a/pkg/kyverno/validate/command.go
+++ b/pkg/kyverno/validate/command.go
@@ -9,11 +9,16 @@ import (
 
 	v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
 	"github.com/kyverno/kyverno/pkg/kyverno/common"
+	"github.com/kyverno/kyverno/pkg/kyverno/crds"
 	sanitizederror "github.com/kyverno/kyverno/pkg/kyverno/sanitizedError"
 	"github.com/kyverno/kyverno/pkg/openapi"
 	policy2 "github.com/kyverno/kyverno/pkg/policy"
 	"github.com/kyverno/kyverno/pkg/utils"
 	"github.com/spf13/cobra"
+	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
+	apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/util/validation/field"
 	"sigs.k8s.io/controller-runtime/pkg/log"
 	"sigs.k8s.io/yaml"
 )
@@ -46,34 +51,14 @@ func Command() *cobra.Command {
 				return sanitizederror.NewWithError(fmt.Sprintf("policy file(s) required"), err)
 			}
 
-			var policies []*v1.ClusterPolicy
-			var errs []error
-			if policyPaths[0] == "-" {
-				if common.IsInputFromPipe() {
-					policyStr := ""
-					scanner := bufio.NewScanner(os.Stdin)
-					for scanner.Scan() {
-						policyStr = policyStr + scanner.Text() + "\n"
-					}
-
-					yamlBytes := []byte(policyStr)
-					policies, err = utils.GetPolicy(yamlBytes)
-					if err != nil {
-						return sanitizederror.NewWithError("failed to parse policy", err)
-					}
-				}
-			} else {
-				policies, errs = common.GetPolicies(policyPaths)
-				if len(errs) > 0 && len(policies) == 0 {
-					return sanitizederror.NewWithErrors("failed to read policies", errs)
-				}
+			policies, err := getPolicyFromGivenPath(policyPaths)
+			if err != nil {
+				return sanitizederror.NewWithError("failed to parse policy", err)
+			}
 
-				if len(errs) > 0 && log.Log.V(1).Enabled() {
-					fmt.Printf("ignoring errors: \n")
-					for _, e := range errs {
-						fmt.Printf("    %v \n", e.Error())
-					}
-				}
+			v1crd, err := getPolicyCRD()
+			if err != nil {
+				return sanitizederror.NewWithError("failed to decode crd: ", err)
 			}
 
 			openAPIController, err := openapi.NewOpenAPIController()
@@ -93,38 +78,9 @@ func Command() *cobra.Command {
 				}
 			}
 
-			invalidPolicyFound := false
-			for _, policy := range policies {
-				fmt.Println("----------------------------------------------------------------------")
-				err := policy2.Validate(policy, nil, true, openAPIController)
-				if err != nil {
-					fmt.Printf("Policy %s is invalid.\n", policy.Name)
-					fmt.Printf("Error: invalid policy.\nCause: %s\n\n", err)
-					invalidPolicyFound = true
-				} else {
-					fmt.Printf("Policy %s is valid.\n\n", policy.Name)
-					if outputType != "" {
-						logger := log.Log.WithName("validate")
-						p, err := common.MutatePolicy(policy, logger)
-						if err != nil {
-							if !sanitizederror.IsErrorSanitized(err) {
-								return sanitizederror.NewWithError("failed to mutate policy.", err)
-							}
-							return err
-						}
-						if outputType == "yaml" {
-							yamlPolicy, _ := yaml.Marshal(p)
-							fmt.Println(string(yamlPolicy))
-						} else {
-							jsonPolicy, _ := json.MarshalIndent(p, "", "  ")
-							fmt.Println(string(jsonPolicy))
-						}
-					}
-				}
-			}
-
-			if invalidPolicyFound == true {
-				os.Exit(1)
+			err = validatePolicies(policies, v1crd, openAPIController, outputType)
+			if err != nil {
+				return sanitizederror.NewWithError("failed to validate policies", err)
 			}
 			return nil
 		},
@@ -133,3 +89,115 @@ func Command() *cobra.Command {
 	cmd.Flags().StringArrayVarP(&crdPaths, "crd", "c", []string{}, "Path to CRD files")
 	return cmd
 }
+
+func getPolicyFromGivenPath(policyPaths []string) (policies []*v1.ClusterPolicy, err error) {
+	var errs []error
+	if policyPaths[0] == "-" {
+		if common.IsInputFromPipe() {
+			policyStr := ""
+			scanner := bufio.NewScanner(os.Stdin)
+			for scanner.Scan() {
+				policyStr = policyStr + scanner.Text() + "\n"
+			}
+
+			yamlBytes := []byte(policyStr)
+			policies, err = utils.GetPolicy(yamlBytes)
+			if err != nil {
+				return policies, sanitizederror.NewWithError("failed to parse policy", err)
+			}
+		}
+	} else {
+		policies, errs = common.GetPolicies(policyPaths)
+		if len(errs) > 0 && len(policies) == 0 {
+			return policies, sanitizederror.NewWithErrors("failed to parse policies", errs)
+		}
+
+		if len(errs) > 0 && log.Log.V(1).Enabled() {
+			fmt.Printf("ignoring errors: \n")
+			for _, e := range errs {
+				fmt.Printf("    %v \n", e.Error())
+			}
+		}
+	}
+	return policies, nil
+}
+
+func getPolicyCRD() (v1crd apiextensions.CustomResourceDefinitionSpec, err error) {
+	if err = json.Unmarshal([]byte(crds.PolicyCRD), &v1crd); err != nil {
+		return
+	}
+	return
+}
+
+func validatePolicyAccordingToPolicyCRD(policy *v1.ClusterPolicy, v1crd apiextensions.CustomResourceDefinitionSpec) (err error, errList field.ErrorList) {
+	policyBytes, err := json.Marshal(policy)
+	if err != nil {
+		return sanitizederror.NewWithError("failed to marshal policy", err), nil
+	}
+
+	u := &unstructured.Unstructured{}
+	err = u.UnmarshalJSON(policyBytes)
+	if err != nil {
+		return sanitizederror.NewWithError("failed to decode policy", err), nil
+	}
+
+	versions := v1crd.Versions
+	for _, version := range versions {
+		validator, _, err := apiservervalidation.NewSchemaValidator(&apiextensions.CustomResourceValidation{OpenAPIV3Schema: version.Schema.OpenAPIV3Schema})
+		if err != nil {
+			return sanitizederror.NewWithError("failed to create schema validator", err), nil
+		}
+
+		errList = apiservervalidation.ValidateCustomResource(nil, u.UnstructuredContent(), validator)
+	}
+	return
+}
+
+func validatePolicies(policies []*v1.ClusterPolicy, v1crd apiextensions.CustomResourceDefinitionSpec, openAPIController *openapi.Controller, outputType string) error {
+	invalidPolicyFound := false
+	for _, policy := range policies {
+		err, errorList := validatePolicyAccordingToPolicyCRD(policy, v1crd)
+		if err != nil {
+			return sanitizederror.NewWithError("failed to validate policy.", err)
+		}
+
+		if errorList == nil {
+			err = policy2.Validate(policy, nil, true, openAPIController)
+		}
+
+		fmt.Println("----------------------------------------------------------------------")
+		if errorList != nil || err != nil {
+			fmt.Printf("Policy %s is invalid.\n", policy.Name)
+			if errorList != nil {
+				fmt.Printf("Error: invalid policy.\nCause: %s\n\n", errorList)
+			} else {
+				fmt.Printf("Error: invalid policy.\nCause: %s\n\n", err)
+			}
+			invalidPolicyFound = true
+		} else {
+			fmt.Printf("Policy %s is valid.\n\n", policy.Name)
+			if outputType != "" {
+				logger := log.Log.WithName("validate")
+				p, err := common.MutatePolicy(policy, logger)
+				if err != nil {
+					if !sanitizederror.IsErrorSanitized(err) {
+						return sanitizederror.NewWithError("failed to mutate policy.", err)
+					}
+					return err
+				}
+				if outputType == "yaml" {
+					yamlPolicy, _ := yaml.Marshal(p)
+					fmt.Println(string(yamlPolicy))
+				} else {
+					jsonPolicy, _ := json.MarshalIndent(p, "", "  ")
+					fmt.Println(string(jsonPolicy))
+				}
+			}
+		}
+	}
+
+	if invalidPolicyFound {
+		os.Exit(1)
+	}
+	return nil
+}
diff --git a/pkg/utils/util.go b/pkg/utils/util.go
index c4be1d4c4..51cf6456b 100644
--- a/pkg/utils/util.go
+++ b/pkg/utils/util.go
@@ -205,6 +205,26 @@ func SliceContains(slice []string, values ...string) bool {
 // and converts it into []kyverno.Condition or kyverno.AnyAllConditions according to its content.
 // it also helps in validating the condtions as it returns an error when the conditions are provided wrongfully by the user.
 func ApiextensionsJsonToKyvernoConditions(original apiextensions.JSON) (interface{}, error) {
+	path := "preconditions/validate.deny.conditions"
+
+	// checks for the existence any other field apart from 'any'/'all' under preconditions/validate.deny.conditions
+	unknownFieldChecker := func(jsonByteArr []byte, path string) error {
+		allowedKeys := map[string]bool{
+			"any": true,
+			"all": true,
+		}
+		var jsonDecoded map[string]interface{}
+		if err := json.Unmarshal(jsonByteArr, &jsonDecoded); err != nil {
+			return fmt.Errorf("error occurred while checking for unknown fields under %s: %+v", path, err)
+		}
+		for k := range jsonDecoded {
+			if !allowedKeys[k] {
+				return fmt.Errorf("unknown field '%s' found under %s", k, path)
+			}
+		}
+		return nil
+	}
+
 	// marshalling the abstract apiextensions.JSON back to JSON form
 	jsonByte, err := json.Marshal(original)
 
@@ -215,8 +235,12 @@ func ApiextensionsJsonToKyvernoConditions(original apiextensions.JSON) (interfac
 
 	var kyvernoAnyAllConditions kyverno.AnyAllConditions
 	if err = json.Unmarshal(jsonByte, &kyvernoAnyAllConditions); err == nil {
+		// checking if unknown fields exist or not
+		err = unknownFieldChecker(jsonByte, path)
+		if err != nil {
+			return nil, fmt.Errorf("error occurred while parsing %s: %+v", path, err)
+		}
 		return kyvernoAnyAllConditions, nil
 	}
-
-	return nil, fmt.Errorf("conditions filled wrongfully")
+	return nil, fmt.Errorf("error occurred while parsing %s: %+v", path, err)
 }
diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go
index 208ac9a9e..b6c57234c 100644
--- a/pkg/webhookconfig/registration.go
+++ b/pkg/webhookconfig/registration.go
@@ -39,6 +39,7 @@ type Register struct {
 	serverIP       string // when running outside a cluster
 	timeoutSeconds int32
 	log            logr.Logger
+	debug          bool
 }
 
 // NewRegister creates new Register instance
@@ -48,6 +49,7 @@ func NewRegister(
 	resCache resourcecache.ResourceCache,
 	serverIP string,
 	webhookTimeout int32,
+	debug bool,
 	log logr.Logger) *Register {
 	return &Register{
 		clientConfig:   clientConfig,
@@ -56,6 +58,7 @@ func NewRegister(
 		serverIP:       serverIP,
 		timeoutSeconds: webhookTimeout,
 		log:            log.WithName("Register"),
+		debug:          debug,
 	}
 }
 
@@ -65,10 +68,11 @@ func (wrc *Register) Register() error {
 	if wrc.serverIP != "" {
 		logger.Info("Registering webhook", "url", fmt.Sprintf("https://%s", wrc.serverIP))
 	}
-	if err := wrc.checkEndpoint(); err != nil {
-		return err
+	if !wrc.debug {
+		if err := wrc.checkEndpoint(); err != nil {
+			return err
+		}
 	}
-
 	wrc.removeWebhookConfigurations()
 
 	caData := wrc.readCaData()
diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go
index adadefeae..9c37a0fd8 100644
--- a/pkg/webhooks/generation.go
+++ b/pkg/webhooks/generation.go
@@ -2,6 +2,7 @@ package webhooks
 
 import (
 	contextdefault "context"
+	"encoding/json"
 	"fmt"
 	"reflect"
 	"sort"
@@ -14,10 +15,13 @@ import (
 	v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
 	"github.com/kyverno/kyverno/pkg/common"
 	"github.com/kyverno/kyverno/pkg/config"
+	client "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/engine"
 	"github.com/kyverno/kyverno/pkg/engine/context"
+	enginectx "github.com/kyverno/kyverno/pkg/engine/context"
 	"github.com/kyverno/kyverno/pkg/engine/response"
 	enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
+	"github.com/kyverno/kyverno/pkg/engine/variables"
 	"github.com/kyverno/kyverno/pkg/event"
 	gen "github.com/kyverno/kyverno/pkg/generate"
 	kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
@@ -147,27 +151,32 @@ func (ws *WebhookServer) handleUpdateTargetResource(request *v1beta1.AdmissionRe
 		if policy.GetName() == policyName {
 			for _, rule := range policy.Spec.Rules {
 				if rule.Generation.Kind == targetSourceKind && rule.Generation.Name == targetSourceName {
-					data := rule.Generation.DeepCopy().Data
-					if data != nil {
-						if _, err := gen.ValidateResourceWithPattern(logger, newRes.Object, data); err != nil {
-							enqueueBool = true
-							break
+					updatedRule, err := getGeneratedByResource(newRes, resLabels, ws.client, rule, logger)
+					if err != nil {
+						logger.V(4).Info("skipping generate policy and resource pattern validaton", "error", err)
+					} else {
+						data := updatedRule.Generation.DeepCopy().Data
+						if data != nil {
+							if _, err := gen.ValidateResourceWithPattern(logger, newRes.Object, data); err != nil {
+								enqueueBool = true
+								break
+							}
 						}
-					}
 
-					cloneName := rule.Generation.Clone.Name
-					if cloneName != "" {
-						obj, err := ws.client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
-						if err != nil {
-							logger.Error(err, fmt.Sprintf("source resource %s/%s/%s not found.", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name))
-							continue
-						}
+						cloneName := updatedRule.Generation.Clone.Name
+						if cloneName != "" {
+							obj, err := ws.client.GetResource("", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name)
+							if err != nil {
+								logger.Error(err, fmt.Sprintf("source resource %s/%s/%s not found.", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name))
+								continue
+							}
 
-						sourceObj, newResObj := stripNonPolicyFields(obj.Object, newRes.Object, logger)
+							sourceObj, newResObj := stripNonPolicyFields(obj.Object, newRes.Object, logger)
 
-						if _, err := gen.ValidateResourceWithPattern(logger, newResObj, sourceObj); err != nil {
-							enqueueBool = true
-							break
+							if _, err := gen.ValidateResourceWithPattern(logger, newResObj, sourceObj); err != nil {
+								enqueueBool = true
+								break
+							}
 						}
 					}
 				}
@@ -186,6 +195,38 @@ func (ws *WebhookServer) handleUpdateTargetResource(request *v1beta1.AdmissionRe
 	}
 }
 
+func getGeneratedByResource(newRes *unstructured.Unstructured, resLabels map[string]string, client *client.Client, rule v1.Rule, logger logr.Logger) (v1.Rule, error) {
+	var apiVersion, kind, name, namespace string
+	sourceRequest := &v1beta1.AdmissionRequest{}
+	kind = resLabels["kyverno.io/generated-by-kind"]
+	name = resLabels["kyverno.io/generated-by-name"]
+	if kind != "Namespace" {
+		namespace = resLabels["kyverno.io/generated-by-namespace"]
+	}
+	obj, err := client.GetResource(apiVersion, kind, namespace, name)
+	if err != nil {
+		logger.Error(err, "source resource not found.")
+		return rule, err
+	}
+	rawObj, err := json.Marshal(obj)
+	if err != nil {
+		logger.Error(err, "failed to marshal resource")
+		return rule, err
+	}
+	sourceRequest.Object.Raw = rawObj
+	sourceRequest.Operation = "CREATE"
+	ctx := enginectx.NewContext()
+	if err := ctx.AddRequest(sourceRequest); err != nil {
+		logger.Error(err, "failed to load incoming request in context")
+		return rule, err
+	}
+	if rule, err = variables.SubstituteAllInRule(logger, ctx, rule); err != nil {
+		logger.Error(err, "variable substitution failed for rule %s", rule.Name)
+		return rule, err
+	}
+	return rule, nil
+}
+
 //stripNonPolicyFields - remove feilds which get updated with each request by kyverno and are non policy fields
 func stripNonPolicyFields(obj, newRes map[string]interface{}, logger logr.Logger) (map[string]interface{}, map[string]interface{}) {
 
diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go
index a5993b31c..fa84b6c75 100644
--- a/pkg/webhooks/server.go
+++ b/pkg/webhooks/server.go
@@ -296,7 +296,6 @@ func writeResponse(rw http.ResponseWriter, admissionReview *v1beta1.AdmissionRev
 
 // ResourceMutation mutates resource
 func (ws *WebhookServer) ResourceMutation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
-
 	logger := ws.log.WithName("ResourceMutation").WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation)
 
 	if excludeKyvernoResources(request.Kind.Kind) {
diff --git a/pkg/webhooks/validation.go b/pkg/webhooks/validation.go
index c0f5799a9..b0eaf48bc 100644
--- a/pkg/webhooks/validation.go
+++ b/pkg/webhooks/validation.go
@@ -136,13 +136,14 @@ func HandleValidation(
 		return false, getEnforceFailureErrorMsg(engineResponses)
 	}
 
-	prInfos := policyreport.GeneratePRsFromEngineResponse(engineResponses, logger)
-	prGenerator.Add(prInfos...)
-
 	if request.Operation == v1beta1.Delete {
 		prGenerator.Add(buildDeletionPrInfo(oldR))
+		return true, ""
 	}
 
+	prInfos := policyreport.GeneratePRsFromEngineResponse(engineResponses, logger)
+	prGenerator.Add(prInfos...)
+
 	return true, ""
 }
 


Test patch:
diff --git a/pkg/engine/jmespath/functions_test.go b/pkg/engine/jmespath/functions_test.go
new file mode 100644
index 000000000..b282c3171
--- /dev/null
+++ b/pkg/engine/jmespath/functions_test.go
@@ -0,0 +1,245 @@
+package jmespath
+
+import (
+	"encoding/json"
+	"testing"
+
+	"gotest.tools/assert"
+)
+
+func TestJMESPathFunctions_CompareEqualStrings(t *testing.T) {
+	jp, err := New("compare('a', 'a')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	equal, ok := result.(int)
+	assert.Assert(t, ok)
+	assert.Equal(t, equal, 0)
+}
+
+func TestJMESPathFunctions_CompareDifferentStrings(t *testing.T) {
+	jp, err := New("compare('a', 'b')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	equal, ok := result.(int)
+	assert.Assert(t, ok)
+	assert.Equal(t, equal, -1)
+}
+
+func TestJMESPathFunctions_Contains(t *testing.T) {
+	jp, err := New("contains('string', 'str')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	contains, ok := result.(bool)
+	assert.Assert(t, ok)
+	assert.Assert(t, contains)
+}
+
+func TestJMESPathFunctions_EqualFold(t *testing.T) {
+	jp, err := New("equal_fold('Go', 'go')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	equal, ok := result.(bool)
+	assert.Assert(t, ok)
+	assert.Assert(t, equal)
+}
+
+func TestJMESPathFunctions_Replace(t *testing.T) {
+	// Can't use integer literals due to
+	// https://github.com/jmespath/go-jmespath/issues/27
+	//
+	// TODO: fix this in https://github.com/kyverno/go-jmespath
+	//
+
+	jp, err := New("replace('Lorem ipsum dolor sit amet', 'ipsum', 'muspi', `-1`)")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	replaced, ok := result.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, replaced, "Lorem muspi dolor sit amet")
+}
+
+func TestJMESPathFunctions_ReplaceAll(t *testing.T) {
+	jp, err := New("replace_all('Lorem ipsum dolor sit amet', 'ipsum', 'muspi')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	replaced, ok := result.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, replaced, "Lorem muspi dolor sit amet")
+}
+
+func TestJMESPathFunctions_ToUpper(t *testing.T) {
+	jp, err := New("to_upper('abc')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	upper, ok := result.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, upper, "ABC")
+}
+
+func TestJMESPathFunctions_ToLower(t *testing.T) {
+	jp, err := New("to_lower('AbC')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	lower, ok := result.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, lower, "abc")
+}
+
+func TestJMESPathFunctions_Trim(t *testing.T) {
+	jp, err := New("trim('¡¡¡Hello, Gophers!!!', '!¡')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	trim, ok := result.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, trim, "Hello, Gophers")
+}
+
+func TestJMESPathFunctions_Split(t *testing.T) {
+	jp, err := New("split('Hello, Gophers', ', ')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	split, ok := result.([]string)
+	assert.Assert(t, ok)
+	assert.Equal(t, split[0], "Hello")
+	assert.Equal(t, split[1], "Gophers")
+}
+
+func TestJMESPathFunctions_HasPrefix(t *testing.T) {
+	jp, err := New("starts_with('Gophers', 'Go')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	split, ok := result.(bool)
+	assert.Assert(t, ok)
+	assert.Equal(t, split, true)
+}
+
+func TestJMESPathFunctions_HasSuffix(t *testing.T) {
+	jp, err := New("ends_with('Amigo', 'go')")
+	assert.NilError(t, err)
+
+	result, err := jp.Search("")
+	assert.NilError(t, err)
+
+	split, ok := result.(bool)
+	assert.Assert(t, ok)
+	assert.Equal(t, split, true)
+}
+
+func Test_regexMatch(t *testing.T) {
+	data := make(map[string]interface{})
+	data["foo"] = "hgf'b1a2r'b12g"
+
+	query, err := New("regex_match('12.*', foo)")
+	assert.NilError(t, err)
+
+	result, err := query.Search(data)
+	assert.NilError(t, err)
+	assert.Equal(t, true, result)
+}
+
+func Test_regexMatchWithNumber(t *testing.T) {
+	data := make(map[string]interface{})
+	data["foo"] = -12.0
+
+	query, err := New("regex_match('12.*', abs(foo))")
+	assert.NilError(t, err)
+
+	result, err := query.Search(data)
+	assert.NilError(t, err)
+	assert.Equal(t, true, result)
+}
+
+func Test_regexReplaceAll(t *testing.T) {
+	resourceRaw := []byte(`
+	{
+		"metadata": {
+			"name": "temp",
+			"namespace": "ns_first"
+		},
+		"spec": {
+			"namespace": "ns_first",
+			"name": "temp_other",
+			"field" : "Hello world, helworldlo"
+		}
+	}
+	`)
+	expected := "Glo world, Gworldlo"
+
+	var resource interface{}
+	err := json.Unmarshal(resourceRaw, &resource)
+	assert.NilError(t, err)
+	query, err := New(`regex_replace_all('([Hh]e|G)l', spec.field, '${2}G')`)
+	assert.NilError(t, err)
+
+	res, err := query.Search(resource)
+	assert.NilError(t, err)
+
+	result, ok := res.(string)
+	assert.Assert(t, ok)
+	assert.Equal(t, string(result), expected)
+}
+
+func Test_regexReplaceAllLiteral(t *testing.T) {
+	resourceRaw := []byte(`
+	{
+		"metadata": {
+			"name": "temp",
+			"namespace": "ns_first"
+		},
+		"spec": {
+			"namespace": "ns_first",
+			"name": "temp_other",
+			"field" : "Hello world, helworldlo"
+		}
+	}
+	`)
+	expected := "Glo world, Gworldlo"
+
+	var resource interface{}
+	err := json.Unmarshal(resourceRaw, &resource)
+	assert.NilError(t, err)
+
+	query, err := New(`regex_replace_all_literal('[Hh]el?', spec.field, 'G')`)
+	assert.NilError(t, err)
+
+	res, err := query.Search(resource)
+	assert.NilError(t, err)
+
+	result, ok := res.(string)
+	assert.Assert(t, ok)
+
+	assert.Equal(t, string(result), expected)
+}
diff --git a/pkg/engine/mutation_test.go b/pkg/engine/mutation_test.go
index 8bd55a310..6d7f5bdb6 100644
--- a/pkg/engine/mutation_test.go
+++ b/pkg/engine/mutation_test.go
@@ -160,7 +160,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
 		JSONContext: ctx,
 		NewResource: *resourceUnstructured}
 	er := Mutate(policyContext)
-	expectedErrorStr := "variable substitution failed for rule test-path-not-exist: variable request.object.metadata.name1 not resolved at path /mutate/overlay/spec/name"
+	expectedErrorStr := "variable substitution failed for rule test-path-not-exist: NotFoundVariableErr, variable request.object.metadata.name1 not resolved at path /mutate/overlay/spec/name"
 	t.Log(er.PolicyResponse.Rules[0].Message)
 	assert.Equal(t, er.PolicyResponse.Rules[0].Message, expectedErrorStr)
 }
diff --git a/pkg/engine/validation_test.go b/pkg/engine/validation_test.go
index 1b09f3aa8..5fd4850ea 100644
--- a/pkg/engine/validation_test.go
+++ b/pkg/engine/validation_test.go
@@ -1319,9 +1319,9 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
 		JSONContext: ctx,
 		NewResource: *resourceUnstructured}
 	er := Validate(policyContext)
-	assert.Assert(t, !er.PolicyResponse.Rules[0].Success)
+	assert.Assert(t, er.PolicyResponse.Rules[0].Success)
 	assert.Equal(t, er.PolicyResponse.Rules[0].Message,
-		"variable substitution failed for rule test-path-not-exist: variable request.object.metadata.name1 not resolved at path /validate/pattern/spec/containers/0/name")
+		"variable substitution failed for rule test-path-not-exist: NotFoundVariableErr, variable request.object.metadata.name1 not resolved at path /validate/pattern/spec/containers/0/name")
 }
 
 func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSubstitutionFails(t *testing.T) {
@@ -1411,8 +1411,8 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
 		JSONContext: ctx,
 		NewResource: *resourceUnstructured}
 	er := Validate(policyContext)
-	assert.Assert(t, !er.PolicyResponse.Rules[0].Success)
-	assert.Equal(t, er.PolicyResponse.Rules[0].Message, "variable substitution failed for rule test-path-not-exist: variable request.object.metadata.name1 not resolved at path /validate/anyPattern/0/spec/template/spec/containers/0/name")
+	assert.Assert(t, er.PolicyResponse.Rules[0].Success)
+	assert.Equal(t, er.PolicyResponse.Rules[0].Message, "variable substitution failed for rule test-path-not-exist: NotFoundVariableErr, variable request.object.metadata.name1 not resolved at path /validate/anyPattern/0/spec/template/spec/containers/0/name")
 }
 
 func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
@@ -1561,8 +1561,8 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
 		JSONContext: ctx,
 		NewResource: *resourceUnstructured}
 	er := Validate(policyContext)
-	assert.Assert(t, !er.PolicyResponse.Rules[0].Success)
-	assert.Equal(t, er.PolicyResponse.Rules[0].Message, "variable substitution failed for rule test-path-not-exist: variable request.object.metadata.name1 not resolved at path /validate/anyPattern/0/spec/template/spec/containers/0/name")
+	assert.Assert(t, er.PolicyResponse.Rules[0].Success)
+	assert.Equal(t, er.PolicyResponse.Rules[0].Message, "variable substitution failed for rule test-path-not-exist: NotFoundVariableErr, variable request.object.metadata.name1 not resolved at path /validate/anyPattern/0/spec/template/spec/containers/0/name")
 }
 
 func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatternSatisfy(t *testing.T) {
@@ -1761,6 +1761,65 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
 	assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
 }
 
+func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
+	tests := []struct {
+		name            string
+		policyRaw       []byte
+		resourceRaw     []byte
+		expectedResult  bool
+		expectedMessage string
+	}{
+		{
+			name:      "path-not-present",
+			policyRaw: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"flux-multi-tenancy"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"serviceAccountName","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":".spec.serviceAccountName is required","pattern":{"spec":{"serviceAccountName":"?*"}}}},{"name":"sourceRefNamespace","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":"spec.sourceRef.namespace must be the same as metadata.namespace","deny":{"conditions":[{"key":"{{request.object.spec.sourceRef.namespace}}","operator":"NotEquals","value":"{{request.object.metadata.namespace}}"}]}}}]}}`),
+			// referred variable path not present
+			resourceRaw:     []byte(`{"apiVersion":"kustomize.toolkit.fluxcd.io/v1beta1","kind":"Kustomization","metadata":{"name":"dev-team","namespace":"apps"},"spec":{"serviceAccountName":"dev-team","interval":"5m","sourceRef":{"kind":"GitRepository","name":"dev-team"},"prune":true,"validation":"client"}}`),
+			expectedResult:  true,
+			expectedMessage: "variable substitution failed for rule sourceRefNamespace: NotFoundVariableErr, variable request.object.spec.sourceRef.namespace not resolved at path /validate/deny/conditions/0/key",
+		},
+		{
+			name:      "resource-with-violation",
+			policyRaw: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"flux-multi-tenancy"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"serviceAccountName","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":".spec.serviceAccountName is required","pattern":{"spec":{"serviceAccountName":"?*"}}}},{"name":"sourceRefNamespace","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":"spec.sourceRef.namespace {{request.object.spec.sourceRef.namespace}} must be the same as metadata.namespace {{request.object.metadata.namespace}}","deny":{"conditions":[{"key":"{{request.object.spec.sourceRef.namespace}}","operator":"NotEquals","value":"{{request.object.metadata.namespace}}"}]}}}]}}`),
+			// referred variable path present with different value
+			resourceRaw:     []byte(`{"apiVersion":"kustomize.toolkit.fluxcd.io/v1beta1","kind":"Kustomization","metadata":{"name":"dev-team","namespace":"apps"},"spec":{"serviceAccountName":"dev-team","interval":"5m","sourceRef":{"kind":"GitRepository","name":"dev-team","namespace":"default"},"prune":true,"validation":"client"}}`),
+			expectedResult:  false,
+			expectedMessage: "spec.sourceRef.namespace default must be the same as metadata.namespace apps",
+		},
+		{
+			name:      "resource-comply",
+			policyRaw: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"flux-multi-tenancy"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"serviceAccountName","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":".spec.serviceAccountName is required","pattern":{"spec":{"serviceAccountName":"?*"}}}},{"name":"sourceRefNamespace","exclude":{"resources":{"namespaces":["flux-system"]}},"match":{"resources":{"kinds":["Kustomization","HelmRelease"]}},"validate":{"message":"spec.sourceRef.namespace must be the same as metadata.namespace","deny":{"conditions":[{"key":"{{request.object.spec.sourceRef.namespace}}","operator":"NotEquals","value":"{{request.object.metadata.namespace}}"}]}}}]}}`),
+			// referred variable path present with same value - validate passes
+			resourceRaw:     []byte(`{"apiVersion":"kustomize.toolkit.fluxcd.io/v1beta1","kind":"Kustomization","metadata":{"name":"dev-team","namespace":"apps"},"spec":{"serviceAccountName":"dev-team","interval":"5m","sourceRef":{"kind":"GitRepository","name":"dev-team","namespace":"apps"},"prune":true,"validation":"client"}}`),
+			expectedResult:  true,
+			expectedMessage: "spec.sourceRef.namespace must be the same as metadata.namespace",
+		},
+	}
+
+	for _, test := range tests {
+		var policy kyverno.ClusterPolicy
+		assert.NilError(t, json.Unmarshal(test.policyRaw, &policy))
+		resourceUnstructured, err := utils.ConvertToUnstructured(test.resourceRaw)
+		assert.NilError(t, err)
+
+		ctx := context.NewContext()
+		err = ctx.AddResource(test.resourceRaw)
+		assert.NilError(t, err)
+
+		policyContext := &PolicyContext{
+			Policy:      policy,
+			JSONContext: ctx,
+			NewResource: *resourceUnstructured}
+		er := Validate(policyContext)
+
+		for i, rule := range er.PolicyResponse.Rules {
+			if rule.Name == "sourceRefNamespace" {
+				assert.Equal(t, er.PolicyResponse.Rules[i].Success, test.expectedResult)
+				assert.Equal(t, er.PolicyResponse.Rules[i].Message, test.expectedMessage, "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedMessage, rule.Message)
+			}
+		}
+	}
+}
+
 type testCase struct {
 	description   string
 	policy        []byte
diff --git a/pkg/engine/variables/vars_test.go b/pkg/engine/variables/vars_test.go
index 6b17f98be..759cdb788 100644
--- a/pkg/engine/variables/vars_test.go
+++ b/pkg/engine/variables/vars_test.go
@@ -135,6 +135,149 @@ func Test_subVars_failed(t *testing.T) {
 	}
 }
 
+func Test_subVars_with_JMESPath_At(t *testing.T) {
+	patternMap := []byte(`
+	{
+		"kind": "{{@}}",
+		"data": {
+			"rules": [
+				{
+					"apiGroups": [
+						"{{request.object.metadata.name}}"
+					],
+					"resources": [
+						"namespaces"
+					],
+					"verbs": [
+						"*"
+					],
+					"resourceNames": [
+						"{{request.object.metadata.name}}"
+					]
+				}
+			]
+		}
+	}
+	`)
+
+	resourceRaw := []byte(`
+	{
+		"kind": "foo",
+		"name": "bar",
+		"metadata": {
+			"name": "temp",
+			"namespace": "n1"
+		},
+		"spec": {
+			"namespace": "n1",
+			"name": "temp1"
+		}
+	}
+		`)
+
+	expected := []byte(`{"data":{"rules":[{"apiGroups":["temp"],"resourceNames":["temp"],"resources":["namespaces"],"verbs":["*"]}]},"kind":"foo"}`)
+
+	var pattern, resource interface{}
+	var err error
+	err = json.Unmarshal(patternMap, &pattern)
+	assert.NilError(t, err)
+	err = json.Unmarshal(resourceRaw, &resource)
+	assert.NilError(t, err)
+	// context
+	ctx := context.NewContext()
+	err = ctx.AddResource(resourceRaw)
+	assert.NilError(t, err)
+
+	output, err := SubstituteAll(log.Log, ctx, pattern)
+	assert.NilError(t, err)
+	out, err := json.Marshal(output)
+	assert.NilError(t, err)
+	assert.Equal(t, string(out), string(expected))
+}
+
+func Test_subVars_withRegexMatch(t *testing.T) {
+	patternMap := []byte(`
+	{
+		"port": "{{ regex_match('(443)', '{{@}}') }}",
+		"name": "ns-owner-{{request.object.metadata.name}}"
+	}
+	`)
+
+	resourceRaw := []byte(`
+	{
+		"port": "443",
+		"metadata": {
+			"name": "temp",
+			"namespace": "n1"
+		},
+		"spec": {
+			"namespace": "n1",
+			"name": "temp1"
+		}
+	}
+		`)
+	expected := []byte(`{"name":"ns-owner-temp","port":true}`)
+
+	var pattern, resource interface{}
+	var err error
+	err = json.Unmarshal(patternMap, &pattern)
+	assert.NilError(t, err)
+	err = json.Unmarshal(resourceRaw, &resource)
+	assert.NilError(t, err)
+	// context
+	ctx := context.NewContext()
+	err = ctx.AddResource(resourceRaw)
+	assert.NilError(t, err)
+
+	output, err := SubstituteAll(log.Log, ctx, pattern)
+	assert.NilError(t, err)
+	out, err := json.Marshal(output)
+	assert.NilError(t, err)
+	fmt.Print(string(out))
+	assert.Equal(t, string(out), string(expected))
+}
+
+func Test_subVars_withRegexReplaceAll(t *testing.T) {
+	patternMap := []byte(`
+	{
+		"port": "{{ regex_replace_all_literal('.*', '{{@}}', '1313') }}",
+		"name": "ns-owner-{{request.object.metadata.name}}"
+	}
+	`)
+
+	resourceRaw := []byte(`
+	{
+		"port": "43123",
+		"metadata": {
+			"name": "temp",
+			"namespace": "n1"
+		},
+		"spec": {
+			"namespace": "n1",
+			"name": "temp1"
+		}
+	}
+		`)
+	expected := []byte(`{"name":"ns-owner-temp","port":"1313"}`)
+
+	var pattern, resource interface{}
+	var err error
+	err = json.Unmarshal(patternMap, &pattern)
+	assert.NilError(t, err)
+	err = json.Unmarshal(resourceRaw, &resource)
+	assert.NilError(t, err)
+	// context
+	ctx := context.NewContext()
+	err = ctx.AddResource(resourceRaw)
+	assert.NilError(t, err)
+
+	output, err := SubstituteAll(log.Log, ctx, pattern)
+	assert.NilError(t, err)
+	out, err := json.Marshal(output)
+	assert.NilError(t, err)
+	assert.Equal(t, string(out), string(expected))
+}
+
 func Test_ReplacingPathWhenDeleting(t *testing.T) {
 	patternRaw := []byte(`"{{request.object.metadata.annotations.target}}"`)
 
diff --git a/pkg/kyverno/validate/commmand_test.go b/pkg/kyverno/validate/commmand_test.go
new file mode 100644
index 000000000..0f2e9c468
--- /dev/null
+++ b/pkg/kyverno/validate/commmand_test.go
@@ -0,0 +1,112 @@
+package validate
+
+import (
+	"encoding/json"
+	"fmt"
+	"testing"
+
+	kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
+	"gotest.tools/assert"
+)
+
+func Test_validateUsingPolicyCRD(t *testing.T) {
+	type TestCase struct {
+		rawPolicy   []byte
+		errorDetail string
+	}
+
+	testcases := []TestCase{
+		{
+			rawPolicy: []byte(`
+		{
+			"apiVersion": "kyverno.io/v1",
+			"kind": "ClusterPolicy",
+			"metadata": {
+			  "name": "add-requests"
+			},
+			"spec": {
+			  "rules": [
+				{
+				  "name": "Set memory and/or cpu requests for all pods in namespaces labeled 'myprivatelabel'",
+				  "match": {
+					"resources": {
+					  "kinds": [
+						"Pod"
+					  ]
+					}
+				  },
+				  "mutate": {
+					"overlay": {
+					  "spec": {
+						"containers": [
+						  {
+							"(name)": "*",
+							"resources": {
+							  "requests": {
+								"cpu": "1000m"
+							  }
+							}
+						  }
+						]
+					  }
+					}
+				  }
+				}
+			  ]
+			}
+		  }
+		`),
+			errorDetail: "spec.rules.name in body should be at most 63 chars long",
+		},
+		{
+			rawPolicy: []byte(`
+				{
+					"apiVersion": "kyverno.io/v1",
+					"kind": "ClusterPolicy",
+					"metadata": {
+					  "name": "min-replicas-clusterpolicy"
+					},
+					"spec": {
+					  "validationFailureAction": "audit",
+					  "rules": [
+						{
+						  "name": "check-min-replicas",
+						  "match": {
+							"resources": {
+							  "kinds": [
+								"Deployment"
+							  ]
+							}
+						  },
+						  "validate": {
+							"message": "should have at least 2 replicas",
+							"pattern": {
+							  "spec": {
+								"replicas": 2
+							  }
+							}
+						  }
+						}
+					  ]
+					}
+				  }
+		`),
+			errorDetail: "",
+		},
+	}
+
+	v1crd, err := getPolicyCRD()
+	assert.NilError(t, err)
+
+	var policy kyverno.ClusterPolicy
+	for _, tc := range testcases {
+		err = json.Unmarshal(tc.rawPolicy, &policy)
+		assert.NilError(t, err)
+
+		_, errorList := validatePolicyAccordingToPolicyCRD(&policy, v1crd)
+		fmt.Println("errorList:  ", errorList)
+		for _, e := range errorList {
+			assert.Assert(t, tc.errorDetail == e.Detail)
+		}
+	}
+}