diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index a92c1b8436..677c852d33 100755 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -405,7 +405,7 @@ func main() { os.Exit(1) } - if !autoUpdateWebhooks { + if autoUpdateWebhooks { go webhookCfg.UpdateWebhookConfigurations(configData) } if registrationErr := registerWrapperRetry(); registrationErr != nil { diff --git a/pkg/config/dynamicconfig.go b/pkg/config/dynamicconfig.go index b39be2facc..f456a09b7d 100644 --- a/pkg/config/dynamicconfig.go +++ b/pkg/config/dynamicconfig.go @@ -195,13 +195,14 @@ func (cd *ConfigData) updateCM(old, cur interface{}) { return } // if data has not changed then dont load configmap - reconcilePolicyReport, updateWebook := cd.load(*cm) + reconcilePolicyReport, updateWebhook := cd.load(*cm) + if reconcilePolicyReport { cd.log.Info("resource filters changed, sending reconcile signal to the policy controller") cd.reconcilePolicyReport <- true } - if updateWebook { + if updateWebhook { cd.log.Info("webhook configurations changed, updating webhook configurations") cd.updateWebhookConfigurations <- true } @@ -284,7 +285,13 @@ func (cd *ConfigData) load(cm v1.ConfigMap) (reconcilePolicyReport, updateWebhoo webhooks, ok := cm.Data["webhooks"] if !ok { - logger.V(4).Info("configuration: No webhook configurations defined in ConfigMap") + if len(cd.webhooks) > 0 { + cd.webhooks = nil + updateWebhook = true + logger.V(4).Info("configuration: Setting namespaceSelector to empty in the webhook configurations") + } else { + logger.V(4).Info("configuration: No webhook configurations defined in ConfigMap") + } } else { cfgs, err := parseWebhooks(webhooks) if err != nil { diff --git a/pkg/webhookconfig/monitor.go b/pkg/webhookconfig/monitor.go index 65982a2625..cefd252d53 100644 --- a/pkg/webhookconfig/monitor.go +++ b/pkg/webhookconfig/monitor.go @@ -106,6 +106,12 @@ func (t *Monitor) Run(register *Register, certRenewer *tls.CertRenewer, eventGen t.log.Error(err, "") } + // update namespaceSelector every 30 seconds + if register.autoUpdateWebhooks { + logger.V(3).Info("updating webhook configurations for namespaceSelector with latest kyverno ConfigMap") + register.UpdateWebhookChan <- true + } + timeDiff := time.Since(t.Time()) lastRequestTimeFromAnn := lastRequestTimeFromAnnotation(register, t.log.WithName("lastRequestTimeFromAnnotation")) if lastRequestTimeFromAnn == nil { diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go index 37a08803f8..783c66176c 100644 --- a/pkg/webhookconfig/registration.go +++ b/pkg/webhookconfig/registration.go @@ -712,19 +712,24 @@ func (wrc *Register) updateResourceValidatingWebhookConfiguration(nsSelector map return errors.Wrapf(err, "unable to load validatingWebhookConfigurations.webhooks") } - var webhooks map[string]interface{} - var ok bool - if webhooksUntyped != nil { - webhooks, ok = webhooksUntyped[0].(map[string]interface{}) + var ( + webhook map[string]interface{} + webhooks []interface{} + ok bool + ) + + for i, whu := range webhooksUntyped { + webhook, ok = whu.(map[string]interface{}) if !ok { - return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[0]) + return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[i]) } - } - if err = unstructured.SetNestedMap(webhooks, nsSelector, "namespaceSelector"); err != nil { - return errors.Wrapf(err, "unable to set validatingWebhookConfigurations.webhooks[0].namespaceSelector") + if err = unstructured.SetNestedMap(webhook, nsSelector, "namespaceSelector"); err != nil { + return errors.Wrapf(err, "unable to set validatingWebhookConfigurations.webhooks["+fmt.Sprint(i)+"].namespaceSelector") + } + webhooks = append(webhooks, webhook) } - if err = unstructured.SetNestedSlice(resourceValidating.UnstructuredContent(), []interface{}{webhooks}, "webhooks"); err != nil { + if err = unstructured.SetNestedSlice(resourceValidating.UnstructuredContent(), webhooks, "webhooks"); err != nil { return errors.Wrapf(err, "unable to set validatingWebhookConfigurations.webhooks") } @@ -748,19 +753,24 @@ func (wrc *Register) updateResourceMutatingWebhookConfiguration(nsSelector map[s return errors.Wrapf(err, "unable to load mutatingWebhookConfigurations.webhooks") } - var webhooks map[string]interface{} - var ok bool - if webhooksUntyped != nil { - webhooks, ok = webhooksUntyped[0].(map[string]interface{}) + var ( + webhook map[string]interface{} + webhooks []interface{} + ok bool + ) + + for i, whu := range webhooksUntyped { + webhook, ok = whu.(map[string]interface{}) if !ok { - return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[0]) + return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[i]) } - } - if err = unstructured.SetNestedMap(webhooks, nsSelector, "namespaceSelector"); err != nil { - return errors.Wrapf(err, "unable to set mutatingWebhookConfigurations.webhooks[0].namespaceSelector") + if err = unstructured.SetNestedMap(webhook, nsSelector, "namespaceSelector"); err != nil { + return errors.Wrapf(err, "unable to set mutatingWebhookConfigurations.webhooks["+fmt.Sprint(i)+"].namespaceSelector") + } + webhooks = append(webhooks, webhook) } - if err = unstructured.SetNestedSlice(resourceMutating.UnstructuredContent(), []interface{}{webhooks}, "webhooks"); err != nil { + if err = unstructured.SetNestedSlice(resourceMutating.UnstructuredContent(), webhooks, "webhooks"); err != nil { return errors.Wrapf(err, "unable to set mutatingWebhookConfigurations.webhooks") }