From e499264ea9616b7dfecd852d054523d4c97c22fd Mon Sep 17 00:00:00 2001 From: shivkumar dudhani Date: Wed, 19 Feb 2020 19:24:34 -0800 Subject: [PATCH 1/2] refactor events --- pkg/event/msgbuilder.go | 4 + pkg/webhooks/mutation.go | 10 ++- pkg/webhooks/report.go | 157 ++++++++++++++++++++----------------- pkg/webhooks/validation.go | 19 ++++- 4 files changed, 113 insertions(+), 77 deletions(-) diff --git a/pkg/event/msgbuilder.go b/pkg/event/msgbuilder.go index ea897ab07f..61db77033f 100644 --- a/pkg/event/msgbuilder.go +++ b/pkg/event/msgbuilder.go @@ -17,6 +17,8 @@ const ( FPolicyApplyBlockCreate FPolicyApplyBlockUpdate FPolicyBlockResourceUpdate + FPolicyApplyFailed + FResourcePolicyFailed ) func (k MsgKey) String() string { @@ -28,6 +30,8 @@ func (k MsgKey) String() string { "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", + "Rule(s) '%s' failed to apply on resource %s", + "Rule(s) '%s' of policy '%s' failed to apply on the resource", }[k] } diff --git a/pkg/webhooks/mutation.go b/pkg/webhooks/mutation.go index b081f04ef0..3375ba1c5c 100644 --- a/pkg/webhooks/mutation.go +++ b/pkg/webhooks/mutation.go @@ -126,9 +126,15 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou // generate violation when response fails pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) ws.pvGenerator.Add(pvInfos...) - + // REPORTING EVENTS + // Scenario 1: + // some/all policies failed to apply on the resource. a policy volation is generated. + // create an event on the resource and the policy that failed + // Scenario 2: + // all policies were applied succesfully. + // create an event on the resource // ADD EVENTS - events := generateEvents(engineResponses, (request.Operation == v1beta1.Update)) + events := generateEvents(engineResponses, false, (request.Operation == v1beta1.Update)) ws.eventGen.Add(events...) sendStat(false) diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index f18946fc51..9b262fcc7c 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -6,82 +6,21 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" - "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/event" ) //generateEvents generates event info for the engine responses -func generateEvents(engineResponses []response.EngineResponse, onUpdate bool) []event.Info { +func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate bool) []event.Info { var events []event.Info - if !isResponseSuccesful(engineResponses) { - for _, er := range engineResponses { - if er.IsSuccesful() { - // dont create events on success - continue - } - // default behavior is audit - reason := event.PolicyViolation - if er.PolicyResponse.ValidationFailureAction == Enforce { - reason = event.RequestBlocked - } - failedRules := er.GetFailedRules() - filedRulesStr := strings.Join(failedRules, ";") - if onUpdate { - var e event.Info - // UPDATE - // event on resource - e = event.NewEvent( - er.PolicyResponse.Resource.Kind, - er.PolicyResponse.Resource.APIVersion, - er.PolicyResponse.Resource.Namespace, - er.PolicyResponse.Resource.Name, - reason.String(), - event.AdmissionController, - event.FPolicyApplyBlockUpdate, - filedRulesStr, - er.PolicyResponse.Policy, - ) - glog.V(4).Infof("UPDATE event on resource %s/%s/%s with policy %s", er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name, er.PolicyResponse.Policy) - events = append(events, e) - - // event on policy - e = event.NewEvent( - "ClusterPolicy", - kyverno.SchemeGroupVersion.String(), - "", - er.PolicyResponse.Policy, - reason.String(), - event.AdmissionController, - event.FPolicyBlockResourceUpdate, - er.PolicyResponse.Resource.GetKey(), - filedRulesStr, - ) - glog.V(4).Infof("UPDATE event on policy %s", er.PolicyResponse.Policy) - events = append(events, e) - - } else { - // CREATE - // event on policy - e := event.NewEvent( - "ClusterPolicy", - kyverno.SchemeGroupVersion.String(), - "", - er.PolicyResponse.Policy, - reason.String(), - event.AdmissionController, - event.FPolicyApplyBlockCreate, - er.PolicyResponse.Resource.GetKey(), - filedRulesStr, - ) - glog.V(4).Infof("CREATE event on policy %s", er.PolicyResponse.Policy) - events = append(events, e) - } + // 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 } - return events - } - if !onUpdate { - // All policies were applied successfully - // CREATE for _, er := range engineResponses { successRules := er.GetSuccessRules() successRulesStr := strings.Join(successRules, ";") @@ -99,7 +38,83 @@ func generateEvents(engineResponses []response.EngineResponse, onUpdate bool) [] ) 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.IsSuccesful() { + // do not create event on polices that were succesfuly + continue + } + if er.PolicyResponse.ValidationFailureAction != 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( + "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.IsSuccesful() { + // do not create event on polices that were succesfuly + continue + } + // Rules that failed + failedRules := er.GetFailedRules() + filedRulesStr := strings.Join(failedRules, ";") + // Event on the policy + e := event.NewEvent( + "ClusterPolicy", + kyverno.SchemeGroupVersion.String(), + "", + er.PolicyResponse.Policy, + event.PolicyFailed.String(), + event.AdmissionController, + event.FPolicyApplyFailed, + filedRulesStr, + er.PolicyResponse.Resource.GetKey(), + ) + // Event on the resource + // event on resource + e = event.NewEvent( + er.PolicyResponse.Resource.Kind, + er.PolicyResponse.Resource.APIVersion, + er.PolicyResponse.Resource.Namespace, + er.PolicyResponse.Resource.Name, + event.PolicyViolation.String(), + event.AdmissionController, + event.FResourcePolicyFailed, + filedRulesStr, + er.PolicyResponse.Policy, + ) + events = append(events, e) + } + return events } diff --git a/pkg/webhooks/validation.go b/pkg/webhooks/validation.go index c67a012ea2..cf30c61f17 100644 --- a/pkg/webhooks/validation.go +++ b/pkg/webhooks/validation.go @@ -113,11 +113,25 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol // If Validation fails then reject the request // no violations will be created on "enforce" - // the event will be reported on owner by k8s blocked := toBlockResource(engineResponses) + + // REPORTING EVENTS + // Scenario 1: + // resource is blocked, as there is a policy in "enforce" mode that failed. + // create an event on the policy to inform the resource request was blocked + // Scenario 2: + // some/all policies failed to apply on the resource. a policy volation is generated. + // create an event on the resource and the policy that failed + // Scenario 3: + // all policies were applied succesfully. + // create an event on the resource + events := generateEvents(engineResponses, blocked, (request.Operation == v1beta1.Update)) + ws.eventGen.Add(events...) if blocked { glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName()) sendStat(true) + // EVENTS + // - event on the Policy return false, getEnforceFailureErrorMsg(engineResponses) } @@ -125,9 +139,6 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol // violations are created with resource on "audit" pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) ws.pvGenerator.Add(pvInfos...) - // ADD EVENTS - events := generateEvents(engineResponses, (request.Operation == v1beta1.Update)) - ws.eventGen.Add(events...) sendStat(false) // report time end glog.V(4).Infof("report: %v %s/%s/%s", time.Since(reportTime), request.Kind, request.Namespace, request.Name) From a31dc2107609103711ddac7e5fd53469eae415e3 Mon Sep 17 00:00:00 2001 From: shivkumar dudhani Date: Thu, 20 Feb 2020 10:01:29 -0800 Subject: [PATCH 2/2] fix ineffective assign --- pkg/webhooks/report.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index 9b262fcc7c..035a60688e 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -100,6 +100,7 @@ func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate filedRulesStr, er.PolicyResponse.Resource.GetKey(), ) + events = append(events, e) // Event on the resource // event on resource e = event.NewEvent(