diff --git a/pkg/controllers/report/utils/events.go b/pkg/controllers/report/utils/events.go index 4fd2d5e2cb..a1e3aaf9ef 100644 --- a/pkg/controllers/report/utils/events.go +++ b/pkg/controllers/report/utils/events.go @@ -1,8 +1,6 @@ package utils import ( - "strings" - "github.com/go-logr/logr" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" @@ -36,7 +34,7 @@ func generateSuccessEvents(log logr.Logger, ers ...*engineapi.EngineResponse) (e func generateExceptionEvents(log logr.Logger, ers ...*engineapi.EngineResponse) (eventInfos []event.Info) { for _, er := range ers { for i, ruleResp := range er.PolicyResponse.Rules { - isException := strings.Contains(ruleResp.Message, "rule skipped due to policy exception") + isException := ruleResp.Exception != nil if ruleResp.Status == engineapi.RuleStatusSkip && isException { eventInfos = append(eventInfos, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i])...) } diff --git a/pkg/engine/api/ruleresponse.go b/pkg/engine/api/ruleresponse.go index 5dbb8fa2a4..bf2c7b471c 100644 --- a/pkg/engine/api/ruleresponse.go +++ b/pkg/engine/api/ruleresponse.go @@ -3,6 +3,7 @@ package api import ( "fmt" + kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1" pssutils "github.com/kyverno/kyverno/pkg/pss/utils" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -43,6 +44,8 @@ type RuleResponse struct { PatchedTargetParentResourceGVR metav1.GroupVersionResource // PodSecurityChecks contains pod security checks (only if this is a pod security rule) PodSecurityChecks *PodSecurityChecks + // Exception is the exception applied (if any) + Exception *kyvernov2alpha1.PolicyException } // HasStatus checks if rule status is in a given list diff --git a/pkg/engine/exceptions.go b/pkg/engine/exceptions.go index 719a5558b8..830f59a0a3 100644 --- a/pkg/engine/exceptions.go +++ b/pkg/engine/exceptions.go @@ -83,19 +83,18 @@ func hasPolicyExceptions( ) *engineapi.RuleResponse { // if matches, check if there is a corresponding policy exception exception, err := matchesException(selector, ctx, rule, subresourceGVKToAPIResource, cfg) + var response *engineapi.RuleResponse // if we found an exception if err == nil && exception != nil { key, err := cache.MetaNamespaceKeyFunc(exception) if err != nil { log.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName()) - return &engineapi.RuleResponse{ - Name: rule.Name, - Message: "failed to find matched exception " + key, - Status: engineapi.RuleStatusError, - } + response = internal.RuleError(rule, ruleType, "failed to compute exception key", err) + } else { + log.V(3).Info("policy rule skipped due to policy exception", "exception", key) + response = internal.RuleSkip(rule, ruleType, "rule skipped due to policy exception "+key) + response.Exception = exception } - log.V(3).Info("policy rule skipped due to policy exception", "exception", key) - return internal.RuleSkip(rule, ruleType, "rule skipped due to policy exception "+key) } - return nil + return response } diff --git a/pkg/event/events.go b/pkg/event/events.go index 00bf31ea29..e33222f516 100644 --- a/pkg/event/events.go +++ b/pkg/event/events.go @@ -124,7 +124,7 @@ func NewBackgroundSuccessEvent(policy, rule string, source Source, r *unstructur } func NewPolicyExceptionEvents(engineResponse *engineapi.EngineResponse, ruleResp *engineapi.RuleResponse) []Info { - exceptionName, exceptionNamespace := getExceptionEventInfoFromRuleResponseMsg(ruleResp.Message) + exceptionName, exceptionNamespace := ruleResp.Exception.GetName(), ruleResp.Exception.GetNamespace() policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", engineResponse.PatchedResource.GetName(), ruleResp.Name, exceptionNamespace, exceptionName) var exceptionMessage string if engineResponse.Policy.GetNamespace() == "" { @@ -148,18 +148,3 @@ func NewPolicyExceptionEvents(engineResponse *engineapi.EngineResponse, ruleResp } return []Info{policyEvent, exceptionEvent} } - -func getExceptionEventInfoFromRuleResponseMsg(message string) (name string, namespace string) { - key := message[strings.LastIndex(message, " ")+1:] - arr := strings.Split(key, "/") - - if len(arr) > 1 { - namespace = arr[0] - name = arr[1] - } else { - namespace = "" - name = arr[0] - } - - return name, namespace -} diff --git a/pkg/webhooks/utils/event.go b/pkg/webhooks/utils/event.go index 97c89b2ccb..62a8590b4b 100644 --- a/pkg/webhooks/utils/event.go +++ b/pkg/webhooks/utils/event.go @@ -1,8 +1,6 @@ package utils import ( - "strings" - engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/event" ) @@ -34,7 +32,7 @@ func GenerateEvents(engineResponses []*engineapi.EngineResponse, blocked bool) [ } } else if er.IsSkipped() { // Handle PolicyException Event for i, ruleResp := range er.PolicyResponse.Rules { - isException := strings.Contains(ruleResp.Message, "rule skipped due to policy exception") + isException := ruleResp.Exception != nil if ruleResp.Status == engineapi.RuleStatusSkip && !blocked && isException { events = append(events, event.NewPolicyExceptionEvents(er, &er.PolicyResponse.Rules[i])...) }