From 5dab189743560b41040a34571465ab3c16f8442a Mon Sep 17 00:00:00 2001 From: shivkumar dudhani Date: Thu, 12 Sep 2019 15:04:35 -0700 Subject: [PATCH] fix event resource name + add filtered kinds to policy controller & namespace + fix messages --- pkg/engine/generation.go | 24 ++++++++++++------------ pkg/engine/validation_test.go | 4 ++-- pkg/event/controller.go | 2 +- pkg/kyverno/apply/apply.go | 2 +- pkg/namespace/controller.go | 23 ++++++++++++++++++----- pkg/namespace/report.go | 16 ++++++++-------- pkg/policy/controller.go | 3 ++- pkg/policy/existing.go | 25 ++++++++++++------------- pkg/policy/report.go | 14 +++++++------- pkg/webhooks/report.go | 4 ++-- 10 files changed, 65 insertions(+), 52 deletions(-) diff --git a/pkg/engine/generation.go b/pkg/engine/generation.go index 23903e505a..b841f655cf 100644 --- a/pkg/engine/generation.go +++ b/pkg/engine/generation.go @@ -78,19 +78,19 @@ func applyRuleGenerator(client *client.Client, ns unstructured.Unstructured, rul // check if the rule is create, if yes, then verify if the specified configuration is present in the resource ok, err := checkResource(rule.Generation.Data, obj) if err != nil { - glog.V(4).Infof("generate rule:: unable to check if configuration %v, is present in resource %s/%s/%s", rule.Generation.Data, rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + glog.V(4).Infof("generate rule: unable to check if configuration %v, is present in resource '%s/%s' in namespace '%s'", rule.Generation.Data, rule.Generation.Kind, rule.Generation.Name, ns.GetName()) response.Success = false - response.Message = fmt.Sprintf("unable to check if configuration %v, is present in resource %s/%s/%s", rule.Generation.Data, rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + response.Message = fmt.Sprintf("unable to check if configuration %v, is present in resource '%s/%s' in namespace '%s'", rule.Generation.Data, rule.Generation.Kind, rule.Generation.Name, ns.GetName()) return response } if !ok { - glog.V(4).Infof("generate rule:: configuration %v not present in resource %s/%s/%s", rule.Generation.Data, rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + glog.V(4).Infof("generate rule: configuration %v not present in resource '%s/%s' in namespace '%s'", rule.Generation.Data, rule.Generation.Kind, rule.Generation.Name, ns.GetName()) response.Success = false - response.Message = fmt.Sprintf("configuration %v not present in resource %s/%s/%s", rule.Generation.Data, rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + response.Message = fmt.Sprintf("configuration %v not present in resource '%s/%s' in namespace '%s'", rule.Generation.Data, rule.Generation.Kind, rule.Generation.Name, ns.GetName()) return response } response.Success = true - response.Message = fmt.Sprintf("required configuration %v is present in resource %s/%s/%s", rule.Generation.Data, rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + response.Message = fmt.Sprintf("required configuration %v is present in resource '%s/%s' in namespace '%s'", rule.Generation.Data, rule.Generation.Kind, rule.Generation.Name, ns.GetName()) return response } rdata, err = runtime.DefaultUnstructuredConverter.ToUnstructured(&rule.Generation.Data) @@ -106,26 +106,26 @@ func applyRuleGenerator(client *client.Client, ns unstructured.Unstructured, rul // 1> Check if resource exists _, err := client.GetResource(rule.Generation.Kind, ns.GetName(), rule.Generation.Name) if err == nil { - glog.V(4).Infof("generate rule: resource %s/%s/%s already present", rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + glog.V(4).Infof("generate rule: resource '%s/%s' already present in namespace '%s'", rule.Generation.Kind, rule.Generation.Name, ns.GetName()) response.Success = true - response.Message = fmt.Sprintf("resource %s/%s/%s already present", rule.Generation.Kind, ns.GetName(), rule.Generation.Name) + response.Message = fmt.Sprintf("resource '%s/%s' already present in namespace '%s'", rule.Generation.Kind, rule.Generation.Name, ns.GetName()) return response } // 2> If clone already exists return resource, err = client.GetResource(rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name) if err != nil { - glog.V(4).Infof("generate rule: clone reference resource %s/%s/%s not present: %v", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name, err) + glog.V(4).Infof("generate rule: clone reference resource '%s/%s' not present in namespace '%s': %v", rule.Generation.Kind, rule.Generation.Clone.Name, rule.Generation.Clone.Namespace, err) response.Success = false - response.Message = fmt.Sprintf("clone reference resource %s/%s/%s not present: %v", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name, err) + response.Message = fmt.Sprintf("clone reference resource '%s/%s' not present in namespace '%s': %v", rule.Generation.Kind, rule.Generation.Clone.Name, rule.Generation.Clone.Namespace, err) return response } - glog.V(4).Infof("generate rule: clone reference resource %s/%s/%s present", rule.Generation.Kind, rule.Generation.Clone.Namespace, rule.Generation.Clone.Name) + glog.V(4).Infof("generate rule: clone reference resource '%s/%s' present in namespace '%s'", rule.Generation.Kind, rule.Generation.Clone.Name, rule.Generation.Clone.Namespace) rdata = resource.UnstructuredContent() } if processExisting { - glog.V(4).Infof("resource %s not found in existing namespace %s", rule.Generation.Name, ns.GetName()) + glog.V(4).Infof("resource '%s/%s' not found in existing namespace '%s'", rule.Generation.Kind, rule.Generation.Name, ns.GetName()) response.Success = false - response.Message = fmt.Sprintf("resource %s not found in existing namespace %s", rule.Generation.Name, ns.GetName()) + response.Message = fmt.Sprintf("resource '%s/%s' not found in existing namespace '%s'", rule.Generation.Kind, rule.Generation.Name, ns.GetName()) // for existing resources we generate an error which indirectly generates a policy violation return response } diff --git a/pkg/engine/validation_test.go b/pkg/engine/validation_test.go index 79a3637ea5..94d06537ca 100644 --- a/pkg/engine/validation_test.go +++ b/pkg/engine/validation_test.go @@ -1505,7 +1505,7 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) { func TestValidate_ServiceTest(t *testing.T) { rawPolicy := []byte(`{ "apiVersion":"kyverno.nirmata.io/v1alpha1", - "kind":"Policy", + "kind":"ClusterPolicy", "metadata":{ "name":"policy-service" }, @@ -1597,7 +1597,7 @@ func TestValidate_ServiceTest(t *testing.T) { func TestValidate_MapHasFloats(t *testing.T) { rawPolicy := []byte(`{ "apiVersion":"kyverno.nirmata.io/v1alpha1", - "kind":"Policy", + "kind":"ClusterPolicy", "metadata":{ "name":"policy-deployment-changed" }, diff --git a/pkg/event/controller.go b/pkg/event/controller.go index ac66f7356d..03d27cb621 100644 --- a/pkg/event/controller.go +++ b/pkg/event/controller.go @@ -147,7 +147,7 @@ func (gen *Generator) syncHandler(key Info) error { var robj runtime.Object var err error switch key.Kind { - case "Policy": + case "ClusterPolicy": //TODO: policy is clustered resource so wont need namespace robj, err = gen.pLister.Get(key.Name) if err != nil { diff --git a/pkg/kyverno/apply/apply.go b/pkg/kyverno/apply/apply.go index 468c730d61..36af12ce40 100644 --- a/pkg/kyverno/apply/apply.go +++ b/pkg/kyverno/apply/apply.go @@ -147,7 +147,7 @@ func extractPolicy(fileDir string) (*kyverno.ClusterPolicy, error) { return nil, fmt.Errorf("failed to decode policy %s, err: %v", policy.Name, err) } - if policy.TypeMeta.Kind != "Policy" { + if policy.TypeMeta.Kind != "ClusterPolicy" { return nil, fmt.Errorf("failed to parse policy") } diff --git a/pkg/namespace/controller.go b/pkg/namespace/controller.go index 439b73d678..35db2a8cda 100644 --- a/pkg/namespace/controller.go +++ b/pkg/namespace/controller.go @@ -9,6 +9,7 @@ import ( client "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/event" "github.com/nirmata/kyverno/pkg/policy" + "github.com/nirmata/kyverno/pkg/utils" "k8s.io/apimachinery/pkg/api/errors" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" @@ -53,6 +54,8 @@ type NamespaceController struct { queue workqueue.RateLimitingInterface // Resource manager, manages the mapping for already processed resource rm resourceManager + // filter the resources defined in the list + filterK8Resources []utils.K8Resource } //NewNamespaceController returns a new Controller to manage generation rules @@ -62,14 +65,16 @@ func NewNamespaceController(kyvernoClient *kyvernoclient.Clientset, pInformer kyvernoinformer.ClusterPolicyInformer, pvInformer kyvernoinformer.ClusterPolicyViolationInformer, policyStatus policy.PolicyStatusInterface, - eventGen event.Interface) *NamespaceController { + eventGen event.Interface, + filterK8Resources string) *NamespaceController { //TODO: do we need to event recorder for this controller? // create the controller nsc := &NamespaceController{ - client: client, - kyvernoClient: kyvernoClient, - eventGen: eventGen, - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"), + client: client, + kyvernoClient: kyvernoClient, + eventGen: eventGen, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "namespace"), + filterK8Resources: utils.ParseKinds(filterK8Resources), } nsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -201,6 +206,14 @@ func (nsc *NamespaceController) syncNamespace(key string) error { // TODO: Deep-copy only when needed. n := namespace.DeepCopy() + // skip processing namespace if its been filtered + // exclude the filtered resources + if utils.SkipFilteredResources("Namespace", "", namespace.Name, nsc.filterK8Resources) { + //TODO: improve the text + glog.V(4).Infof("excluding namespace %s as its a filtered resource",namespace.Name ) + return nil + } + // process generate rules engineResponses := nsc.processNamespace(*n) // report errors diff --git a/pkg/namespace/report.go b/pkg/namespace/report.go index afb3f3f9ef..666a67f26b 100644 --- a/pkg/namespace/report.go +++ b/pkg/namespace/report.go @@ -29,29 +29,29 @@ func reportEvents(engineResponse engine.EngineResponseNew, eventGen event.Interf if engineResponse.IsSuccesful() { return } - glog.V(4).Infof("reporting results for policy %s application on resource %s/%s/%s", engineResponse.PolicyResponse.Policy, engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) + glog.V(4).Infof("reporting results for policy '%s' application on resource '%s/%s/%s'", engineResponse.PolicyResponse.Policy, engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) for _, rule := range engineResponse.PolicyResponse.Rules { if rule.Success { return } // generate event on resource for each failed rule - glog.V(4).Infof("generation event on resource %s/%s/%s for policy %s", engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name, engineResponse.PolicyResponse.Policy) + glog.V(4).Infof("generation event on resource '%s/%s' for policy '%s'", engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Name, engineResponse.PolicyResponse.Policy) e := event.Info{} e.Kind = engineResponse.PolicyResponse.Resource.Kind - e.Namespace = engineResponse.PolicyResponse.Resource.Namespace - e.Name = engineResponse.PolicyResponse.Policy + e.Namespace = "" // event generate on namespace resource + e.Name = engineResponse.PolicyResponse.Resource.Name e.Reason = "Failure" - e.Message = fmt.Sprintf("policy %s (%s) rule %s failed to apply. %v", engineResponse.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) + e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' failed to apply. %v", engineResponse.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) eventGen.Add(e) } // generate a event on policy for all failed rules - glog.V(4).Infof("generation event on policy %s", engineResponse.PolicyResponse.Policy) + glog.V(4).Infof("generation event on policy '%s'", engineResponse.PolicyResponse.Policy) e := event.Info{} - e.Kind = "Policy" + e.Kind = "ClusterPolicy" e.Namespace = "" e.Name = engineResponse.PolicyResponse.Policy e.Reason = "Failure" - e.Message = fmt.Sprintf("failed to apply rules %v on resource %s/%s/%s", engineResponse.GetFailedRules(), engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) + e.Message = fmt.Sprintf("failed to apply policy '%s' rules '%v' on resource '%s/%s/%s'", engineResponse.PolicyResponse.Policy, engineResponse.GetFailedRules(), engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) eventGen.Add(e) } diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go index a29a91e4cd..9e39b357a1 100644 --- a/pkg/policy/controller.go +++ b/pkg/policy/controller.go @@ -81,7 +81,7 @@ type PolicyController struct { // NewPolicyController create a new PolicyController func NewPolicyController(kyvernoClient *kyvernoclient.Clientset, client *client.Client, pInformer kyvernoinformer.ClusterPolicyInformer, pvInformer kyvernoinformer.ClusterPolicyViolationInformer, - eventGen event.Interface, webhookInformer webhookinformer.MutatingWebhookConfigurationInformer, webhookRegistrationClient *webhookconfig.WebhookRegistrationClient) (*PolicyController, error) { + eventGen event.Interface, webhookInformer webhookinformer.MutatingWebhookConfigurationInformer, webhookRegistrationClient *webhookconfig.WebhookRegistrationClient, filterK8Resources string) (*PolicyController, error) { // Event broad caster eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartLogging(glog.Infof) @@ -98,6 +98,7 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset, client *client. eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "policy_controller"}), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "policy"), webhookRegistrationClient: webhookRegistrationClient, + filterK8Resources: utils.ParseKinds(filterK8Resources), } pc.pvControl = RealPVControl{Client: kyvernoClient, Recorder: pc.eventRecorder} diff --git a/pkg/policy/existing.go b/pkg/policy/existing.go index 468b6de442..7c84baa47d 100644 --- a/pkg/policy/existing.go +++ b/pkg/policy/existing.go @@ -66,8 +66,6 @@ func listResources(client *client.Client, policy kyverno.ClusterPolicy, filterK8 // get all namespaces namespaces = getAllNamespaces(client) } - // check if exclude namespace is not clashing - // namespaces = excludeNamespaces(namespaces, rule.ExcludeResources.Namespaces) // get resources in the namespaces for _, ns := range namespaces { @@ -101,13 +99,6 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri continue } } - // // exclude name - // if rule.ExcludeResources.Name != "" { - // if wildcard.Match(rule.ExcludeResources.Name, r.GetName()) { - // glog.V(4).Infof("skipping resource %s/%s due to exclude condition name=%s mistatch", r.GetNamespace(), r.GetName(), rule.MatchResources.Name) - // continue - // } - // } // Skip the filtered resources if utils.SkipFilteredResources(r.GetKind(), r.GetNamespace(), r.GetName(), filterK8Resources) { continue @@ -117,13 +108,14 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri resourceMap[string(r.GetUID())] = r } - // All the included resource - // Need to exclude - excludeResources(resourceMap, rule.ExcludeResources.ResourceDescription) + // exclude the resources + // skip resources to be filtered + excludeResources(resourceMap, rule.ExcludeResources.ResourceDescription, filterK8Resources) + // glog.V(4).Infof("resource map: %v", resourceMap) return resourceMap } -func excludeResources(included map[string]unstructured.Unstructured, exclude kyverno.ResourceDescription) { +func excludeResources(included map[string]unstructured.Unstructured, exclude kyverno.ResourceDescription, filterK8Resources []utils.K8Resource) { if reflect.DeepEqual(exclude, (kyverno.ResourceDescription{})) { return } @@ -203,6 +195,13 @@ func excludeResources(included map[string]unstructured.Unstructured, exclude kyv if ret := excludeKind(resource.GetKind()); ret != NotEvaluate { excludeEval = append(excludeEval, ret) } + // exclude the filtered resources + if utils.SkipFilteredResources(resource.GetKind(), resource.GetNamespace(), resource.GetName(), filterK8Resources) { + //TODO: improve the text + glog.V(4).Infof("excluding resource %s/%s/%s as its satisfies the filtered resources", resource.GetKind(), resource.GetNamespace(), resource.GetName()) + delete(included, uid) + continue + } func() bool { for _, ret := range excludeEval { diff --git a/pkg/policy/report.go b/pkg/policy/report.go index 10e715d252..13ca8f7e44 100644 --- a/pkg/policy/report.go +++ b/pkg/policy/report.go @@ -30,31 +30,31 @@ func reportEvents(engineResponse engine.EngineResponseNew, eventGen event.Interf if engineResponse.IsSuccesful() { return } - glog.V(4).Infof("reporting results for policy %s application on resource %s/%s/%s", engineResponse.PolicyResponse.Policy, engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) + glog.V(4).Infof("reporting results for policy '%s' application on resource '%s/%s/%s'", engineResponse.PolicyResponse.Policy, engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) for _, rule := range engineResponse.PolicyResponse.Rules { if rule.Success { return } // generate event on resource for each failed rule - glog.V(4).Infof("generation event on resource %s/%s/%s for policy %s", engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name, engineResponse.PolicyResponse.Policy) + glog.V(4).Infof("generation event on resource '%s/%s/%s' for policy '%s'", engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name, engineResponse.PolicyResponse.Policy) e := event.Info{} e.Kind = engineResponse.PolicyResponse.Resource.Kind e.Namespace = engineResponse.PolicyResponse.Resource.Namespace - e.Name = engineResponse.PolicyResponse.Policy + e.Name = engineResponse.PolicyResponse.Resource.Name e.Reason = "Failure" - e.Message = fmt.Sprintf("policy %s (%s) rule %s failed to apply. %v", engineResponse.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) + e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' failed to apply. %v", engineResponse.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) eventGen.Add(e) } // generate a event on policy for all failed rules - glog.V(4).Infof("generation event on policy %s", engineResponse.PolicyResponse.Policy) + glog.V(4).Infof("generation event on policy '%s'", engineResponse.PolicyResponse.Policy) e := event.Info{} - e.Kind = "Policy" + e.Kind = "ClusterPolicy" e.Namespace = "" e.Name = engineResponse.PolicyResponse.Policy e.Reason = "Failure" - e.Message = fmt.Sprintf("failed to apply rules %v on resource %s/%s/%s", engineResponse.GetFailedRules(), engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) + e.Message = fmt.Sprintf("failed to apply policy '%s' rules '%v' on resource '%s/%s/%s'", engineResponse.PolicyResponse.Policy, engineResponse.GetFailedRules(), engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) eventGen.Add(e) } diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index ab446254ca..d1860830ee 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -40,7 +40,7 @@ func generateEvents(engineResponses []engine.EngineResponseNew, onUpdate bool) [ // event on policy e = event.NewEventNew( - "Policy", + "ClusterPolicy", kyverno.SchemeGroupVersion.String(), "", er.PolicyResponse.Policy, @@ -56,7 +56,7 @@ func generateEvents(engineResponses []engine.EngineResponseNew, onUpdate bool) [ // CREATE // event on policy e := event.NewEventNew( - "Policy", + "ClusterPolicy", kyverno.SchemeGroupVersion.String(), "", er.PolicyResponse.Policy,