diff --git a/.gitignore b/.gitignore index 0117c88617..d8cbb60872 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ coverage.txt cmd/initContainer/kyvernopre cmd/kyverno/kyverno cmd/cli/kubectl-kyverno/kyverno +kubectl-kyverno diff --git a/pkg/event/builder_test.go b/pkg/event/builder_test.go index 210487c98e..17588ac77e 100644 --- a/pkg/event/builder_test.go +++ b/pkg/event/builder_test.go @@ -9,8 +9,9 @@ import ( func TestPositive(t *testing.T) { resourceName := "test_resource" - expectedMsg := fmt.Sprintf("Policy applied successfully on the resource '%s'", resourceName) - msg, err := getEventMsg(SPolicyApply, resourceName) + ruleName := "test_rule" + expectedMsg := fmt.Sprintf("Rule(s) '%s' failed to apply on resource %s", ruleName, resourceName) + msg, err := getEventMsg(FPolicyApplyFailed, ruleName, resourceName) assert.NilError(t, err) assert.Equal(t, expectedMsg, msg) } @@ -18,6 +19,6 @@ func TestPositive(t *testing.T) { // passing incorrect args func TestIncorrectArgs(t *testing.T) { resourceName := "test_resource" - _, err := getEventMsg(SPolicyApply, resourceName, "extra_args") - assert.Error(t, err, "message expects 1 arguments, but 2 arguments passed") + _, err := getEventMsg(FPolicyApplyFailed, resourceName, "extra_args1", "extra_args2") + assert.Error(t, err, "message expects 2 arguments, but 3 arguments passed") } diff --git a/pkg/event/controller.go b/pkg/event/controller.go index c6f91da4a3..480bd29862 100644 --- a/pkg/event/controller.go +++ b/pkg/event/controller.go @@ -1,9 +1,10 @@ package event import ( - "github.com/go-logr/logr" "time" + "github.com/go-logr/logr" + "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" @@ -192,9 +193,6 @@ func (gen *Generator) syncHandler(key Info) error { // set the event type based on reason eventType := v1.EventTypeWarning - if key.Reason == PolicyApplied.String() { - eventType = v1.EventTypeNormal - } // based on the source of event generation, use different event recorders switch key.Source { diff --git a/pkg/event/msgbuilder.go b/pkg/event/msgbuilder.go index 61db77033f..387e7d9fea 100644 --- a/pkg/event/msgbuilder.go +++ b/pkg/event/msgbuilder.go @@ -10,11 +10,7 @@ type MsgKey int //Message id for pre-defined messages const ( - FResourcePolcy MsgKey = iota - FProcessRule - SPolicyApply - SRulesApply - FPolicyApplyBlockCreate + FPolicyApplyBlockCreate MsgKey = iota FPolicyApplyBlockUpdate FPolicyBlockResourceUpdate FPolicyApplyFailed @@ -23,10 +19,6 @@ const ( func (k MsgKey) String() string { return [...]string{ - "Policy violation on resource '%s'. The rule(s) '%s' not satisfied", - "Failed to process rule '%s' of policy '%s'.", - "Policy applied successfully on the resource '%s'", - "Rule(s) '%s' of Policy '%s' applied successfully", "Resource %s creation blocked by rule(s) %s", "Rule(s) '%s' of policy '%s' blocked update of the resource", "Resource %s update blocked by rule(s) %s", diff --git a/pkg/event/reason.go b/pkg/event/reason.go index a29c0ad36c..1de55d07f3 100644 --- a/pkg/event/reason.go +++ b/pkg/event/reason.go @@ -6,8 +6,6 @@ type Reason int const ( //PolicyViolation there is a violation of policy PolicyViolation Reason = iota - //PolicyApplied policy applied - PolicyApplied //RequestBlocked the request to create/update the resource was blocked( generated from admission-controller) RequestBlocked //PolicyFailed policy failed @@ -17,7 +15,6 @@ const ( func (r Reason) String() string { return [...]string{ "PolicyViolation", - "PolicyApplied", "RequestBlocked", "PolicyFailed", }[r] diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go index c1c848c73d..7d5a24db70 100644 --- a/pkg/generate/generate.go +++ b/pkg/generate/generate.go @@ -22,6 +22,7 @@ func (c *Controller) processGR(gr *kyverno.GenerateRequest) error { var err error var resource *unstructured.Unstructured var genResources []kyverno.ResourceSpec + // 1 - Check if the resource exists resource, err = getResource(c.client, gr.Spec.Resource) if err != nil { @@ -29,10 +30,14 @@ func (c *Controller) processGR(gr *kyverno.GenerateRequest) error { logger.Error(err, "resource does not exist or is yet to be created, requeueing") return err } + // 2 - Apply the generate policy on the resource genResources, err = c.applyGenerate(*resource, *gr) + // 3 - Report Events - reportEvents(logger, err, c.eventGen, *gr, *resource) + events := failedEvents(err, *gr, *resource) + c.eventGen.Add(events...) + // 4 - Update Status return updateStatus(c.statusControl, *gr, err, genResources) } @@ -47,16 +52,16 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern policy, err := c.pLister.Get(gr.Spec.Policy) if err != nil { if apierrors.IsNotFound(err) { - for _,e := range gr.Status.GeneratedResources { - resp, err := c.client.GetResource(e.Kind,e.Namespace,e.Name); + for _, e := range gr.Status.GeneratedResources { + resp, err := c.client.GetResource(e.Kind, e.Namespace, e.Name) if err != nil { - logger.Error(err,"Generated resource failed to get","Resource",e.Name) + logger.Error(err, "Generated resource failed to get", "Resource", e.Name) } labels := resp.GetLabels() if labels["policy.kyverno.io/synchronize"] == "enable" { if err := c.client.DeleteResource(resp.GetKind(), resp.GetNamespace(), resp.GetName(), false); err != nil { - logger.Error(err,"Generated resource is not deleted","Resource",e.Name) + logger.Error(err, "Generated resource is not deleted", "Resource", e.Name) } } } @@ -135,7 +140,7 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P continue } startTime := time.Now() - genResource, err := applyRule(log, c.client, rule, resource, ctx, processExisting,policy.Name) + genResource, err := applyRule(log, c.client, rule, resource, ctx, processExisting, policy.Name) if err != nil { return nil, err } @@ -192,7 +197,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond } -func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, processExisting bool,policy string) (kyverno.ResourceSpec, error) { +func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, processExisting bool, policy string) (kyverno.ResourceSpec, error) { var rdata map[string]interface{} var err error var mode ResourceMode diff --git a/pkg/generate/report.go b/pkg/generate/report.go index f9d24fcc10..3cc786ed6e 100644 --- a/pkg/generate/report.go +++ b/pkg/generate/report.go @@ -3,38 +3,13 @@ package generate import ( "fmt" - "github.com/go-logr/logr" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/event" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -func reportEvents(log logr.Logger, err error, eventGen event.Interface, gr kyverno.GenerateRequest, resource unstructured.Unstructured) { - if err == nil { - // Success Events - // - resource -> policy rule applied successfully - // - policy -> rule successfully applied on resource - events := successEvents(gr, resource) - eventGen.Add(events...) - return - } - events := failedEvents(err, gr, resource) - eventGen.Add(events...) -} - func failedEvents(err error, gr kyverno.GenerateRequest, resource unstructured.Unstructured) []event.Info { - var events []event.Info - // Cluster Policy - pe := event.Info{} - pe.Kind = "ClusterPolicy" - // cluserwide-resource - pe.Name = gr.Spec.Policy - pe.Reason = event.PolicyFailed.String() - pe.Source = event.GeneratePolicyController - pe.Message = fmt.Sprintf("policy failed to apply on resource %s/%s/%s: %v", resource.GetKind(), resource.GetNamespace(), resource.GetName(), err) - events = append(events, pe) - // Resource re := event.Info{} re.Kind = resource.GetKind() re.Namespace = resource.GetNamespace() @@ -42,32 +17,6 @@ func failedEvents(err error, gr kyverno.GenerateRequest, resource unstructured.U re.Reason = event.PolicyFailed.String() re.Source = event.GeneratePolicyController re.Message = fmt.Sprintf("policy %s failed to apply: %v", gr.Spec.Policy, err) - events = append(events, re) - return events -} - -func successEvents(gr kyverno.GenerateRequest, resource unstructured.Unstructured) []event.Info { - var events []event.Info - // Cluster Policy - pe := event.Info{} - pe.Kind = "ClusterPolicy" - // clusterwide-resource - pe.Name = gr.Spec.Policy - pe.Reason = event.PolicyApplied.String() - pe.Source = event.GeneratePolicyController - pe.Message = fmt.Sprintf("applied successfully on resource %s/%s/%s", resource.GetKind(), resource.GetNamespace(), resource.GetName()) - events = append(events, pe) - - // Resource - re := event.Info{} - re.Kind = resource.GetKind() - re.Namespace = resource.GetNamespace() - re.Name = resource.GetName() - re.Reason = event.PolicyApplied.String() - re.Source = event.GeneratePolicyController - re.Message = fmt.Sprintf("policy %s successfully applied", gr.Spec.Policy) - events = append(events, re) - - return events + return []event.Info{re} } diff --git a/pkg/policy/report.go b/pkg/policy/report.go index 726074c7cd..54f5142dc9 100644 --- a/pkg/policy/report.go +++ b/pkg/policy/report.go @@ -42,9 +42,11 @@ func generateEvents(log logr.Logger, ers []response.EngineResponse) []event.Info } func generateEventsPerEr(log logr.Logger, er response.EngineResponse) []event.Info { - logger := log.WithValues("policy", er.PolicyResponse.Policy, "kind", er.PolicyResponse.Resource.Kind, "namespace", er.PolicyResponse.Resource.Namespace, "name", er.PolicyResponse.Resource.Name) var eventInfos []event.Info + + logger := log.WithValues("policy", er.PolicyResponse.Policy, "kind", er.PolicyResponse.Resource.Kind, "namespace", er.PolicyResponse.Resource.Namespace, "name", er.PolicyResponse.Resource.Name) logger.V(4).Info("reporting results for policy") + for _, rule := range er.PolicyResponse.Rules { if rule.Success { continue @@ -57,22 +59,9 @@ func generateEventsPerEr(log logr.Logger, er response.EngineResponse) []event.In e.Name = er.PolicyResponse.Resource.Name e.Reason = event.PolicyViolation.String() e.Source = event.PolicyController - e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' not satisfied. %v", er.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) + e.Message = fmt.Sprintf("policy '%s' (%s) rule '%s' failed. %v", er.PolicyResponse.Policy, rule.Type, rule.Name, rule.Message) eventInfos = append(eventInfos, e) } - if er.IsSuccessful() { - return eventInfos - } - // generate a event on policy for all failed rules - logger.V(4).Info("generating event on policy") - e := event.Info{} - e.Kind = "ClusterPolicy" - e.Namespace = "" - e.Name = er.PolicyResponse.Policy - e.Reason = event.PolicyViolation.String() - e.Source = event.PolicyController - e.Message = fmt.Sprintf("policy '%s' rules '%v' not satisfied on resource '%s/%s/%s'", er.PolicyResponse.Policy, er.GetFailedRules(), er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name) - eventInfos = append(eventInfos, e) return eventInfos } diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go index 8e31a4ed17..251f822c0d 100644 --- a/pkg/webhooks/generation.go +++ b/pkg/webhooks/generation.go @@ -189,18 +189,6 @@ func (resp generateRequestResponse) error() string { } func failedEvents(err error, gr kyverno.GenerateRequestSpec, resource unstructured.Unstructured) []event.Info { - var events []event.Info - // Cluster Policy - pe := event.Info{} - pe.Kind = "ClusterPolicy" - // cluserwide-resource - pe.Name = gr.Policy - pe.Reason = event.PolicyFailed.String() - pe.Source = event.GeneratePolicyController - pe.Message = fmt.Sprintf("policy failed to apply on resource %s/%s/%s: %v", resource.GetKind(), resource.GetNamespace(), resource.GetName(), err) - events = append(events, pe) - - // Resource re := event.Info{} re.Kind = resource.GetKind() re.Namespace = resource.GetNamespace() @@ -208,7 +196,6 @@ func failedEvents(err error, gr kyverno.GenerateRequestSpec, resource unstructur re.Reason = event.PolicyFailed.String() re.Source = event.GeneratePolicyController re.Message = fmt.Sprintf("policy %s failed to apply: %v", gr.Policy, err) - events = append(events, re) - return events + return []event.Info{re} } diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index 5dadccc553..da6520e6da 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -4,8 +4,6 @@ import ( "strings" "github.com/go-logr/logr" - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "github.com/nirmata/kyverno/pkg/common" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/event" @@ -14,101 +12,23 @@ import ( //generateEvents generates event info for the engine responses func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate bool, log logr.Logger) []event.Info { var events []event.Info - // Scenario 1 - // - Admission-Response is SUCCESS && CREATE - // - All policies were succesfully - // - report event on resources - if isResponseSuccesful(engineResponses) { - if !onUpdate { - // we only report events on CREATE requests - return events - } - for _, er := range engineResponses { - successRules := er.GetSuccessRules() - successRulesStr := strings.Join(successRules, ";") - // event on resource - e := event.NewEvent( - log, - er.PolicyResponse.Resource.Kind, - er.PolicyResponse.Resource.APIVersion, - er.PolicyResponse.Resource.Namespace, - er.PolicyResponse.Resource.Name, - event.PolicyApplied.String(), - event.AdmissionController, - event.SRulesApply, - successRulesStr, - er.PolicyResponse.Policy, - ) - events = append(events, e) - } - return events - } - // Scneario 2 - // - Admission-Response is BLOCKED - // - report event of policy is in enforce mode and failed to apply - if blocked { - for _, er := range engineResponses { - if er.IsSuccessful() { - // do not create event on polices that were succesfuly - continue - } - if er.PolicyResponse.ValidationFailureAction != common.Enforce { - // do not create event on "audit" policy - continue - } - // Rules that failed - failedRules := er.GetFailedRules() - filedRulesStr := strings.Join(failedRules, ";") - // Event on Policy - e := event.NewEvent( - log, - "ClusterPolicy", - kyverno.SchemeGroupVersion.String(), - "", - er.PolicyResponse.Policy, - event.RequestBlocked.String(), - event.AdmissionController, - event.FPolicyBlockResourceUpdate, - er.PolicyResponse.Resource.GetKey(), - filedRulesStr, - ) - events = append(events, e) - } - return events - } - - // Scenario 3 // - Admission-Response is SUCCESS // - Some/All policies failed (policy violations generated) - // - report event on policy that failed // - report event on resource that failed for _, er := range engineResponses { if er.IsSuccessful() { - // do not create event on polices that were succesfuly + // do not create event on rules that were succesful continue } // Rules that failed failedRules := er.GetFailedRules() filedRulesStr := strings.Join(failedRules, ";") - // Event on the policy - e := event.NewEvent( - log, - "ClusterPolicy", - kyverno.SchemeGroupVersion.String(), - "", - er.PolicyResponse.Policy, - event.PolicyFailed.String(), - event.AdmissionController, - event.FPolicyApplyFailed, - filedRulesStr, - er.PolicyResponse.Resource.GetKey(), - ) - events = append(events, e) + // Event on the resource // event on resource - e = event.NewEvent( + e := event.NewEvent( log, er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.APIVersion,