Repository: kyverno/kyverno
Pull request #1716 (2021-03-16 18:42:32)

Change isNotIn
Signed-off-by: Joshua Snider <jsnider@mtu.edu>

## Related issue
#1689 

## What type of PR is this
/kind bug

## Proposed changes
Change isNotIn to return true if any element of key is not found in value.

## Checklist

- [x] I have read the [contributing guidelines](https://github.com/kyverno/kyverno/blob/main/CONTRIBUTING.md).
- [x] I have added tests that prove my fix is effective or that my feature works.
- [] I have added or changed [the documentation](https://github.com/kyverno/website).
  - If not, I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update:



Patch:
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6ee986481..874b6e55e 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -41,9 +41,6 @@ them, don't hesitate to ask. We're here to help! This is simply a reminder of wh
 - [] 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.
 - [] I have added or changed [the documentation](https://github.com/kyverno/website).
-  - If not, I have raised an issue in [kyverno/website](https://github.com/kyverno/website) to track the doc update:
-  <!-- Uncomment to link to the issue -->
-  <!-- https://github.com/kyverno/website/issues/1 -->
 
 ## Further comments
 
diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go
index 4f0dc8986..7e09ecff8 100644
--- a/cmd/initContainer/main.go
+++ b/cmd/initContainer/main.go
@@ -10,6 +10,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/kyverno/kyverno/pkg/config"
 	client "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/signal"
 	"github.com/kyverno/kyverno/pkg/utils"
@@ -27,6 +28,8 @@ var (
 )
 
 const (
+	mutatingWebhookConfigKind      string = "MutatingWebhookConfiguration"
+	validatingWebhookConfigKind    string = "ValidatingWebhookConfiguration"
 	policyReportKind               string = "PolicyReport"
 	clusterPolicyReportKind        string = "ClusterPolicyReport"
 	reportChangeRequestKind        string = "ReportChangeRequest"
@@ -69,6 +72,16 @@ func main() {
 	}
 
 	requests := []request{
+		{validatingWebhookConfigKind, config.ValidatingWebhookConfigurationName},
+		{validatingWebhookConfigKind, config.ValidatingWebhookConfigurationDebugName},
+		{mutatingWebhookConfigKind, config.MutatingWebhookConfigurationName},
+		{mutatingWebhookConfigKind, config.MutatingWebhookConfigurationDebugName},
+
+		{validatingWebhookConfigKind, config.PolicyValidatingWebhookConfigurationName},
+		{validatingWebhookConfigKind, config.PolicyValidatingWebhookConfigurationDebugName},
+		{mutatingWebhookConfigKind, config.PolicyMutatingWebhookConfigurationName},
+		{mutatingWebhookConfigKind, config.PolicyMutatingWebhookConfigurationDebugName},
+
 		{policyReportKind, ""},
 		{clusterPolicyReportKind, ""},
 
@@ -107,6 +120,8 @@ func main() {
 
 func executeRequest(client *client.Client, req request) error {
 	switch req.kind {
+	case mutatingWebhookConfigKind, validatingWebhookConfigKind:
+		return removeWebhookIfExists(client, req.kind, req.name)
 	case policyReportKind:
 		return removePolicyReport(client, req.kind)
 	case clusterPolicyReportKind:
@@ -221,6 +236,29 @@ func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan err
 	return out
 }
 
+func removeWebhookIfExists(client *client.Client, kind string, name string) error {
+	logger := log.Log.WithName("removeExistingWebhook").WithValues("kind", kind, "name", name)
+	var err error
+	// Get resource
+	_, err = client.GetResource("", kind, "", name)
+	if errors.IsNotFound(err) {
+		logger.V(4).Info("resource not found")
+		return nil
+	}
+	if err != nil {
+		logger.Error(err, "failed to get resource")
+		return err
+	}
+	// Delete resource
+	err = client.DeleteResource("", kind, "", name, false)
+	if err != nil {
+		logger.Error(err, "failed to delete resource")
+		return err
+	}
+	logger.Info("removed the resource")
+	return nil
+}
+
 func removeClusterPolicyReport(client *client.Client, kind string) error {
 	logger := log.Log.WithName("removeClusterPolicyReport")
 
diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index 01ab10270..61e8548ac 100755
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -24,7 +24,6 @@ import (
 	"github.com/kyverno/kyverno/pkg/policystatus"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
 	"github.com/kyverno/kyverno/pkg/signal"
-	ktls "github.com/kyverno/kyverno/pkg/tls"
 	"github.com/kyverno/kyverno/pkg/utils"
 	"github.com/kyverno/kyverno/pkg/version"
 	"github.com/kyverno/kyverno/pkg/webhookconfig"
@@ -145,7 +144,7 @@ func main() {
 		log.Log)
 
 	// Resource Mutating Webhook Watcher
-	webhookMonitor := webhookconfig.NewMonitor(rCache, log.Log.WithName("WebhookMonitor"))
+	webhookMonitor := webhookconfig.NewMonitor(log.Log.WithName("WebhookMonitor"))
 
 	// KYVERNO CRD INFORMER
 	// watches CRD resources:
@@ -284,9 +283,8 @@ func main() {
 		client,
 	)
 
-	certRenewer := ktls.NewCertRenewer(client, clientConfig, ktls.CertRenewalInterval, ktls.CertValidityDuration, log.Log.WithName("CertRenewer"))
 	// Configure certificates
-	tlsPair, err := certRenewer.InitTLSPemPair(serverIP)
+	tlsPair, err := client.InitTLSPemPair(clientConfig, serverIP)
 	if err != nil {
 		setupLog.Error(err, "Failed to initialize TLS key/certificate pair")
 		os.Exit(1)
@@ -331,7 +329,6 @@ func main() {
 		pCacheController.Cache,
 		webhookCfg,
 		webhookMonitor,
-		certRenewer,
 		statusSync.Listener,
 		configData,
 		reportReqGen,
diff --git a/pkg/dclient/certificates.go b/pkg/dclient/certificates.go
new file mode 100644
index 000000000..784fa5c94
--- /dev/null
+++ b/pkg/dclient/certificates.go
@@ -0,0 +1,243 @@
+package client
+
+import (
+	"encoding/base64"
+	"fmt"
+	"net/url"
+
+	"github.com/kyverno/kyverno/pkg/config"
+	tls "github.com/kyverno/kyverno/pkg/tls"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/client-go/rest"
+)
+
+// InitTLSPemPair Loads or creates PEM private key and TLS certificate for webhook server.
+// Created pair is stored in cluster's secret.
+// Returns struct with key/certificate pair.
+func (c *Client) InitTLSPemPair(configuration *rest.Config, serverIP string) (*tls.PemPair, error) {
+	logger := c.log
+	certProps, err := c.GetTLSCertProps(configuration)
+	if err != nil {
+		return nil, err
+	}
+
+	logger.Info("Building key/certificate pair for TLS")
+	tlsPair, err := c.buildTLSPemPair(certProps, serverIP)
+	if err != nil {
+		return nil, err
+	}
+	if err = c.WriteTLSPairToSecret(certProps, tlsPair); err != nil {
+		return nil, fmt.Errorf("Unable to save TLS pair to the cluster: %v", err)
+	}
+
+	return tlsPair, nil
+}
+
+// buildTLSPemPair Issues TLS certificate for webhook server using self-signed CA cert
+// Returns signed and approved TLS certificate in PEM format
+func (c *Client) buildTLSPemPair(props tls.CertificateProps, serverIP string) (*tls.PemPair, error) {
+	caCert, caPEM, err := tls.GenerateCACert()
+	if err != nil {
+		return nil, err
+	}
+
+	if err := c.WriteCACertToSecret(caPEM, props); err != nil {
+		return nil, fmt.Errorf("failed to write CA cert to secret: %v", err)
+	}
+
+	return tls.GenerateCertPem(caCert, props, serverIP)
+}
+
+//ReadRootCASecret returns the RootCA from the pre-defined secret
+func (c *Client) ReadRootCASecret() (result []byte) {
+	logger := c.log.WithName("ReadRootCASecret")
+	certProps, err := c.GetTLSCertProps(c.clientConfig)
+	if err != nil {
+		logger.Error(err, "failed to get TLS Cert Properties")
+		return result
+	}
+	sname := generateRootCASecretName(certProps)
+	stlsca, err := c.GetResource("", Secrets, certProps.Namespace, sname)
+	if err != nil {
+		return result
+	}
+	tlsca, err := convertToSecret(stlsca)
+	if err != nil {
+		logger.Error(err, "failed to convert secret", "name", sname, "namespace", certProps.Namespace)
+		return result
+	}
+
+	result = tlsca.Data[rootCAKey]
+	if len(result) == 0 {
+		logger.Info("root CA certificate not found in secret", "name", tlsca.Name, "namespace", certProps.Namespace)
+		return result
+	}
+	logger.V(4).Info("using CA bundle defined in secret to validate the webhook's server certificate", "name", tlsca.Name, "namespace", certProps.Namespace)
+	return result
+}
+
+const selfSignedAnnotation string = "self-signed-cert"
+const rootCAKey string = "rootCA.crt"
+
+// ReadTLSPair Reads the pair of TLS certificate and key from the specified secret.
+func (c *Client) ReadTLSPair(props tls.CertificateProps) *tls.PemPair {
+	logger := c.log.WithName("ReadTLSPair")
+	sname := generateTLSPairSecretName(props)
+	unstrSecret, err := c.GetResource("", Secrets, props.Namespace, sname)
+	if err != nil {
+		logger.Error(err, "Failed to get secret", "name", sname, "namespace", props.Namespace)
+		return nil
+	}
+
+	// If secret contains annotation 'self-signed-cert', then it's created using helper scripts to setup self-signed certificates.
+	// As the root CA used to sign the certificate is required for webhook cnofiguration, check if the corresponding secret is created
+	annotations := unstrSecret.GetAnnotations()
+	if _, ok := annotations[selfSignedAnnotation]; ok {
+		sname := generateRootCASecretName(props)
+		_, err := c.GetResource("", Secrets, props.Namespace, sname)
+		if err != nil {
+			logger.Error(err, "Root CA secret is required while using self-signed certificates TLS pair, defaulting to generating new TLS pair", "name", sname, "namespace", props.Namespace)
+			return nil
+		}
+	}
+	secret, err := convertToSecret(unstrSecret)
+	if err != nil {
+		return nil
+	}
+	pemPair := tls.PemPair{
+		Certificate: secret.Data[v1.TLSCertKey],
+		PrivateKey:  secret.Data[v1.TLSPrivateKeyKey],
+	}
+	if len(pemPair.Certificate) == 0 {
+		logger.Info("TLS Certificate not found in secret", "name", sname, "namespace", props.Namespace)
+		return nil
+	}
+	if len(pemPair.PrivateKey) == 0 {
+		logger.Info("TLS PrivateKey not found in secret", "name", sname, "namespace", props.Namespace)
+		return nil
+	}
+	return &pemPair
+}
+
+// WriteCACertToSecret stores the CA cert in secret
+func (c *Client) WriteCACertToSecret(caPEM *tls.PemPair, props tls.CertificateProps) error {
+	logger := c.log.WithName("CAcert")
+	name := generateRootCASecretName(props)
+
+	secretUnstr, err := c.GetResource("", Secrets, props.Namespace, name)
+	if err != nil {
+		secret := &v1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      name,
+				Namespace: props.Namespace,
+				Annotations: map[string]string{
+					selfSignedAnnotation: "true",
+				},
+			},
+			Data: map[string][]byte{
+				rootCAKey: caPEM.Certificate,
+			},
+			Type: v1.SecretTypeOpaque,
+		}
+
+		_, err := c.CreateResource("", Secrets, props.Namespace, secret, false)
+		if err == nil {
+			logger.Info("secret created", "name", name, "namespace", props.Namespace)
+		}
+		return err
+	}
+
+	if _, ok := secretUnstr.GetAnnotations()[selfSignedAnnotation]; !ok {
+		secretUnstr.SetAnnotations(map[string]string{selfSignedAnnotation: "true"})
+	}
+
+	dataMap := map[string]interface{}{
+		rootCAKey: base64.StdEncoding.EncodeToString(caPEM.Certificate)}
+
+	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
+		return err
+	}
+
+	_, err = c.UpdateResource("", Secrets, props.Namespace, secretUnstr, false)
+	if err != nil {
+		return err
+	}
+	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
+	return nil
+}
+
+// WriteTLSPairToSecret Writes the pair of TLS certificate and key to the specified secret.
+// Updates existing secret or creates new one.
+func (c *Client) WriteTLSPairToSecret(props tls.CertificateProps, pemPair *tls.PemPair) error {
+	logger := c.log.WithName("WriteTLSPair")
+	name := generateTLSPairSecretName(props)
+	secretUnstr, err := c.GetResource("", Secrets, props.Namespace, name)
+	if err != nil {
+		secret := &v1.Secret{
+			TypeMeta: metav1.TypeMeta{
+				Kind:       "Secret",
+				APIVersion: "v1",
+			},
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      name,
+				Namespace: props.Namespace,
+			},
+			Data: map[string][]byte{
+				v1.TLSCertKey:       pemPair.Certificate,
+				v1.TLSPrivateKeyKey: pemPair.PrivateKey,
+			},
+			Type: v1.SecretTypeTLS,
+		}
+
+		_, err := c.CreateResource("", Secrets, props.Namespace, secret, false)
+		if err == nil {
+			logger.Info("secret created", "name", name, "namespace", props.Namespace)
+		}
+		return err
+	}
+
+	dataMap := map[string]interface{}{
+		v1.TLSCertKey:       base64.StdEncoding.EncodeToString(pemPair.Certificate),
+		v1.TLSPrivateKeyKey: base64.StdEncoding.EncodeToString(pemPair.PrivateKey),
+	}
+
+	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
+		return err
+	}
+
+	_, err = c.UpdateResource("", Secrets, props.Namespace, secretUnstr, false)
+	if err != nil {
+		return err
+	}
+
+	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
+	return nil
+}
+
+func generateTLSPairSecretName(props tls.CertificateProps) string {
+	return tls.GenerateInClusterServiceName(props) + ".kyverno-tls-pair"
+}
+
+func generateRootCASecretName(props tls.CertificateProps) string {
+	return tls.GenerateInClusterServiceName(props) + ".kyverno-tls-ca"
+}
+
+//GetTLSCertProps provides the TLS Certificate Properties
+func (c *Client) GetTLSCertProps(configuration *rest.Config) (certProps tls.CertificateProps, err error) {
+	apiServerURL, err := url.Parse(configuration.Host)
+	if err != nil {
+		return certProps, err
+	}
+	certProps = tls.CertificateProps{
+		Service:       config.KyvernoServiceName,
+		Namespace:     config.KyvernoNamespace,
+		APIServerHost: apiServerURL.Hostname(),
+	}
+	return certProps, nil
+}
diff --git a/pkg/dclient/client.go b/pkg/dclient/client.go
index cbd31c42e..3fa1cf66b 100644
--- a/pkg/dclient/client.go
+++ b/pkg/dclient/client.go
@@ -9,6 +9,7 @@ import (
 	"github.com/go-logr/logr"
 	openapiv2 "github.com/googleapis/gnostic/openapiv2"
 	certificates "k8s.io/api/certificates/v1beta1"
+	v1 "k8s.io/api/core/v1"
 	helperv1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -197,6 +198,15 @@ func convertToUnstructured(obj interface{}) *unstructured.Unstructured {
 	return &unstructured.Unstructured{Object: unstructuredObj}
 }
 
+//To-Do remove this to use unstructured type
+func convertToSecret(obj *unstructured.Unstructured) (v1.Secret, error) {
+	secret := v1.Secret{}
+	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &secret); err != nil {
+		return secret, err
+	}
+	return secret, nil
+}
+
 //To-Do remove this to use unstructured type
 func convertToCSR(obj *unstructured.Unstructured) (*certificates.CertificateSigningRequest, error) {
 	csr := certificates.CertificateSigningRequest{}
diff --git a/pkg/dclient/utils.go b/pkg/dclient/utils.go
index 6b6dc19b0..d4cf657eb 100644
--- a/pkg/dclient/utils.go
+++ b/pkg/dclient/utils.go
@@ -15,6 +15,17 @@ import (
 	kubernetesfake "k8s.io/client-go/kubernetes/fake"
 )
 
+const (
+	// CSRs CertificateSigningRequest
+	CSRs string = "CertificateSigningRequest"
+	// Secrets Secret
+	Secrets string = "Secret"
+	// ConfigMaps ConfigMap
+	ConfigMaps string = "ConfigMap"
+	// Namespaces Namespace
+	Namespaces string = "Namespace"
+)
+
 //NewMockClient ---testing utilities
 func NewMockClient(scheme *runtime.Scheme, gvrToListKind map[schema.GroupVersionResource]string, objects ...runtime.Object) (*Client, error) {
 	client := fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...)
diff --git a/pkg/engine/variables/operator/in.go b/pkg/engine/variables/operator/in.go
index bd510e101..87e74b935 100644
--- a/pkg/engine/variables/operator/in.go
+++ b/pkg/engine/variables/operator/in.go
@@ -180,7 +180,7 @@ func isIn(key []string, value []string) bool {
 	return true
 }
 
-// isNotIn checks if none of the values in S1 is in S2
+// isNotIn checks if any of the values in S1 is not in S2
 func isNotIn(key []string, value []string) bool {
 	set := make(map[string]bool)
 
@@ -190,12 +190,12 @@ func isNotIn(key []string, value []string) bool {
 
 	for _, val := range key {
 		_, found := set[val]
-		if found {
-			return false
+		if !found {
+			return true
 		}
 	}
 
-	return true
+	return false
 }
 
 func (in InHandler) validateValueWithBoolPattern(_ bool, _ interface{}) bool {
diff --git a/pkg/resourcecache/gvrcache.go b/pkg/resourcecache/gvrcache.go
index befc315a8..8d8d76d0c 100644
--- a/pkg/resourcecache/gvrcache.go
+++ b/pkg/resourcecache/gvrcache.go
@@ -4,7 +4,6 @@ import (
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/dynamic/dynamiclister"
 	"k8s.io/client-go/informers"
-	"k8s.io/client-go/tools/cache"
 )
 
 // GenericCache - allows operation on a single resource
@@ -14,7 +13,6 @@ type GenericCache interface {
 	Lister() dynamiclister.Lister
 	NamespacedLister(namespace string) dynamiclister.NamespaceLister
 	GVR() schema.GroupVersionResource
-	GetInformer() cache.SharedIndexInformer
 }
 
 type genericCache struct {
@@ -58,8 +56,3 @@ func (gc *genericCache) Lister() dynamiclister.Lister {
 func (gc *genericCache) NamespacedLister(namespace string) dynamiclister.NamespaceLister {
 	return dynamiclister.New(gc.genericInformer.Informer().GetIndexer(), gc.GVR()).Namespace(namespace)
 }
-
-// GetInformer gets SharedIndexInformer
-func (gc *genericCache) GetInformer() cache.SharedIndexInformer {
-	return gc.genericInformer.Informer()
-}
diff --git a/pkg/resourcecache/main.go b/pkg/resourcecache/main.go
index f8cc3c5f1..b902c2f94 100644
--- a/pkg/resourcecache/main.go
+++ b/pkg/resourcecache/main.go
@@ -10,15 +10,11 @@ import (
 )
 
 // ResourceCache - allows the creation, deletion and saving the resource informers as a cache
-// the resource cache can be registered by gvks as follows:
-// - group/version/kind
-// - group/kind
-// - kind
 type ResourceCache interface {
-	CreateInformers(gvks ...string) []error
-	CreateGVKInformer(gvk string) (GenericCache, error)
-	StopResourceInformer(gvk string)
-	GetGVRCache(gvk string) (GenericCache, bool)
+	CreateInformers(resources ...string) []error
+	CreateGVKInformer(kind string) (GenericCache, error)
+	StopResourceInformer(resource string)
+	GetGVRCache(resource string) (GenericCache, bool)
 }
 
 type resourceCache struct {
diff --git a/pkg/tls/certRenewer.go b/pkg/tls/certRenewer.go
deleted file mode 100644
index f4cb20581..000000000
--- a/pkg/tls/certRenewer.go
+++ /dev/null
@@ -1,348 +0,0 @@
-package tls
-
-import (
-	"crypto/tls"
-	"crypto/x509"
-	"encoding/base64"
-	"encoding/pem"
-	"fmt"
-	"time"
-
-	"github.com/cenkalti/backoff"
-	"github.com/go-logr/logr"
-	"github.com/kyverno/kyverno/pkg/config"
-	client "github.com/kyverno/kyverno/pkg/dclient"
-	"github.com/pkg/errors"
-	v1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/client-go/rest"
-)
-
-const (
-	// ManagedByLabel is added to Kyverno managed secrets
-	ManagedByLabel string = "cert.kyverno.io/managed-by"
-
-	SelfSignedAnnotation    string = "self-signed-cert"
-	RootCAKey               string = "rootCA.crt"
-	rollingUpdateAnnotation string = "update.kyverno.io/force-rolling-update"
-)
-
-// CertRenewer creates rootCA and pem pair to register
-// webhook configurations and webhook server
-// renews RootCA at the given interval
-type CertRenewer struct {
-	client               *client.Client
-	clientConfig         *rest.Config
-	certRenewalInterval  time.Duration
-	certValidityDuration time.Duration
-	log                  logr.Logger
-}
-
-// NewCertRenewer returns an instance of CertRenewer
-func NewCertRenewer(client *client.Client, clientConfig *rest.Config, certRenewalInterval, certValidityDuration time.Duration, log logr.Logger) *CertRenewer {
-	return &CertRenewer{
-		client:               client,
-		clientConfig:         clientConfig,
-		certRenewalInterval:  certRenewalInterval,
-		certValidityDuration: certValidityDuration,
-		log:                  log,
-	}
-}
-
-// InitTLSPemPair Loads or creates PEM private key and TLS certificate for webhook server.
-// Created pair is stored in cluster's secret.
-// Returns struct with key/certificate pair.
-func (c *CertRenewer) InitTLSPemPair(serverIP string) (*PemPair, error) {
-	logger := c.log.WithName("InitTLSPemPair")
-	certProps, err := GetTLSCertProps(c.clientConfig)
-	if err != nil {
-		return nil, err
-	}
-
-	if valid, err := c.ValidCert(); err == nil && valid {
-		if tlsPair, err := ReadTLSPair(c.clientConfig, c.client); err == nil {
-			logger.Info("using existing TLS key/certificate pair")
-			return tlsPair, nil
-		}
-	} else {
-		logger.V(3).Info("unable to find TLS pair", "reason", err.Error())
-	}
-
-	logger.Info("building key/certificate pair for TLS")
-	return c.buildTLSPemPairAndWriteToSecrets(certProps, serverIP)
-}
-
-// buildTLSPemPairAndWriteToSecrets Issues TLS certificate for webhook server using self-signed CA cert
-// Returns signed and approved TLS certificate in PEM format
-func (c *CertRenewer) buildTLSPemPairAndWriteToSecrets(props CertificateProps, serverIP string) (*PemPair, error) {
-	caCert, caPEM, err := GenerateCACert(c.certValidityDuration)
-	if err != nil {
-		return nil, err
-	}
-
-	if err := c.WriteCACertToSecret(caPEM, props); err != nil {
-		return nil, fmt.Errorf("failed to write CA cert to secret: %v", err)
-	}
-
-	tlsPair, err := GenerateCertPem(caCert, props, serverIP, c.certValidityDuration)
-	if err != nil {
-		return nil, err
-	}
-
-	if err = c.WriteTLSPairToSecret(props, tlsPair); err != nil {
-		return nil, fmt.Errorf("unable to save TLS pair to the cluster: %v", err)
-	}
-
-	return tlsPair, nil
-}
-
-// ReadTLSPair Reads the pair of TLS certificate and key from the specified secret.
-
-// WriteCACertToSecret stores the CA cert in secret
-func (c *CertRenewer) WriteCACertToSecret(caPEM *PemPair, props CertificateProps) error {
-	logger := c.log.WithName("CAcert")
-	name := generateRootCASecretName(props)
-
-	secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
-	if err != nil {
-		secret := &v1.Secret{
-			TypeMeta: metav1.TypeMeta{
-				Kind:       "Secret",
-				APIVersion: "v1",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      name,
-				Namespace: props.Namespace,
-				Annotations: map[string]string{
-					SelfSignedAnnotation: "true",
-				},
-				Labels: map[string]string{
-					ManagedByLabel: "kyverno",
-				},
-			},
-			Data: map[string][]byte{
-				RootCAKey: caPEM.Certificate,
-			},
-			Type: v1.SecretTypeOpaque,
-		}
-
-		_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
-		if err == nil {
-			logger.Info("secret created", "name", name, "namespace", props.Namespace)
-		}
-		return err
-	}
-
-	if _, ok := secretUnstr.GetAnnotations()[SelfSignedAnnotation]; !ok {
-		secretUnstr.SetAnnotations(map[string]string{SelfSignedAnnotation: "true"})
-	}
-
-	dataMap := map[string]interface{}{
-		RootCAKey: base64.StdEncoding.EncodeToString(caPEM.Certificate)}
-
-	if err := unstructured.SetNestedMap(secretUnstr.Object, dataMap, "data"); err != nil {
-		return err
-	}
-
-	_, err = c.client.UpdateResource("", "Secret", props.Namespace, secretUnstr, false)
-	if err != nil {
-		return err
-	}
-	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
-	return nil
-}
-
-// WriteTLSPairToSecret Writes the pair of TLS certificate and key to the specified secret.
-// Updates existing secret or creates new one.
-func (c *CertRenewer) WriteTLSPairToSecret(props CertificateProps, pemPair *PemPair) error {
-	logger := c.log.WithName("WriteTLSPair")
-
-	name := generateTLSPairSecretName(props)
-	secretUnstr, err := c.client.GetResource("", "Secret", props.Namespace, name)
-	if err != nil {
-		secret := &v1.Secret{
-			TypeMeta: metav1.TypeMeta{
-				Kind:       "Secret",
-				APIVersion: "v1",
-			},
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      name,
-				Namespace: props.Namespace,
-				Labels: map[string]string{
-					ManagedByLabel: "kyverno",
-				},
-			},
-			Data: map[string][]byte{
-				v1.TLSCertKey:       pemPair.Certificate,
-				v1.TLSPrivateKeyKey: pemPair.PrivateKey,
-			},
-			Type: v1.SecretTypeTLS,
-		}
-
-		_, err := c.client.CreateResource("", "Secret", props.Namespace, secret, false)
-		if err == nil {
-			logger.Info("secret created", "name", name, "namespace", props.Namespace)
-		}
-		return err
-	}
-
-	dataMap := map[string][]byte{
-		v1.TLSCertKey:       pemPair.Certificate,
-		v1.TLSPrivateKeyKey: pemPair.PrivateKey,
-	}
-
-	secret, err := convertToSecret(secretUnstr)
-	if err != nil {
-		return err
-	}
-
-	secret.Data = dataMap
-	_, err = c.client.UpdateResource("", "Secret", props.Namespace, secret, false)
-	if err != nil {
-		return err
-	}
-
-	logger.Info("secret updated", "name", name, "namespace", props.Namespace)
-	return nil
-}
-
-// RollingUpdate triggers a rolling update of Kyverno pod.
-// It is used when the rootCA is renewed, the restart of
-// Kyverno pod will register webhook server with new cert
-func (c *CertRenewer) RollingUpdate() error {
-
-	update := func() error {
-		deploy, err := c.client.GetResource("", "Deployment", config.KyvernoNamespace, config.KyvernoDeploymentName)
-		if err != nil {
-			return errors.Wrap(err, "failed to find Kyverno")
-		}
-
-		if IsKyvernoIsInRollingUpdate(deploy.UnstructuredContent(), c.log) {
-			return nil
-		}
-
-		annotations, ok, err := unstructured.NestedStringMap(deploy.UnstructuredContent(), "spec", "template", "metadata", "annotations")
-		if err != nil {
-			return errors.Wrap(err, "bad annotations")
-		}
-
-		if !ok {
-			annotations = map[string]string{}
-		}
-
-		annotations[rollingUpdateAnnotation] = time.Now().String()
-		if err = unstructured.SetNestedStringMap(deploy.UnstructuredContent(),
-			annotations,
-			"spec", "template", "metadata", "annotations",
-		); err != nil {
-			return errors.Wrapf(err, "set annotation %s", rollingUpdateAnnotation)
-		}
-
-		if _, err = c.client.UpdateResource("", "Deployment", config.KyvernoNamespace, deploy, false); err != nil {
-			return errors.Wrap(err, "update Kyverno deployment")
-		}
-		return nil
-	}
-
-	exbackoff := &backoff.ExponentialBackOff{
-		InitialInterval:     500 * time.Millisecond,
-		RandomizationFactor: 0.5,
-		Multiplier:          1.5,
-		MaxInterval:         time.Second,
-		MaxElapsedTime:      3 * time.Second,
-		Clock:               backoff.SystemClock,
-	}
-
-	exbackoff.Reset()
-	return backoff.Retry(update, exbackoff)
-}
-
-// ValidCert validates the CA Cert
-func (c *CertRenewer) ValidCert() (bool, error) {
-	logger := c.log.WithName("ValidCert")
-
-	rootCA, err := ReadRootCASecret(c.clientConfig, c.client)
-	if err != nil {
-		return false, errors.Wrap(err, "unable to read CA from secret")
-	}
-
-	tlsPair, err := ReadTLSPair(c.clientConfig, c.client)
-	if err != nil {
-		// wait till next reconcile
-		logger.Info("unable to read TLS PEM Pair from secret", "reason", err.Error())
-		return false, errors.Wrap(err, "unable to read TLS PEM Pair from secret")
-	}
-
-	// build cert pool
-	pool := x509.NewCertPool()
-	caPem, _ := pem.Decode(rootCA)
-	if caPem == nil {
-		logger.Error(err, "bad certificate")
-		return false, nil
-	}
-
-	cac, err := x509.ParseCertificate(caPem.Bytes)
-	if err != nil {
-		logger.Error(err, "failed to parse CA cert")
-		return false, nil
-	}
-	pool.AddCert(cac)
-
-	// valid PEM pair
-	_, err = tls.X509KeyPair(tlsPair.Certificate, tlsPair.PrivateKey)
-	if err != nil {
-		logger.Error(err, "invalid PEM pair")
-		return false, nil
-	}
-
-	certPem, _ := pem.Decode(tlsPair.Certificate)
-	if certPem == nil {
-		logger.Error(err, "bad private key")
-		return false, nil
-	}
-
-	cert, err := x509.ParseCertificate(certPem.Bytes)
-	if err != nil {
-		logger.Error(err, "failed to parse cert")
-		return false, nil
-	}
-
-	if _, err = cert.Verify(x509.VerifyOptions{
-		Roots:       pool,
-		CurrentTime: time.Now().Add(c.certRenewalInterval),
-	}); err != nil {
-		logger.Error(err, "invalid cert")
-		return false, nil
-	}
-
-	return true, nil
-}
-
-// IsKyvernoIsInRollingUpdate returns true if Kyverno is in rolling update
-func IsKyvernoIsInRollingUpdate(deploy map[string]interface{}, logger logr.Logger) bool {
-	replicas, _, err := unstructured.NestedInt64(deploy, "spec", "replicas")
-	if err != nil {
-		logger.Error(err, "unable to fetch spec.replicas")
-	}
-
-	nonTerminatedReplicas, _, err := unstructured.NestedInt64(deploy, "status", "replicas")
-	if err != nil {
-		logger.Error(err, "unable to fetch status.replicas")
-	}
-
-	if nonTerminatedReplicas > replicas {
-		logger.Info("detect Kyverno is in rolling update, won't trigger the update again")
-		return true
-	}
-
-	return false
-}
-
-func generateTLSPairSecretName(props CertificateProps) string {
-	return generateInClusterServiceName(props) + ".kyverno-tls-pair"
-}
-
-func generateRootCASecretName(props CertificateProps) string {
-	return generateInClusterServiceName(props) + ".kyverno-tls-ca"
-}
diff --git a/pkg/tls/reader.go b/pkg/tls/reader.go
deleted file mode 100644
index 4ddebc9a2..000000000
--- a/pkg/tls/reader.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package tls
-
-import (
-	"fmt"
-	"net/url"
-
-	"github.com/kyverno/kyverno/pkg/config"
-	client "github.com/kyverno/kyverno/pkg/dclient"
-	"github.com/pkg/errors"
-	v1 "k8s.io/api/core/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/rest"
-)
-
-// ReadRootCASecret returns the RootCA from the pre-defined secret
-func ReadRootCASecret(restConfig *rest.Config, client *client.Client) (result []byte, err error) {
-	certProps, err := GetTLSCertProps(restConfig)
-	if err != nil {
-		return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
-	}
-
-	sname := generateRootCASecretName(certProps)
-	stlsca, err := client.GetResource("", "Secret", certProps.Namespace, sname)
-	if err != nil {
-		return nil, err
-	}
-
-	tlsca, err := convertToSecret(stlsca)
-	if err != nil {
-		return nil, errors.Wrapf(err, "failed to convert secret %s/%s", certProps.Namespace, sname)
-	}
-
-	result = tlsca.Data[RootCAKey]
-	if len(result) == 0 {
-		return nil, errors.Errorf("root CA certificate not found in secret %s/%s", certProps.Namespace, tlsca.Name)
-	}
-
-	return result, nil
-}
-
-// ReadTLSPair returns the pem pair from the pre-defined secret
-func ReadTLSPair(restConfig *rest.Config, client *client.Client) (*PemPair, error) {
-	certProps, err := GetTLSCertProps(restConfig)
-	if err != nil {
-		return nil, errors.Wrap(err, "failed to get TLS Cert Properties")
-	}
-
-	sname := generateTLSPairSecretName(certProps)
-	unstrSecret, err := client.GetResource("", "Secret", certProps.Namespace, sname)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get secret %s/%s: %v", certProps.Namespace, sname, err)
-	}
-
-	// If secret contains annotation 'self-signed-cert', then it's created using helper scripts to setup self-signed certificates.
-	// As the root CA used to sign the certificate is required for webhook configuration, check if the corresponding secret is created
-	annotations := unstrSecret.GetAnnotations()
-	if _, ok := annotations[SelfSignedAnnotation]; ok {
-		sname := generateRootCASecretName(certProps)
-		_, err := client.GetResource("", "Secret", certProps.Namespace, sname)
-		if err != nil {
-			return nil, fmt.Errorf("rootCA secret is required while using self-signed certificate TLS pair, defaulting to generating new TLS pair  %s/%s", certProps.Namespace, sname)
-		}
-	}
-	secret, err := convertToSecret(unstrSecret)
-	if err != nil {
-		return nil, err
-	}
-
-	pemPair := PemPair{
-		Certificate: secret.Data[v1.TLSCertKey],
-		PrivateKey:  secret.Data[v1.TLSPrivateKeyKey],
-	}
-
-	if len(pemPair.Certificate) == 0 {
-		return nil, fmt.Errorf("TLS Certificate not found in secret %s/%s", certProps.Namespace, sname)
-	}
-	if len(pemPair.PrivateKey) == 0 {
-		return nil, fmt.Errorf("TLS PrivateKey not found in secret %s/%s", certProps.Namespace, sname)
-	}
-
-	return &pemPair, nil
-}
-
-//GetTLSCertProps provides the TLS Certificate Properties
-func GetTLSCertProps(configuration *rest.Config) (certProps CertificateProps, err error) {
-	apiServerURL, err := url.Parse(configuration.Host)
-	if err != nil {
-		return certProps, err
-	}
-
-	certProps = CertificateProps{
-		Service:       config.KyvernoServiceName,
-		Namespace:     config.KyvernoNamespace,
-		APIServerHost: apiServerURL.Hostname(),
-	}
-	return certProps, nil
-}
-
-func convertToSecret(obj *unstructured.Unstructured) (v1.Secret, error) {
-	secret := v1.Secret{}
-	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &secret); err != nil {
-		return secret, err
-	}
-	return secret, nil
-}
diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go
index 880dc9f6e..023db9e69 100644
--- a/pkg/tls/tls.go
+++ b/pkg/tls/tls.go
@@ -14,11 +14,7 @@ import (
 	"time"
 )
 
-// CertRenewalInterval is the renewal interval for rootCA
-const CertRenewalInterval time.Duration = 12 * time.Hour
-
-// CertValidityDuration is the valid duration for a new cert
-const CertValidityDuration time.Duration = 365 * 24 * time.Hour
+const certValidityDuration = 10 * 365 * 24 * time.Hour
 
 // CertificateProps Properties of TLS certificate which should be issued for webhook server
 type CertificateProps struct {
@@ -67,7 +63,7 @@ func CertificateToPem(certificateDER []byte) []byte {
 
 // GenerateCACert creates the self-signed CA cert and private key
 // it will be used to sign the webhook server certificate
-func GenerateCACert(certValidityDuration time.Duration) (*KeyPair, *PemPair, error) {
+func GenerateCACert() (*KeyPair, *PemPair, error) {
 	now := time.Now()
 	begin := now.Add(-1 * time.Hour)
 	end := now.Add(certValidityDuration)
@@ -114,7 +110,7 @@ func GenerateCACert(certValidityDuration time.Duration) (*KeyPair, *PemPair, err
 
 // GenerateCertPem takes the results of GenerateCACert and uses it to create the
 // PEM-encoded public certificate and private key, respectively
-func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string, certValidityDuration time.Duration) (*PemPair, error) {
+func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string) (*PemPair, error) {
 	now := time.Now()
 	begin := now.Add(-1 * time.Hour)
 	end := now.Add(certValidityDuration)
@@ -125,7 +121,7 @@ func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string, c
 
 	dnsNames[1] = fmt.Sprintf("%s.%s", props.Service, props.Namespace)
 	// The full service name is the CommonName for the certificate
-	commonName := generateInClusterServiceName(props)
+	commonName := GenerateInClusterServiceName(props)
 	dnsNames[2] = fmt.Sprintf("%s", commonName)
 
 	var ips []net.IP
@@ -178,7 +174,7 @@ func GenerateCertPem(caCert *KeyPair, props CertificateProps, serverIP string, c
 }
 
 //GenerateInClusterServiceName The generated service name should be the common name for TLS certificate
-func generateInClusterServiceName(props CertificateProps) string {
+func GenerateInClusterServiceName(props CertificateProps) string {
 	return props.Service + "." + props.Namespace + ".svc"
 }
 
diff --git a/pkg/webhookconfig/common.go b/pkg/webhookconfig/common.go
index 58a3a2b0d..0ec76c895 100644
--- a/pkg/webhookconfig/common.go
+++ b/pkg/webhookconfig/common.go
@@ -4,34 +4,28 @@ import (
 	"io/ioutil"
 
 	"github.com/kyverno/kyverno/pkg/config"
-	"github.com/kyverno/kyverno/pkg/tls"
 	admregapi "k8s.io/api/admissionregistration/v1beta1"
 	apps "k8s.io/api/apps/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	rest "k8s.io/client-go/rest"
 )
 
 func (wrc *Register) readCaData() []byte {
-	logger := wrc.log.WithName("readCaData")
+	logger := wrc.log
 	var caData []byte
-	var err error
-
 	// Check if ca is defined in the secret tls-ca
 	// assume the key and signed cert have been defined in secret tls.kyverno
-	if caData, err = tls.ReadRootCASecret(wrc.clientConfig, wrc.client); err == nil {
+	if caData = wrc.client.ReadRootCASecret(); len(caData) != 0 {
 		logger.V(4).Info("read CA from secret")
 		return caData
 	}
-
-	logger.V(4).Info("failed to read CA from secret, reading from kubeconfig", "reason", err.Error())
+	logger.V(4).Info("failed to read CA from secret, reading from kubeconfig")
 	// load the CA from kubeconfig
 	if caData = extractCA(wrc.clientConfig); len(caData) != 0 {
 		logger.V(4).Info("read CA from kubeconfig")
 		return caData
 	}
-
 	logger.V(4).Info("failed to read CA from kubeconfig")
 	return nil
 }
@@ -55,8 +49,8 @@ func extractCA(config *rest.Config) (result []byte) {
 
 func (wrc *Register) constructOwner() v1.OwnerReference {
 	logger := wrc.log
+	kubePolicyDeployment, err := wrc.getKubePolicyDeployment()
 
-	kubePolicyDeployment, _, err := wrc.GetKubePolicyDeployment()
 	if err != nil {
 		logger.Error(err, "failed to construct OwnerReference")
 		return v1.OwnerReference{}
@@ -70,18 +64,17 @@ func (wrc *Register) constructOwner() v1.OwnerReference {
 	}
 }
 
-// GetKubePolicyDeployment gets Kyverno deployment
-func (wrc *Register) GetKubePolicyDeployment() (*apps.Deployment, *unstructured.Unstructured, error) {
+func (wrc *Register) getKubePolicyDeployment() (*apps.Deployment, error) {
 	lister, _ := wrc.resCache.GetGVRCache("Deployment")
 	kubePolicyDeployment, err := lister.NamespacedLister(config.KyvernoNamespace).Get(config.KyvernoDeploymentName)
 	if err != nil {
-		return nil, nil, err
+		return nil, err
 	}
 	deploy := apps.Deployment{}
 	if err = runtime.DefaultUnstructuredConverter.FromUnstructured(kubePolicyDeployment.UnstructuredContent(), &deploy); err != nil {
-		return nil, kubePolicyDeployment, err
+		return nil, err
 	}
-	return &deploy, kubePolicyDeployment, nil
+	return &deploy, nil
 }
 
 // debug mutating webhook
diff --git a/pkg/webhookconfig/monitor.go b/pkg/webhookconfig/monitor.go
index b39ecbe96..af59210c9 100644
--- a/pkg/webhookconfig/monitor.go
+++ b/pkg/webhookconfig/monitor.go
@@ -2,18 +2,12 @@ package webhookconfig
 
 import (
 	"fmt"
-	"os"
-	"reflect"
 	"sync"
 	"time"
 
 	"github.com/go-logr/logr"
-	"github.com/kyverno/kyverno/pkg/config"
+	dclient "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/event"
-	"github.com/kyverno/kyverno/pkg/resourcecache"
-	"github.com/kyverno/kyverno/pkg/tls"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/client-go/tools/cache"
 )
 
 //maxRetryCount defines the max deadline count
@@ -34,34 +28,17 @@ const (
 // like the webhook settings.
 //
 type Monitor struct {
-	t           time.Time
-	mu          sync.RWMutex
-	secretQueue chan bool
-	log         logr.Logger
+	t   time.Time
+	mu  sync.RWMutex
+	log logr.Logger
 }
 
-//NewMonitor returns a new instance of webhook monitor
-func NewMonitor(resCache resourcecache.ResourceCache, log logr.Logger) *Monitor {
-	monitor := &Monitor{
-		t:           time.Now(),
-		secretQueue: make(chan bool, 1),
-		log:         log,
+//NewMonitor returns a new instance of LastRequestTime store
+func NewMonitor(log logr.Logger) *Monitor {
+	return &Monitor{
+		t:   time.Now(),
+		log: log,
 	}
-
-	var err error
-	secretCache, ok := resCache.GetGVRCache("Secret")
-	if !ok {
-		if secretCache, err = resCache.CreateGVKInformer("Secret"); err != nil {
-			log.Error(err, "unable to start Secret's informer")
-		}
-	}
-
-	secretCache.GetInformer().AddEventHandler(cache.ResourceEventHandlerFuncs{
-		AddFunc:    monitor.addSecretFunc,
-		UpdateFunc: monitor.updateSecretFunc,
-	})
-
-	return monitor
 }
 
 //Time returns the last request time
@@ -79,59 +56,18 @@ func (t *Monitor) SetTime(tm time.Time) {
 	t.t = tm
 }
 
-func (t *Monitor) addSecretFunc(obj interface{}) {
-	secret := obj.(*unstructured.Unstructured)
-	if secret.GetNamespace() != config.KyvernoNamespace {
-		return
-	}
-
-	val, ok := secret.GetAnnotations()[tls.SelfSignedAnnotation]
-	if !ok || val != "true" {
-		return
-	}
-
-	t.secretQueue <- true
-}
-
-func (t *Monitor) updateSecretFunc(oldObj interface{}, newObj interface{}) {
-	old := oldObj.(*unstructured.Unstructured)
-	new := newObj.(*unstructured.Unstructured)
-	if new.GetNamespace() != config.KyvernoNamespace {
-		return
-	}
-
-	val, ok := new.GetAnnotations()[tls.SelfSignedAnnotation]
-	if !ok || val != "true" {
-		return
-	}
-
-	if reflect.DeepEqual(old.UnstructuredContent()["data"], new.UnstructuredContent()["data"]) {
-		return
-	}
-
-	t.secretQueue <- true
-	t.log.V(4).Info("secret updated, reconciling webhook configurations")
-}
-
 //Run runs the checker and verify the resource update
-func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen event.Interface, stopCh <-chan struct{}) {
+func (t *Monitor) Run(register *Register, eventGen event.Interface, client *dclient.Client, stopCh <-chan struct{}) {
 	logger := t.log
 	logger.V(4).Info("starting webhook monitor", "interval", idleCheckInterval)
-	status := newStatusControl(register.client, eventGen, logger.WithName("WebhookStatusControl"))
+	status := newStatusControl(client, eventGen, logger.WithName("WebhookStatusControl"))
 
 	ticker := time.NewTicker(tickerInterval)
 	defer ticker.Stop()
 
-	certsRenewalTicker := time.NewTicker(tls.CertRenewalInterval)
-	defer certsRenewalTicker.Stop()
-
 	for {
 		select {
 		case <-ticker.C:
-			if skipWebhookCheck(register, logger.WithName("statusCheck/skipWebhookCheck")) {
-				logger.Info("skip validating webhook status, Kyverno is in rolling update")
-				continue
-			}
 
 			if err := register.Check(); err != nil {
 				t.log.Error(err, "missing webhooks")
@@ -159,10 +95,6 @@ func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen
 
 			if timeDiff > idleCheckInterval {
 				logger.V(1).Info("webhook idle time exceeded", "deadline", idleCheckInterval)
-				if skipWebhookCheck(register, logger.WithName("skipWebhookCheck")) {
-					logger.Info("skip validating webhook status, Kyverno is in rolling update")
-					continue
-				}
 
 				// send request to update the Kyverno deployment
 				if err := status.IncrementAnnotation(); err != nil {
@@ -178,40 +110,6 @@ func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen
 				logger.Error(err, "failed to annotate deployment webhook status to success")
 			}
 
-		case <-certsRenewalTicker.C:
-			valid, err := certRenewer.ValidCert()
-			if err != nil {
-				logger.Error(err, "failed to validate cert")
-				continue
-			}
-
-			if valid {
-				continue
-			}
-
-			logger.Info("rootCA is about to expire, trigger a rolling update to renew the cert")
-			if err := certRenewer.RollingUpdate(); err != nil {
-				logger.Error(err, "unable to trigger a rolling update to renew rootCA, force restarting")
-				os.Exit(1)
-			}
-
-		case <-t.secretQueue:
-			valid, err := certRenewer.ValidCert()
-			if err != nil {
-				logger.Error(err, "failed to validate cert")
-				continue
-			}
-
-			if valid {
-				continue
-			}
-
-			logger.Info("rootCA has changed, updating webhook configurations")
-			if err := certRenewer.RollingUpdate(); err != nil {
-				logger.Error(err, "unable to trigger a rolling update to re-register webhook server, force restarting")
-				os.Exit(1)
-			}
-
 		case <-stopCh:
 			// handler termination signal
 			logger.V(2).Info("stopping webhook monitor")
@@ -219,14 +117,3 @@ func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen
 		}
 	}
 }
-
-// skipWebhookCheck returns true if Kyverno is in rolling update
-func skipWebhookCheck(register *Register, logger logr.Logger) bool {
-	_, deploy, err := register.GetKubePolicyDeployment()
-	if err != nil {
-		logger.Info("unable to get Kyverno deployment", "reason", err.Error())
-		return false
-	}
-
-	return tls.IsKyvernoIsInRollingUpdate(deploy.UnstructuredContent(), logger)
-}
diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go
index aef5331a4..64ace56bf 100644
--- a/pkg/webhookconfig/registration.go
+++ b/pkg/webhookconfig/registration.go
@@ -11,11 +11,9 @@ import (
 	"github.com/kyverno/kyverno/pkg/config"
 	client "github.com/kyverno/kyverno/pkg/dclient"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
-	"github.com/kyverno/kyverno/pkg/tls"
 	admregapi "k8s.io/api/admissionregistration/v1beta1"
 	errorsapi "k8s.io/apimachinery/pkg/api/errors"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	rest "k8s.io/client-go/rest"
 )
 
@@ -66,29 +64,24 @@ func (wrc *Register) Register() error {
 
 	wrc.removeWebhookConfigurations()
 
-	caData := wrc.readCaData()
-	if caData == nil {
-		return errors.New("Unable to extract CA data from configuration")
-	}
-
 	errors := make([]string, 0)
-	if err := wrc.createVerifyMutatingWebhookConfiguration(caData); err != nil {
+	if err := wrc.createVerifyMutatingWebhookConfiguration(); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createPolicyValidatingWebhookConfiguration(caData); err != nil {
+	if err := wrc.createPolicyValidatingWebhookConfiguration(); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createPolicyMutatingWebhookConfiguration(caData); err != nil {
+	if err := wrc.createPolicyMutatingWebhookConfiguration(); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createResourceValidatingWebhookConfiguration(caData); err != nil {
+	if err := wrc.createResourceValidatingWebhookConfiguration(); err != nil {
 		errors = append(errors, err.Error())
 	}
 
-	if err := wrc.createResourceMutatingWebhookConfiguration(caData); err != nil {
+	if err := wrc.createResourceMutatingWebhookConfiguration(); err != nil {
 		errors = append(errors, err.Error())
 	}
 
@@ -129,46 +122,19 @@ func (wrc *Register) Check() error {
 
 // Remove removes all webhook configurations
 func (wrc *Register) Remove(cleanUp chan<- struct{}) {
-	defer close(cleanUp)
-	if !wrc.cleanupKyvernoResource() {
-		return
-	}
-
 	wrc.removeWebhookConfigurations()
-	wrc.removeSecrets()
+	close(cleanUp)
 }
 
-// cleanupKyvernoResource returns true if Kyverno deployment is terminating
-func (wrc *Register) cleanupKyvernoResource() bool {
-	logger := wrc.log.WithName("cleanupKyvernoResource")
-	deploy, err := wrc.client.GetResource("", "Deployment", deployNamespace, deployName)
-	if err != nil {
-		logger.Error(err, "failed to get deployment")
-		return false
-	}
-
-	if deploy.GetDeletionTimestamp() != nil {
-		logger.Info("Kyverno is terminating, clean up Kyverno resources")
-		return true
-	}
+func (wrc *Register) createResourceMutatingWebhookConfiguration() error {
 
-	replicas, _, err := unstructured.NestedInt64(deploy.UnstructuredContent(), "spec", "replicas")
-	if err != nil {
-		logger.Error(err, "unable to fetch spec.replicas of Kyverno deployment")
-	}
+	var caData []byte
+	var config *admregapi.MutatingWebhookConfiguration
 
-	if replicas == 0 {
-		logger.Info("Kyverno is scaled to zero, clean up Kyverno resources")
-		return true
+	if caData = wrc.readCaData(); caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
 	}
 
-	logger.Info("updating Kyverno Pod, won't clean up Kyverno resources")
-	return false
-}
-
-func (wrc *Register) createResourceMutatingWebhookConfiguration(caData []byte) error {
-	var config *admregapi.MutatingWebhookConfiguration
-
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugMutatingWebhookConfig(caData)
 	} else {
@@ -192,9 +158,13 @@ func (wrc *Register) createResourceMutatingWebhookConfiguration(caData []byte) e
 	return nil
 }
 
-func (wrc *Register) createResourceValidatingWebhookConfiguration(caData []byte) error {
+func (wrc *Register) createResourceValidatingWebhookConfiguration() error {
+	var caData []byte
 	var config *admregapi.ValidatingWebhookConfiguration
 
+	if caData = wrc.readCaData(); caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
+	}
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugValidatingWebhookConfig(caData)
 	} else {
@@ -219,9 +189,15 @@ func (wrc *Register) createResourceValidatingWebhookConfiguration(caData []byte)
 }
 
 //registerPolicyValidatingWebhookConfiguration create a Validating webhook configuration for Policy CRD
-func (wrc *Register) createPolicyValidatingWebhookConfiguration(caData []byte) error {
+func (wrc *Register) createPolicyValidatingWebhookConfiguration() error {
+	var caData []byte
 	var config *admregapi.ValidatingWebhookConfiguration
 
+	// read certificate data
+	if caData = wrc.readCaData(); caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
+	}
+
 	if wrc.serverIP != "" {
 		config = wrc.contructDebugPolicyValidatingWebhookConfig(caData)
 	} else {
@@ -241,9 +217,14 @@ func (wrc *Register) createPolicyValidatingWebhookConfiguration(caData []byte) e
 	return nil
 }
 
-func (wrc *Register) createPolicyMutatingWebhookConfiguration(caData []byte) error {
+func (wrc *Register) createPolicyMutatingWebhookConfiguration() error {
+	var caData []byte
 	var config *admregapi.MutatingWebhookConfiguration
 
+	if caData = wrc.readCaData(); caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
+	}
+
 	if wrc.serverIP != "" {
 		config = wrc.contructDebugPolicyMutatingWebhookConfig(caData)
 	} else {
@@ -264,9 +245,14 @@ func (wrc *Register) createPolicyMutatingWebhookConfiguration(caData []byte) err
 	return nil
 }
 
-func (wrc *Register) createVerifyMutatingWebhookConfiguration(caData []byte) error {
+func (wrc *Register) createVerifyMutatingWebhookConfiguration() error {
+	var caData []byte
 	var config *admregapi.MutatingWebhookConfiguration
 
+	if caData = wrc.readCaData(); caData == nil {
+		return errors.New("Unable to extract CA data from configuration")
+	}
+
 	if wrc.serverIP != "" {
 		config = wrc.constructDebugVerifyMutatingWebhookConfig(caData)
 	} else {
@@ -449,24 +435,3 @@ func (wrc *Register) getVerifyWebhookMutatingWebhookName() string {
 func (wrc *Register) GetWebhookTimeOut() time.Duration {
 	return time.Duration(wrc.timeoutSeconds)
 }
-
-// removeSecrets removes Kyverno managed secrets
-func (wrc *Register) removeSecrets() {
-	selector := &v1.LabelSelector{
-		MatchLabels: map[string]string{
-			tls.ManagedByLabel: "kyverno",
-		},
-	}
-
-	secretList, err := wrc.client.ListResource("", "Secret", config.KyvernoNamespace, selector)
-	if err != nil && errorsapi.IsNotFound(err) {
-		wrc.log.Error(err, "failed to clean up Kyverno managed secrets")
-		return
-	}
-
-	for _, secret := range secretList.Items {
-		if err := wrc.client.DeleteResource("", "Secret", secret.GetNamespace(), secret.GetName(), false); err != nil {
-			wrc.log.Error(err, "failed to delete secret", "ns", secret.GetNamespace(), "name", secret.GetName())
-		}
-	}
-}
diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go
index 7a4873067..14d279135 100644
--- a/pkg/webhooks/server.go
+++ b/pkg/webhooks/server.go
@@ -27,7 +27,6 @@ import (
 	"github.com/kyverno/kyverno/pkg/policyreport"
 	"github.com/kyverno/kyverno/pkg/policystatus"
 	"github.com/kyverno/kyverno/pkg/resourcecache"
-	ktls "github.com/kyverno/kyverno/pkg/tls"
 	tlsutils "github.com/kyverno/kyverno/pkg/tls"
 	userinfo "github.com/kyverno/kyverno/pkg/userinfo"
 	"github.com/kyverno/kyverno/pkg/utils"
@@ -105,8 +104,6 @@ type WebhookServer struct {
 	// last request time
 	webhookMonitor *webhookconfig.Monitor
 
-	certRenewer *ktls.CertRenewer
-
 	// policy report generator
 	prGenerator policyreport.GeneratorInterface
 
@@ -151,7 +148,6 @@ func NewWebhookServer(
 	pCache policycache.Interface,
 	webhookRegistrationClient *webhookconfig.Register,
 	webhookMonitor *webhookconfig.Monitor,
-	certRenewer *ktls.CertRenewer,
 	statusSync policystatus.Listener,
 	configHandler config.Interface,
 	prGenerator policyreport.GeneratorInterface,
@@ -202,7 +198,6 @@ func NewWebhookServer(
 		configHandler:         configHandler,
 		cleanUp:               cleanUp,
 		webhookMonitor:        webhookMonitor,
-		certRenewer:           certRenewer,
 		prGenerator:           prGenerator,
 		grGenerator:           grGenerator,
 		grController:          grc,
@@ -517,7 +512,7 @@ func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
 	logger.Info("starting service")
 
 	if !ws.debug {
-		go ws.webhookMonitor.Run(ws.webhookRegister, ws.certRenewer, ws.eventGen, stopCh)
+		go ws.webhookMonitor.Run(ws.webhookRegister, ws.eventGen, ws.client, stopCh)
 	}
 }
 


Test patch:
diff --git a/pkg/engine/variables/evaluate_test.go b/pkg/engine/variables/evaluate_test.go
index 723c21319..e2b0ea129 100644
--- a/pkg/engine/variables/evaluate_test.go
+++ b/pkg/engine/variables/evaluate_test.go
@@ -1066,10 +1066,10 @@ func Test_Eval_In_String_Set_Fail(t *testing.T) {
 	}
 }
 
-// test passes if ALL of the values in "key" are NOT in "value" ("key" is not a subset of "value")
+// test passes if ONE of the values in "key" is NOT in "value" ("key" is not a subset of "value")
 func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
 	ctx := context.NewContext()
-	key := [2]string{"4.4.4.4", "5.5.5.5"}
+	key := [3]string{"1.1.1.1", "4.4.4.4", "5.5.5.5"}
 	keyInterface := make([]interface{}, len(key), len(key))
 	for i := range key {
 		keyInterface[i] = key[i]
@@ -1094,7 +1094,7 @@ func Test_Eval_NotIn_String_Set_Pass(t *testing.T) {
 // test passes if ALL of the values in "key" are in "value" ("key" is a subset of "value")
 func Test_Eval_NotIn_String_Set_Fail(t *testing.T) {
 	ctx := context.NewContext()
-	key := [2]string{"1.1.1.1", "4.4.4.4"}
+	key := [2]string{"1.1.1.1", "2.2.2.2"}
 	keyInterface := make([]interface{}, len(key), len(key))
 	for i := range key {
 		keyInterface[i] = key[i]