From b66c1b7f0cb51e381956d2217c528b0e1b79abaa Mon Sep 17 00:00:00 2001 From: shivkumar dudhani <shivkumar@nirmata.com> Date: Wed, 4 Sep 2019 10:40:49 -0700 Subject: [PATCH 1/5] remove exlude kind checks --- pkg/namespace/utils.go | 48 ------------------------------------------ pkg/webhooks/report.go | 44 -------------------------------------- pkg/webhooks/utils.go | 45 +-------------------------------------- 3 files changed, 1 insertion(+), 136 deletions(-) diff --git a/pkg/namespace/utils.go b/pkg/namespace/utils.go index ee0922fc44..6f648e8344 100644 --- a/pkg/namespace/utils.go +++ b/pkg/namespace/utils.go @@ -4,52 +4,4 @@ const ( wqNamespace string = "namespace" workerCount int = 1 wqRetryLimit int = 5 - policyKind string = "Policy" ) - -// func namespaceMeetsRuleDescription(ns *corev1.Namespace, resourceDescription v1alpha1.ResourceDescription) bool { -// //REWORK Not needed but verify the 'Namespace' is defined in the list of supported kinds -// if !findKind(resourceDescription.Kinds, "Namespace") { -// return false -// } -// if resourceDescription.Name != nil { -// if !wildcard.Match(*resourceDescription.Name, ns.Name) { -// return false -// } -// } - -// if resourceDescription.Selector != nil { -// selector, err := metav1.LabelSelectorAsSelector(resourceDescription.Selector) -// if err != nil { -// return false -// } - -// labelSet := convertLabelsToLabelSet(ns.Labels) -// // labels -// if !selector.Matches(labelSet) { -// return false -// } -// } -// return true -// } - -// func convertLabelsToLabelSet(labelMap map[string]string) labels.Set { -// labelSet := make(labels.Set, len(labelMap)) -// // REWORK: check if the below works -// // if x, ok := labelMap.(labels.Set); !ok { - -// // } -// for k, v := range labelMap { -// labelSet[k] = v -// } -// return labelSet -// } - -// func findKind(kinds []string, kindGVK string) bool { -// for _, kind := range kinds { -// if kind == kindGVK { -// return true -// } -// } -// return false -// } diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index a5fc8ef080..ab446254ca 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -94,47 +94,3 @@ func generateEvents(engineResponses []engine.EngineResponseNew, onUpdate bool) [ } return events } - -// //TODO: change validation from bool -> enum(validation, mutation) -// func newEventInfoFromPolicyInfo(policyInfoList []info.PolicyInfo, onUpdate bool, ruleType info.RuleType) []*event.Info { -// var eventsInfo []*event.Info -// ok, msg := isAdmSuccesful(policyInfoList) -// // Some policies failed to apply succesfully -// if !ok { -// for _, pi := range policyInfoList { -// if pi.IsSuccessful() { -// continue -// } -// rules := pi.FailedRules() -// ruleNames := strings.Join(rules, ";") -// if !onUpdate { -// // CREATE -// eventsInfo = append(eventsInfo, -// event.NewEvent(policyKind, "", pi.Name, event.RequestBlocked, event.FPolicyApplyBlockCreate, pi.RNamespace+"/"+pi.RName, ruleNames)) - -// glog.V(3).Infof("Rule(s) %s of policy %s blocked resource creation, error: %s\n", ruleNames, pi.Name, msg) -// } else { -// // UPDATE -// eventsInfo = append(eventsInfo, -// event.NewEvent(pi.RKind, pi.RNamespace, pi.RName, event.RequestBlocked, event.FPolicyApplyBlockUpdate, ruleNames, pi.Name)) -// eventsInfo = append(eventsInfo, -// event.NewEvent(policyKind, "", pi.Name, event.RequestBlocked, event.FPolicyBlockResourceUpdate, pi.RNamespace+"/"+pi.RName, ruleNames)) -// glog.V(3).Infof("Request blocked events info has prepared for %s/%s and %s/%s\n", policyKind, pi.Name, pi.RKind, pi.RName) -// } -// } -// } else { -// if !onUpdate { -// // All policies were applied succesfully -// // CREATE -// for _, pi := range policyInfoList { -// rules := pi.SuccessfulRules() -// ruleNames := strings.Join(rules, ";") -// eventsInfo = append(eventsInfo, -// event.NewEvent(pi.RKind, pi.RNamespace, pi.RName, event.PolicyApplied, event.SRulesApply, ruleNames, pi.Name)) - -// glog.V(3).Infof("Success event info has prepared for %s/%s\n", pi.RKind, pi.RName) -// } -// } -// } -// return eventsInfo -// } diff --git a/pkg/webhooks/utils.go b/pkg/webhooks/utils.go index c7dcac6d8b..5c658553ce 100644 --- a/pkg/webhooks/utils.go +++ b/pkg/webhooks/utils.go @@ -9,23 +9,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine" ) -const policyKind = "Policy" - -// func isAdmSuccesful(policyInfos []info.PolicyInfo) (bool, string) { -// var admSuccess = true -// var errMsgs []string -// for _, pi := range policyInfos { -// if !pi.IsSuccessful() { -// admSuccess = false -// errMsgs = append(errMsgs, fmt.Sprintf("\nPolicy %s failed with following rules", pi.Name)) -// // Get the error rules -// errorRules := pi.ErrorRules() -// errMsgs = append(errMsgs, errorRules) -// } -// } -// return admSuccess, strings.Join(errMsgs, ";") -// } - func isResponseSuccesful(engineReponses []engine.EngineResponseNew) bool { for _, er := range engineReponses { if !er.IsSuccesful() { @@ -82,26 +65,13 @@ func (i *ArrayFlags) Set(value string) error { // extract the kinds that the policy rules apply to func getApplicableKindsForPolicy(p *kyverno.ClusterPolicy) []string { - kindsMap := map[string]interface{}{} kinds := []string{} // iterate over the rules an identify all kinds // Matching for _, rule := range p.Spec.Rules { for _, k := range rule.MatchResources.Kinds { - kindsMap[k] = nil + kinds = append(kinds, k) } - // remove excluded ones - for _, k := range rule.ExcludeResources.Kinds { - if _, ok := kindsMap[k]; ok { - // delete kind - delete(kindsMap, k) - } - } - } - - // get the kinds - for k := range kindsMap { - kinds = append(kinds, k) } return kinds } @@ -112,19 +82,6 @@ const ( ReportViolation = "audit" ) -// // returns true -> if there is even one policy that blocks resource requst -// // returns false -> if all the policies are meant to report only, we dont block resource request -// func toBlock(pis []info.PolicyInfo) bool { -// for _, pi := range pis { -// if pi.ValidationFailureAction != ReportViolation { -// glog.V(3).Infoln("ValidationFailureAction set to enforce, blocking resource ceation") -// return true -// } -// } -// glog.V(3).Infoln("ValidationFailureAction set to audit, allowing resource creation, reporting with violation") -// return false -// } - func processResourceWithPatches(patch []byte, resource []byte) []byte { if patch == nil { return nil From c2e822c887303f2a3adf32fb599512f85bec648e Mon Sep 17 00:00:00 2001 From: shivkumar dudhani <shivkumar@nirmata.com> Date: Wed, 4 Sep 2019 13:43:12 -0700 Subject: [PATCH 2/5] refactor webhook configuration --- pkg/config/config.go | 18 +++---- pkg/policy/controller.go | 69 +++----------------------- pkg/policy/webhookregistration.go | 71 +++++++++++++++++++++++++++ pkg/webhookconfig/policy.go | 12 ++--- pkg/webhookconfig/registration.go | 80 ++++++++++++++++--------------- pkg/webhookconfig/resource.go | 33 ++++++++++--- pkg/webhooks/policyvalidation.go | 19 +++++++- pkg/webhooks/webhookManager.go | 74 ---------------------------- 8 files changed, 176 insertions(+), 200 deletions(-) create mode 100644 pkg/policy/webhookregistration.go delete mode 100644 pkg/webhooks/webhookManager.go diff --git a/pkg/config/config.go b/pkg/config/config.go index 5052be504f..130e7c7f6d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -7,13 +7,13 @@ const ( KubePolicyNamespace = "kyverno" WebhookServiceName = "kyverno-svc" - MutatingWebhookConfigurationName = "kyverno-mutating-webhook-cfg" - MutatingWebhookConfigurationDebug = "kyverno-mutating-webhook-cfg-debug" - MutatingWebhookName = "nirmata.kyverno.mutating-webhook" + MutatingWebhookConfigurationName = "kyverno-resource-mutating-webhook-cfg" + MutatingWebhookConfigurationDebugName = "kyverno-resource-mutating-webhook-cfg-debug" + MutatingWebhookName = "nirmata.kyverno.resource.mutating-webhook" - ValidatingWebhookConfigurationName = "kyverno-validating-webhook-cfg" - ValidatingWebhookConfigurationDebug = "kyverno-validating-webhook-cfg-debug" - ValidatingWebhookName = "nirmata.kyverno.policy-validating-webhook" + // ValidatingWebhookConfigurationName = "kyverno-validating-webhook-cfg" + // ValidatingWebhookConfigurationDebug = "kyverno-validating-webhook-cfg-debug" + // ValidatingWebhookName = "nirmata.kyverno.policy-validating-webhook" PolicyValidatingWebhookConfigurationName = "kyverno-policy-validating-webhook-cfg" PolicyValidatingWebhookConfigurationDebugName = "kyverno-policy-validating-webhook-cfg-debug" @@ -36,9 +36,9 @@ var ( ValidatingWebhookServicePath = "/validate" PolicyValidatingWebhookServicePath = "/policyvalidate" PolicyMutatingWebhookServicePath = "/policymutate" - KubePolicyAppLabels = map[string]string{ - "app": "kyverno", - } + // KubePolicyAppLabels = map[string]string{ + // "app": "kyverno", + // } SupportedKinds = []string{ "ConfigMap", diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go index 9cc4b377fe..35f5eb45b8 100644 --- a/pkg/policy/controller.go +++ b/pkg/policy/controller.go @@ -13,7 +13,6 @@ import ( "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1alpha1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1alpha1" - "github.com/nirmata/kyverno/pkg/config" client "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/event" "github.com/nirmata/kyverno/pkg/utils" @@ -409,17 +408,21 @@ func (pc *PolicyController) syncPolicy(key string) error { // remove the recorded stats for the policy pc.statusAggregator.RemovePolicyStats(key) // remove webhook configurations if there are not policies - if err := pc.handleWebhookRegistration(true, nil); err != nil { + if err := pc.removeResourceWebhookConfiguration(); err != nil { + // do not fail, if unable to delete resource webhook config + glog.V(4).Info("failed to remove resource webhook configuration: %v", err) glog.Errorln(err) } return nil } if err != nil { + glog.V(4).Info(err) return err } - if err := pc.handleWebhookRegistration(false, policy); err != nil { + if err := pc.createResourceMutatingWebhookConfigurationIfRequired(*policy); err != nil { + glog.V(4).Infof("failed to create resource mutating webhook configurations, policies wont be applied on resources: %v", err) glog.Errorln(err) } @@ -440,47 +443,6 @@ func (pc *PolicyController) syncPolicy(key string) error { return pc.syncStatusOnly(p, pvList) } -// TODO: here checks mutatingwebhook only -// as 'kubectl scale' is not funtional with validatingwebhook -// refer to https://github.com/nirmata/kyverno/issues/250 -func (pc *PolicyController) handleWebhookRegistration(delete bool, policy *kyverno.ClusterPolicy) error { - policies, _ := pc.pLister.List(labels.NewSelector()) - selector := &metav1.LabelSelector{MatchLabels: config.KubePolicyAppLabels} - webhookSelector, err := metav1.LabelSelectorAsSelector(selector) - if err != nil { - return fmt.Errorf("invalid label selector: %v", err) - } - - webhookList, err := pc.mutationwebhookLister.List(webhookSelector) - if err != nil { - return fmt.Errorf("failed to list mutatingwebhookconfigurations, err %v", err) - } - - if delete { - if webhookList == nil { - return nil - } - - // webhook exist, deregister webhookconfigurations on condition - // check empty policy first, then rule type in terms of O(time) - if policies == nil { - glog.V(3).Infoln("No policy found in the cluster, deregistering webhook") - pc.webhookRegistrationClient.RemoveResourceMutatingWebhookConfiguration() - } else if !HasMutateOrValidatePolicies(policies) { - glog.V(3).Infoln("No muatate/validate policy found in the cluster, deregistering webhook") - pc.webhookRegistrationClient.RemoveResourceMutatingWebhookConfiguration() - } - return nil - } - - if webhookList == nil && HasMutateOrValidate(*policy) { - glog.V(3).Infoln("Found policy without mutatingwebhook, registering webhook") - pc.webhookRegistrationClient.CreateResourceMutatingWebhookConfiguration() - } - - return nil -} - //syncStatusOnly updates the policy status subresource // status: // - violations : (count of the resources that violate this policy ) @@ -930,22 +892,3 @@ func joinPatches(patches ...[]byte) []byte { result = append(result, []byte("\n]")...) return result } - -func HasMutateOrValidatePolicies(policies []*kyverno.ClusterPolicy) bool { - for _, policy := range policies { - if HasMutateOrValidate(*policy) { - return true - } - } - return false -} - -func HasMutateOrValidate(policy kyverno.ClusterPolicy) bool { - for _, rule := range policy.Spec.Rules { - if !reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) || !reflect.DeepEqual(rule.Validation, kyverno.Validation{}) { - glog.Infoln(rule.Name) - return true - } - } - return false -} diff --git a/pkg/policy/webhookregistration.go b/pkg/policy/webhookregistration.go new file mode 100644 index 0000000000..4883cfb8de --- /dev/null +++ b/pkg/policy/webhookregistration.go @@ -0,0 +1,71 @@ +package policy + +import ( + "reflect" + + "github.com/golang/glog" + kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1" + "k8s.io/apimachinery/pkg/labels" +) + +func (pc *PolicyController) removeResourceWebhookConfiguration() error { + removeWebhookConfig := func() error { + var err error + err = pc.webhookRegistrationClient.RemoveResourceMutatingWebhookConfiguration() + if err != nil { + return err + } + glog.V(4).Info("removed resource webhook configuration") + return nil + } + + var err error + // get all existing policies + policies, err := pc.pLister.List(labels.NewSelector()) + if err != nil { + glog.V(4).Infof("failed to list policies: %v", err) + return err + } + + if len(policies) == 0 { + glog.V(4).Info("no policies loaded, removing resource webhook configuration if one exists") + return removeWebhookConfig() + } + + // if there are policies, check if they contain mutating or validating rule + if !hasMutateOrValidatePolicies(policies) { + glog.V(4).Info("no policies with mutating or validating webhook configurations, remove resource webhook configuration if one exists") + return removeWebhookConfig() + } + + return nil +} + +func (pc *PolicyController) createResourceMutatingWebhookConfigurationIfRequired(policy kyverno.ClusterPolicy) error { + // if the policy contains mutating & validation rules and it config does not exist we create one + if hasMutateOrValidate(policy) { + if err := pc.webhookRegistrationClient.CreateResourceMutatingWebhookConfiguration(); err != nil { + return err + } + } + return nil +} + +func hasMutateOrValidatePolicies(policies []*kyverno.ClusterPolicy) bool { + for _, policy := range policies { + if hasMutateOrValidate(*policy) { + return true + } + } + return false +} + +func hasMutateOrValidate(policy kyverno.ClusterPolicy) bool { + for _, rule := range policy.Spec.Rules { + if !reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) || !reflect.DeepEqual(rule.Validation, kyverno.Validation{}) { + glog.Infoln(rule.Name) + return true + } + } + return false +} diff --git a/pkg/webhookconfig/policy.go b/pkg/webhookconfig/policy.go index e434b52c30..60a7b5bfae 100644 --- a/pkg/webhookconfig/policy.go +++ b/pkg/webhookconfig/policy.go @@ -13,8 +13,7 @@ func (wrc *WebhookRegistrationClient) contructPolicyValidatingWebhookConfig(caDa return &admregapi.ValidatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.PolicyValidatingWebhookConfigurationName, - Labels: config.KubePolicyAppLabels, + Name: config.PolicyValidatingWebhookConfigurationName, OwnerReferences: []v1.OwnerReference{ wrc.constructOwner(), }, @@ -41,8 +40,7 @@ func (wrc *WebhookRegistrationClient) contructDebugPolicyValidatingWebhookConfig return &admregapi.ValidatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.PolicyValidatingWebhookConfigurationDebugName, - Labels: config.KubePolicyAppLabels, + Name: config.PolicyValidatingWebhookConfigurationDebugName, }, Webhooks: []admregapi.Webhook{ generateDebugWebhook( @@ -63,8 +61,7 @@ func (wrc *WebhookRegistrationClient) contructDebugPolicyValidatingWebhookConfig func (wrc *WebhookRegistrationClient) contructPolicyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.PolicyMutatingWebhookConfigurationName, - Labels: config.KubePolicyAppLabels, + Name: config.PolicyMutatingWebhookConfigurationName, OwnerReferences: []v1.OwnerReference{ wrc.constructOwner(), }, @@ -90,8 +87,7 @@ func (wrc *WebhookRegistrationClient) contructDebugPolicyMutatingWebhookConfig(c return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.PolicyMutatingWebhookConfigurationDebugName, - Labels: config.KubePolicyAppLabels, + Name: config.PolicyMutatingWebhookConfigurationDebugName, }, Webhooks: []admregapi.Webhook{ generateDebugWebhook( diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go index a8f036484e..2511a13167 100644 --- a/pkg/webhookconfig/registration.go +++ b/pkg/webhookconfig/registration.go @@ -7,7 +7,6 @@ import ( "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" client "github.com/nirmata/kyverno/pkg/dclient" - "github.com/tevino/abool" admregapi "k8s.io/api/admissionregistration/v1beta1" errorsapi "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -21,10 +20,8 @@ type WebhookRegistrationClient struct { client *client.Client clientConfig *rest.Config // serverIP should be used if running Kyverno out of clutser - serverIP string - timeoutSeconds int32 - MutationRegistered *abool.AtomicBool - ValidationRegistered *abool.AtomicBool + serverIP string + timeoutSeconds int32 } // NewWebhookRegistrationClient creates new WebhookRegistrationClient instance @@ -34,16 +31,14 @@ func NewWebhookRegistrationClient(clientConfig *rest.Config, client *client.Clie return nil, err } - glog.V(3).Infof("Registering webhook client using serverIP %s\n", serverIP) + glog.V(4).Infof("Registering webhook client using serverIP %s\n", serverIP) return &WebhookRegistrationClient{ - registrationClient: registrationClient, - client: client, - clientConfig: clientConfig, - serverIP: serverIP, - timeoutSeconds: webhookTimeout, - MutationRegistered: abool.New(), - ValidationRegistered: abool.New(), + registrationClient: registrationClient, + client: client, + clientConfig: clientConfig, + serverIP: serverIP, + timeoutSeconds: webhookTimeout, }, nil } @@ -104,14 +99,30 @@ func (wrc *WebhookRegistrationClient) CreateResourceMutatingWebhookConfiguration config = wrc.constructMutatingWebhookConfig(caData) } - if _, err := wrc.registrationClient.MutatingWebhookConfigurations().Create(config); err != nil { + _, err := wrc.registrationClient.MutatingWebhookConfigurations().Create(config) + if errorsapi.IsAlreadyExists(err) { + glog.V(4).Infof("resource mutating webhook configuration %s, already exists. not creating one", config.Name) + return nil + } + if err != nil { + glog.V(4).Infof("failed to create resource mutating webhook configuration %s: %v", config.Name, err) return err } - - wrc.MutationRegistered.Set() return nil } +//GetResourceMutatingWebhookConfiguration returns the MutatingWebhookConfiguration +func (wrc *WebhookRegistrationClient) GetResourceMutatingWebhookConfiguration() (*admregapi.MutatingWebhookConfiguration, error) { + var name string + if wrc.serverIP != "" { + name = config.MutatingWebhookConfigurationDebugName + } else { + name = config.MutatingWebhookConfigurationName + } + + return wrc.registrationClient.MutatingWebhookConfigurations().Get(name, v1.GetOptions{}) +} + //registerPolicyValidatingWebhookConfiguration create a Validating webhook configuration for Policy CRD func (wrc *WebhookRegistrationClient) createPolicyValidatingWebhookConfiguration() error { var caData []byte @@ -193,6 +204,7 @@ func (wrc *WebhookRegistrationClient) removeWebhookConfigurations() { // webhookConfigurations are re-created later func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() { // Validating webhook configuration + var err error var validatingConfig string if wrc.serverIP != "" { validatingConfig = config.PolicyValidatingWebhookConfigurationDebugName @@ -200,9 +212,13 @@ func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() { validatingConfig = config.PolicyValidatingWebhookConfigurationName } glog.V(4).Infof("removing webhook configuration %s", validatingConfig) - err := wrc.registrationClient.ValidatingWebhookConfigurations().Delete(validatingConfig, &v1.DeleteOptions{}) - if err != nil && !errorsapi.IsNotFound(err) { - glog.Error(err) + err = wrc.registrationClient.ValidatingWebhookConfigurations().Delete(validatingConfig, &v1.DeleteOptions{}) + if errorsapi.IsNotFound(err) { + glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig) + } else if err != nil { + glog.Errorf("failed to delete policy webhook configuration %s: %v", validatingConfig, err) + } else { + glog.V(4).Infof("succesfully deleted policy webhook configuration %s", validatingConfig) } // Mutating webhook configuration @@ -214,24 +230,12 @@ func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() { } glog.V(4).Infof("removing webhook configuration %s", mutatingConfig) - if err := wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{}); err != nil && !errorsapi.IsNotFound(err) { - glog.Error(err) - } -} - -//RemoveResourceMutatingWebhookConfiguration removes mutating webhook configuration for all resources -func (wrc *WebhookRegistrationClient) RemoveResourceMutatingWebhookConfiguration() { - var configName string - if wrc.serverIP != "" { - configName = config.MutatingWebhookConfigurationDebug - } else { - configName = config.MutatingWebhookConfigurationName - } - // delete webhook configuration - err := wrc.registrationClient.MutatingWebhookConfigurations().Delete(configName, &v1.DeleteOptions{}) - if err != nil && !errorsapi.IsNotFound(err) { - glog.Error(err) - } else { - wrc.MutationRegistered.UnSet() + err = wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{}) + if errorsapi.IsNotFound(err) { + glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig) + } else if err != nil { + glog.Errorf("failed to delete policy webhook configuration %s: %v", mutatingConfig, err) + } else { + glog.V(4).Infof("succesfully deleted policy webhook configuration %s", mutatingConfig) } } diff --git a/pkg/webhookconfig/resource.go b/pkg/webhookconfig/resource.go index 63d44d28d6..f86777cb82 100644 --- a/pkg/webhookconfig/resource.go +++ b/pkg/webhookconfig/resource.go @@ -6,6 +6,7 @@ import ( "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" admregapi "k8s.io/api/admissionregistration/v1beta1" + "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -15,8 +16,7 @@ func (wrc *WebhookRegistrationClient) contructDebugMutatingWebhookConfig(caData return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.MutatingWebhookConfigurationDebug, - Labels: config.KubePolicyAppLabels, + Name: config.MutatingWebhookConfigurationDebugName, }, Webhooks: []admregapi.Webhook{ generateDebugWebhook( @@ -28,7 +28,7 @@ func (wrc *WebhookRegistrationClient) contructDebugMutatingWebhookConfig(caData "*/*", "*", "*", - []admregapi.OperationType{admregapi.Create}, + []admregapi.OperationType{admregapi.Create, admregapi.Update}, ), }, } @@ -37,8 +37,7 @@ func (wrc *WebhookRegistrationClient) contructDebugMutatingWebhookConfig(caData func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ - Name: config.MutatingWebhookConfigurationName, - Labels: config.KubePolicyAppLabels, + Name: config.MutatingWebhookConfigurationName, OwnerReferences: []v1.OwnerReference{ wrc.constructOwner(), }, @@ -53,8 +52,30 @@ func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(caData []by "*/*", "*", "*", - []admregapi.OperationType{admregapi.Create}, + []admregapi.OperationType{admregapi.Create, admregapi.Update}, ), }, } } + +//RemoveResourceMutatingWebhookConfiguration removes mutating webhook configuration for all resources +func (wrc *WebhookRegistrationClient) RemoveResourceMutatingWebhookConfiguration() error { + var configName string + if wrc.serverIP != "" { + configName = config.MutatingWebhookConfigurationDebugName + } else { + configName = config.MutatingWebhookConfigurationName + } + // delete webhook configuration + err := wrc.registrationClient.MutatingWebhookConfigurations().Delete(configName, &v1.DeleteOptions{}) + if errors.IsNotFound(err) { + glog.V(4).Infof("resource webhook configuration %s does not exits, so not deleting", configName) + return nil + } + if err != nil { + glog.V(4).Infof("failed to delete resource webhook configuration %s: %v", configName, err) + return err + } + glog.V(4).Infof("deleted resource webhook configuration %s", configName) + return nil +} diff --git a/pkg/webhooks/policyvalidation.go b/pkg/webhooks/policyvalidation.go index b63c659da4..0e54b64340 100644 --- a/pkg/webhooks/policyvalidation.go +++ b/pkg/webhooks/policyvalidation.go @@ -31,10 +31,25 @@ func (ws *WebhookServer) handlePolicyValidation(request *v1beta1.AdmissionReques // check for uniqueness of rule names while CREATE/DELET admissionResp = ws.validateUniqueRuleName(policy) - if admissionResp.Allowed { - ws.manageWebhookConfigurations(*policy, request.Operation) + // helper function to evaluate if policy has validtion or mutation rules defined + hasMutateOrValidate := func() bool { + for _, rule := range policy.Spec.Rules { + if !reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) || !reflect.DeepEqual(rule.Validation, kyverno.Validation{}) { + glog.Infoln(rule.Name) + return true + } + } + return false } + if admissionResp.Allowed { + if hasMutateOrValidate() { + // create mutating resource mutatingwebhookconfiguration if not present + if err := ws.webhookRegistrationClient.CreateResourceMutatingWebhookConfiguration(); err != nil { + glog.Error("failed to created resource mutating webhook configuration, policies wont be applied on the resource") + } + } + } return admissionResp } diff --git a/pkg/webhooks/webhookManager.go b/pkg/webhooks/webhookManager.go deleted file mode 100644 index 72a2020b0d..0000000000 --- a/pkg/webhooks/webhookManager.go +++ /dev/null @@ -1,74 +0,0 @@ -package webhooks - -import ( - "reflect" - - "github.com/golang/glog" - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1" - v1beta1 "k8s.io/api/admission/v1beta1" - "k8s.io/apimachinery/pkg/labels" -) - -type policyType int - -const ( - none policyType = iota - mutate - validate - all -) - -func (ws *WebhookServer) manageWebhookConfigurations(policy kyverno.ClusterPolicy, op v1beta1.Operation) { - switch op { - case v1beta1.Create: - ws.registerWebhookConfigurations(policy) - case v1beta1.Delete: - ws.deregisterWebhookConfigurations(policy) - } -} - -func (ws *WebhookServer) registerWebhookConfigurations(policy kyverno.ClusterPolicy) error { - if !HasMutateOrValidate(policy) { - return nil - } - - if !ws.webhookRegistrationClient.MutationRegistered.IsSet() { - if err := ws.webhookRegistrationClient.CreateResourceMutatingWebhookConfiguration(); err != nil { - return err - } - glog.Infof("Mutating webhook registered") - } - - return nil -} - -func (ws *WebhookServer) deregisterWebhookConfigurations(policy kyverno.ClusterPolicy) error { - policies, _ := ws.pLister.List(labels.NewSelector()) - - // deregister webhook if no mutate/validate policy found in cluster - if !HasMutateOrValidatePolicies(policies) { - ws.webhookRegistrationClient.RemoveResourceMutatingWebhookConfiguration() - glog.Infoln("Mutating webhook deregistered") - } - - return nil -} - -func HasMutateOrValidatePolicies(policies []*kyverno.ClusterPolicy) bool { - for _, policy := range policies { - if HasMutateOrValidate(*policy) { - return true - } - } - return false -} - -func HasMutateOrValidate(policy kyverno.ClusterPolicy) bool { - for _, rule := range policy.Spec.Rules { - if !reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) || !reflect.DeepEqual(rule.Validation, kyverno.Validation{}) { - glog.V(4).Infoln(rule.Name) - return true - } - } - return false -} From 7a43bed8e447429479abcf534762331d3c1ba883 Mon Sep 17 00:00:00 2001 From: shivkumar dudhani <shivkumar@nirmata.com> Date: Wed, 4 Sep 2019 14:06:06 -0700 Subject: [PATCH 3/5] remove commented code + fix log param --- pkg/config/config.go | 3 --- pkg/policy/controller.go | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 130e7c7f6d..0fc8a9fe48 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -36,9 +36,6 @@ var ( ValidatingWebhookServicePath = "/validate" PolicyValidatingWebhookServicePath = "/policyvalidate" PolicyMutatingWebhookServicePath = "/policymutate" - // KubePolicyAppLabels = map[string]string{ - // "app": "kyverno", - // } SupportedKinds = []string{ "ConfigMap", diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go index 3938ea50d0..a29a91e4cd 100644 --- a/pkg/policy/controller.go +++ b/pkg/policy/controller.go @@ -410,7 +410,7 @@ func (pc *PolicyController) syncPolicy(key string) error { // remove webhook configurations if there are not policies if err := pc.removeResourceWebhookConfiguration(); err != nil { // do not fail, if unable to delete resource webhook config - glog.V(4).Info("failed to remove resource webhook configuration: %v", err) + glog.V(4).Infof("failed to remove resource webhook configuration: %v", err) glog.Errorln(err) } return nil @@ -911,4 +911,3 @@ func convertRules(rules []RuleStatinfo) []kyverno.RuleStats { } return stats } - From 90a7282b978506fdb40e9b6a6516c2c80b7acd3f Mon Sep 17 00:00:00 2001 From: shivkumar dudhani <shivkumar@nirmata.com> Date: Wed, 4 Sep 2019 14:09:42 -0700 Subject: [PATCH 4/5] remove log --- pkg/webhooks/policyvalidation.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/webhooks/policyvalidation.go b/pkg/webhooks/policyvalidation.go index 0e54b64340..6a047a9c5d 100644 --- a/pkg/webhooks/policyvalidation.go +++ b/pkg/webhooks/policyvalidation.go @@ -35,7 +35,6 @@ func (ws *WebhookServer) handlePolicyValidation(request *v1beta1.AdmissionReques hasMutateOrValidate := func() bool { for _, rule := range policy.Spec.Rules { if !reflect.DeepEqual(rule.Mutation, kyverno.Mutation{}) || !reflect.DeepEqual(rule.Validation, kyverno.Validation{}) { - glog.Infoln(rule.Name) return true } } From 973abe6233c79f60148dff3fe0a8b7827049f3d5 Mon Sep 17 00:00:00 2001 From: shivkumar dudhani <shivkumar@nirmata.com> Date: Wed, 4 Sep 2019 15:30:09 -0700 Subject: [PATCH 5/5] ignore creationg of event and PV if Name is not assgined. --- pkg/event/controller.go | 7 ++++++- pkg/policyviolation/helpers.go | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/event/controller.go b/pkg/event/controller.go index 2a5f3cb3ef..ac66f7356d 100644 --- a/pkg/event/controller.go +++ b/pkg/event/controller.go @@ -71,6 +71,12 @@ func initRecorder(client *client.Client) record.EventRecorder { //Add queues an event for generation func (gen *Generator) Add(infos ...Info) { for _, info := range infos { + if info.Name == "" { + // dont create event for resources with generateName + // as the name is not generated yet + glog.V(4).Infof("recieved info %v, not creating an event as the resource has not been assigned a name yet", info) + continue + } gen.queue.Add(info) } } @@ -140,7 +146,6 @@ func (gen *Generator) processNextWorkItem() bool { func (gen *Generator) syncHandler(key Info) error { var robj runtime.Object var err error - switch key.Kind { case "Policy": //TODO: policy is clustered resource so wont need namespace diff --git a/pkg/policyviolation/helpers.go b/pkg/policyviolation/helpers.go index cd7a6b36b3..d96f654a02 100644 --- a/pkg/policyviolation/helpers.go +++ b/pkg/policyviolation/helpers.go @@ -81,6 +81,11 @@ func buildPVForPolicy(er engine.EngineResponseNew) kyverno.ClusterPolicyViolatio func CreatePV(pvLister kyvernolister.ClusterPolicyViolationLister, client *kyvernoclient.Clientset, engineResponses []engine.EngineResponseNew) { var pvs []kyverno.ClusterPolicyViolation for _, er := range engineResponses { + // ignore creation of PV for resoruces that are yet to be assigned a name + if er.PolicyResponse.Resource.Name == "" { + glog.V(4).Infof("resource %v, has not been assigned a name. not creating a policy violation for it", er.PolicyResponse.Resource) + continue + } if !er.IsSuccesful() { if pv := buildPVForPolicy(er); !reflect.DeepEqual(pv, kyverno.ClusterPolicyViolation{}) { pvs = append(pvs, pv)