From f18f1558166149b0e6a79db8e1aa630f5d2a5a20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?=
 <charles.edouard@nirmata.com>
Date: Wed, 3 May 2023 07:05:01 +0200
Subject: [PATCH] refactor: engine response policy (#7063)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
---
 .../kubectl-kyverno/apply/apply_command.go    |  2 +-
 cmd/cli/kubectl-kyverno/apply/report.go       |  4 +-
 cmd/cli/kubectl-kyverno/apply/report_test.go  |  4 +-
 cmd/cli/kubectl-kyverno/test/test.go          |  6 +--
 .../kubectl-kyverno/utils/common/common.go    |  2 +-
 pkg/background/generate/generate.go           |  2 +-
 pkg/controllers/report/utils/events.go        |  4 +-
 pkg/engine/api/engineresponse.go              | 21 +++++++---
 pkg/engine/api/engineresponse_test.go         | 38 +++++++------------
 pkg/engine/metrics.go                         |  2 +-
 pkg/event/events.go                           | 26 ++++++-------
 pkg/utils/annotations.go                      |  4 +-
 pkg/utils/report/results.go                   |  6 +--
 pkg/webhooks/resource/utils.go                |  6 +--
 pkg/webhooks/utils/block.go                   |  4 +-
 pkg/webhooks/utils/error.go                   |  2 +-
 pkg/webhooks/utils/warning.go                 |  2 +-
 pkg/webhooks/utils/warning_test.go            | 26 ++++++-------
 18 files changed, 78 insertions(+), 83 deletions(-)

diff --git a/cmd/cli/kubectl-kyverno/apply/apply_command.go b/cmd/cli/kubectl-kyverno/apply/apply_command.go
index 23f83df279..f25b3be947 100644
--- a/cmd/cli/kubectl-kyverno/apply/apply_command.go
+++ b/cmd/cli/kubectl-kyverno/apply/apply_command.go
@@ -441,7 +441,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
 			}
 			for _, response := range ers {
 				if !response.IsEmpty() {
-					for _, rule := range autogen.ComputeRules(response.Policy) {
+					for _, rule := range autogen.ComputeRules(response.Policy()) {
 						if rule.HasValidate() || rule.HasVerifyImageChecks() || rule.HasVerifyImages() {
 							ruleFoundInEngineResponse := false
 							for _, valResponseRule := range response.PolicyResponse.Rules {
diff --git a/cmd/cli/kubectl-kyverno/apply/report.go b/cmd/cli/kubectl-kyverno/apply/report.go
index cfd4b3bbc1..208227d761 100644
--- a/cmd/cli/kubectl-kyverno/apply/report.go
+++ b/cmd/cli/kubectl-kyverno/apply/report.go
@@ -77,7 +77,7 @@ func buildPolicyResults(auditWarn bool, engineResponses ...engineapi.EngineRespo
 	now := metav1.Timestamp{Seconds: time.Now().Unix()}
 
 	for _, engineResponse := range engineResponses {
-		policy := engineResponse.Policy
+		policy := engineResponse.Policy()
 		var appname string
 		ns := policy.GetNamespace()
 		if ns != "" {
@@ -105,7 +105,7 @@ func buildPolicyResults(auditWarn bool, engineResponses ...engineapi.EngineRespo
 				Scored: true,
 			}
 
-			ann := engineResponse.Policy.GetAnnotations()
+			ann := engineResponse.Policy().GetAnnotations()
 			if ruleResponse.Status() == engineapi.RuleStatusSkip {
 				result.Result = policyreportv1alpha2.StatusSkip
 			} else if ruleResponse.Status() == engineapi.RuleStatusError {
diff --git a/cmd/cli/kubectl-kyverno/apply/report_test.go b/cmd/cli/kubectl-kyverno/apply/report_test.go
index 4f5c175603..6f18a375d7 100644
--- a/cmd/cli/kubectl-kyverno/apply/report_test.go
+++ b/cmd/cli/kubectl-kyverno/apply/report_test.go
@@ -87,7 +87,7 @@ func Test_buildPolicyReports(t *testing.T) {
 	assert.NilError(t, err)
 
 	er := engineapi.EngineResponse{}
-	er.Policy = &policy
+	er = er.WithPolicy(&policy)
 	er.PolicyResponse.Add(
 		engineapi.ExecutionStats{},
 		*engineapi.RuleFail(
@@ -130,7 +130,7 @@ func Test_buildPolicyResults(t *testing.T) {
 	assert.NilError(t, err)
 
 	er := engineapi.EngineResponse{}
-	er.Policy = &policy
+	er = er.WithPolicy(&policy)
 	er.PolicyResponse.Add(
 		engineapi.ExecutionStats{}, *engineapi.RuleFail(
 			"pods-require-account",
diff --git a/cmd/cli/kubectl-kyverno/test/test.go b/cmd/cli/kubectl-kyverno/test/test.go
index 10c05c88c9..a28474a604 100644
--- a/cmd/cli/kubectl-kyverno/test/test.go
+++ b/cmd/cli/kubectl-kyverno/test/test.go
@@ -304,11 +304,11 @@ func buildPolicyResults(
 	results := map[string]policyreportv1alpha2.PolicyReportResult{}
 
 	for _, resp := range engineResponses {
-		policyName := resp.Policy.GetName()
+		policyName := resp.Policy().GetName()
 		resourceName := resp.Resource.GetName()
 		resourceKind := resp.Resource.GetKind()
 		resourceNamespace := resp.Resource.GetNamespace()
-		policyNamespace := resp.Policy.GetNamespace()
+		policyNamespace := resp.Policy().GetNamespace()
 
 		var rules []string
 		for _, rule := range resp.PolicyResponse.Rules {
@@ -500,7 +500,7 @@ func buildPolicyResults(
 						continue
 					}
 
-					ann := resp.Policy.GetAnnotations()
+					ann := resp.Policy().GetAnnotations()
 					if rule.Status() == engineapi.RuleStatusSkip {
 						result.Result = policyreportv1alpha2.StatusSkip
 					} else if rule.Status() == engineapi.RuleStatusError {
diff --git a/cmd/cli/kubectl-kyverno/utils/common/common.go b/cmd/cli/kubectl-kyverno/utils/common/common.go
index e31481c037..6b2230d956 100644
--- a/cmd/cli/kubectl-kyverno/utils/common/common.go
+++ b/cmd/cli/kubectl-kyverno/utils/common/common.go
@@ -1076,7 +1076,7 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
 	gr := kyvernov1beta1.UpdateRequest{
 		Spec: kyvernov1beta1.UpdateRequestSpec{
 			Type:   kyvernov1beta1.Generate,
-			Policy: generateResponse.Policy.GetName(),
+			Policy: generateResponse.Policy().GetName(),
 			Resource: kyvernov1.ResourceSpec{
 				Kind:       generateResponse.Resource.GetKind(),
 				Namespace:  generateResponse.Resource.GetNamespace(),
diff --git a/pkg/background/generate/generate.go b/pkg/background/generate/generate.go
index 338276d141..f3deb3e45a 100644
--- a/pkg/background/generate/generate.go
+++ b/pkg/background/generate/generate.go
@@ -230,7 +230,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
 		if r.Status() != engineapi.RuleStatusPass {
 			logger.V(4).Info("querying all update requests")
 			selector := labels.SelectorFromSet(labels.Set(map[string]string{
-				kyvernov1beta1.URGeneratePolicyLabel:       engineResponse.Policy.GetName(),
+				kyvernov1beta1.URGeneratePolicyLabel:       engineResponse.Policy().GetName(),
 				kyvernov1beta1.URGenerateResourceNameLabel: engineResponse.Resource.GetName(),
 				kyvernov1beta1.URGenerateResourceKindLabel: engineResponse.Resource.GetKind(),
 				kyvernov1beta1.URGenerateResourceNSLabel:   engineResponse.Resource.GetNamespace(),
diff --git a/pkg/controllers/report/utils/events.go b/pkg/controllers/report/utils/events.go
index a24c80fa38..208546d369 100644
--- a/pkg/controllers/report/utils/events.go
+++ b/pkg/controllers/report/utils/events.go
@@ -21,7 +21,7 @@ func GenerateEvents(logger logr.Logger, eventGen event.Interface, config config.
 
 func generateSuccessEvents(log logr.Logger, ers ...engineapi.EngineResponse) (eventInfos []event.Info) {
 	for _, er := range ers {
-		logger := log.WithValues("policy", er.Policy.GetName(), "kind", er.Resource.GetKind(), "namespace", er.Resource.GetNamespace(), "name", er.Resource.GetName())
+		logger := log.WithValues("policy", er.Policy().GetName(), "kind", er.Resource.GetKind(), "namespace", er.Resource.GetNamespace(), "name", er.Resource.GetName())
 		if !er.IsFailed() {
 			logger.V(4).Info("generating event on policy for success rules")
 			e := event.NewPolicyAppliedEvent(event.PolicyController, er)
@@ -52,7 +52,7 @@ func generateFailEvents(log logr.Logger, ers ...engineapi.EngineResponse) (event
 func generateFailEventsPerEr(log logr.Logger, er engineapi.EngineResponse) []event.Info {
 	var eventInfos []event.Info
 	logger := log.WithValues(
-		"policy", er.Policy.GetName(),
+		"policy", er.Policy().GetName(),
 		"kind", er.Resource.GetKind(),
 		"namespace", er.Resource.GetNamespace(),
 		"name", er.Resource.GetName(),
diff --git a/pkg/engine/api/engineresponse.go b/pkg/engine/api/engineresponse.go
index 2a023e4f7d..1f2e2fb847 100644
--- a/pkg/engine/api/engineresponse.go
+++ b/pkg/engine/api/engineresponse.go
@@ -14,8 +14,8 @@ import (
 type EngineResponse struct {
 	// Resource is the original resource
 	Resource unstructured.Unstructured
-	// Policy is the original policy
-	Policy kyvernov1.PolicyInterface
+	// policy is the original policy
+	policy kyvernov1.PolicyInterface
 	// namespaceLabels given by policy context
 	namespaceLabels map[string]string
 	// PatchedResource is the resource patched with the engine action changes
@@ -26,7 +26,7 @@ type EngineResponse struct {
 	stats ExecutionStats
 }
 
-func Resource(policyContext PolicyContext) unstructured.Unstructured {
+func resource(policyContext PolicyContext) unstructured.Unstructured {
 	resource := policyContext.NewResource()
 	if resource.Object == nil {
 		resource = policyContext.OldResource()
@@ -36,7 +36,7 @@ func Resource(policyContext PolicyContext) unstructured.Unstructured {
 
 func NewEngineResponseFromPolicyContext(policyContext PolicyContext) EngineResponse {
 	return NewEngineResponse(
-		Resource(policyContext),
+		resource(policyContext),
 		policyContext.Policy(),
 		policyContext.NamespaceLabels(),
 	)
@@ -49,12 +49,17 @@ func NewEngineResponse(
 ) EngineResponse {
 	return EngineResponse{
 		Resource:        resource,
-		Policy:          policy,
+		policy:          policy,
 		namespaceLabels: namespaceLabels,
 		PatchedResource: resource,
 	}
 }
 
+func (er EngineResponse) WithPolicy(policy kyvernov1.PolicyInterface) EngineResponse {
+	er.policy = policy
+	return er
+}
+
 func (er EngineResponse) WithPolicyResponse(policyResponse PolicyResponse) EngineResponse {
 	er.PolicyResponse = policyResponse
 	return er
@@ -79,6 +84,10 @@ func (er *EngineResponse) NamespaceLabels() map[string]string {
 	return er.namespaceLabels
 }
 
+func (er *EngineResponse) Policy() kyvernov1.PolicyInterface {
+	return er.policy
+}
+
 // IsOneOf checks if any rule has status in a given list
 func (er EngineResponse) IsOneOf(status ...RuleStatus) bool {
 	for _, r := range er.PolicyResponse.Rules {
@@ -175,7 +184,7 @@ func (er EngineResponse) getRulesWithErrors(predicate func(RuleResponse) bool) [
 }
 
 func (er EngineResponse) GetValidationFailureAction() kyvernov1.ValidationFailureAction {
-	spec := er.Policy.GetSpec()
+	spec := er.Policy().GetSpec()
 	for _, v := range spec.ValidationFailureActionOverrides {
 		if !v.Action.IsValid() {
 			continue
diff --git a/pkg/engine/api/engineresponse_test.go b/pkg/engine/api/engineresponse_test.go
index 10751ddd55..718a311cf8 100644
--- a/pkg/engine/api/engineresponse_test.go
+++ b/pkg/engine/api/engineresponse_test.go
@@ -41,10 +41,9 @@ func TestEngineResponse_IsEmpty(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsEmpty(); got != tt.want {
 				t.Errorf("EngineResponse.IsEmpty() = %v, want %v", got, tt.want)
 			}
@@ -84,10 +83,9 @@ func TestEngineResponse_IsNil(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsNil(); got != tt.want {
 				t.Errorf("EngineResponse.IsNil() = %v, want %v", got, tt.want)
 			}
@@ -172,10 +170,9 @@ func TestEngineResponse_IsOneOf(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsOneOf(tt.args.status...); got != tt.want {
 				t.Errorf("EngineResponse.IsOneOf() = %v, want %v", got, tt.want)
 			}
@@ -246,10 +243,9 @@ func TestEngineResponse_IsSuccessful(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsSuccessful(); got != tt.want {
 				t.Errorf("EngineResponse.IsSuccessful() = %v, want %v", got, tt.want)
 			}
@@ -320,10 +316,9 @@ func TestEngineResponse_IsSkipped(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsSkipped(); got != tt.want {
 				t.Errorf("EngineResponse.IsSkipped() = %v, want %v", got, tt.want)
 			}
@@ -394,10 +389,9 @@ func TestEngineResponse_IsFailed(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsFailed(); got != tt.want {
 				t.Errorf("EngineResponse.IsFailed() = %v, want %v", got, tt.want)
 			}
@@ -468,10 +462,9 @@ func TestEngineResponse_IsError(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.IsError(); got != tt.want {
 				t.Errorf("EngineResponse.IsError() = %v, want %v", got, tt.want)
 			}
@@ -558,10 +551,9 @@ func TestEngineResponse_GetFailedRules(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.GetFailedRules(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("EngineResponse.GetFailedRules() = %v, want %v", got, tt.want)
 			}
@@ -675,10 +667,9 @@ func TestEngineResponse_GetSuccessRules(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.GetSuccessRules(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("EngineResponse.GetSuccessRules() = %v, want %v", got, tt.want)
 			}
@@ -904,12 +895,11 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
 	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			er := &EngineResponse{
+			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.GetValidationFailureAction(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("EngineResponse.GetValidationFailureAction() = %v, want %v", got, tt.want)
 			}
@@ -972,10 +962,9 @@ func TestEngineResponse_GetPatches(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.GetPatches(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("EngineResponse.GetPatches() = %v, want %v", got, tt.want)
 			}
@@ -1031,10 +1020,9 @@ func TestEngineResponse_GetResourceSpec(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			er := EngineResponse{
 				PatchedResource: tt.fields.PatchedResource,
-				Policy:          tt.fields.Policy,
 				PolicyResponse:  tt.fields.PolicyResponse,
 				namespaceLabels: tt.fields.namespaceLabels,
-			}
+			}.WithPolicy(tt.fields.Policy)
 			if got := er.GetResourceSpec(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("EngineResponse.GetResourceSpec() = %v, want %v", got, tt.want)
 			}
diff --git a/pkg/engine/metrics.go b/pkg/engine/metrics.go
index ca783bc0c1..93aedc62f6 100644
--- a/pkg/engine/metrics.go
+++ b/pkg/engine/metrics.go
@@ -21,7 +21,7 @@ func (e *engine) reportMetrics(
 	if e.resultCounter == nil && e.durationHistogram == nil {
 		return
 	}
-	policy := response.Policy
+	policy := response.Policy()
 	if name, namespace, policyType, backgroundMode, validationMode, err := metrics.GetPolicyInfos(policy); err != nil {
 		logger.Error(err, "failed to get policy infos for metrics reporting")
 	} else {
diff --git a/pkg/event/events.go b/pkg/event/events.go
index acf62697f7..fbbd6b926c 100644
--- a/pkg/event/events.go
+++ b/pkg/event/events.go
@@ -11,9 +11,9 @@ import (
 
 func NewPolicyFailEvent(source Source, reason Reason, engineResponse engineapi.EngineResponse, ruleResp engineapi.RuleResponse, blocked bool) Info {
 	return Info{
-		Kind:      getPolicyKind(engineResponse.Policy),
-		Name:      engineResponse.Policy.GetName(),
-		Namespace: engineResponse.Policy.GetNamespace(),
+		Kind:      getPolicyKind(engineResponse.Policy()),
+		Name:      engineResponse.Policy().GetName(),
+		Namespace: engineResponse.Policy().GetNamespace(),
 		Reason:    reason,
 		Source:    source,
 		Message:   buildPolicyEventMessage(ruleResp, engineResponse.GetResourceSpec(), blocked),
@@ -59,9 +59,9 @@ func NewPolicyAppliedEvent(source Source, engineResponse engineapi.EngineRespons
 	}
 
 	return Info{
-		Kind:      getPolicyKind(engineResponse.Policy),
-		Name:      engineResponse.Policy.GetName(),
-		Namespace: engineResponse.Policy.GetNamespace(),
+		Kind:      getPolicyKind(engineResponse.Policy()),
+		Name:      engineResponse.Policy().GetName(),
+		Namespace: engineResponse.Policy().GetNamespace(),
 		Reason:    PolicyApplied,
 		Source:    source,
 		Message:   bldr.String(),
@@ -72,7 +72,7 @@ func NewResourceViolationEvent(source Source, reason Reason, engineResponse engi
 	var bldr strings.Builder
 	defer bldr.Reset()
 
-	fmt.Fprintf(&bldr, "policy %s/%s %s: %s", engineResponse.Policy.GetName(),
+	fmt.Fprintf(&bldr, "policy %s/%s %s: %s", engineResponse.Policy().GetName(),
 		ruleResp.Name(), ruleResp.Status(), ruleResp.Message())
 	resource := engineResponse.GetResourceSpec()
 
@@ -128,15 +128,15 @@ func NewPolicyExceptionEvents(engineResponse engineapi.EngineResponse, ruleResp
 	exceptionName, exceptionNamespace := exception.GetName(), exception.GetNamespace()
 	policyMessage := fmt.Sprintf("resource %s was skipped from rule %s due to policy exception %s/%s", resourceKey(engineResponse.PatchedResource), ruleResp.Name(), exceptionNamespace, exceptionName)
 	var exceptionMessage string
-	if engineResponse.Policy.GetNamespace() == "" {
-		exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetName(), ruleResp.Name())
+	if engineResponse.Policy().GetNamespace() == "" {
+		exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy().GetName(), ruleResp.Name())
 	} else {
-		exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy.GetNamespace(), engineResponse.Policy.GetName(), ruleResp.Name())
+		exceptionMessage = fmt.Sprintf("resource %s was skipped from policy rule %s/%s/%s", resourceKey(engineResponse.PatchedResource), engineResponse.Policy().GetNamespace(), engineResponse.Policy().GetName(), ruleResp.Name())
 	}
 	policyEvent := Info{
-		Kind:      getPolicyKind(engineResponse.Policy),
-		Name:      engineResponse.Policy.GetName(),
-		Namespace: engineResponse.Policy.GetNamespace(),
+		Kind:      getPolicyKind(engineResponse.Policy()),
+		Name:      engineResponse.Policy().GetName(),
+		Namespace: engineResponse.Policy().GetNamespace(),
 		Reason:    PolicySkipped,
 		Message:   policyMessage,
 		Source:    source,
diff --git a/pkg/utils/annotations.go b/pkg/utils/annotations.go
index f4698c9748..aad73a220d 100644
--- a/pkg/utils/annotations.go
+++ b/pkg/utils/annotations.go
@@ -95,14 +95,14 @@ func annotationFromEngineResponses(engineResponses []engineapi.EngineResponse, l
 	annotationContent := make(map[string]string)
 	for _, engineResponse := range engineResponses {
 		if !engineResponse.IsSuccessful() {
-			log.V(3).Info("skip building annotation; policy failed to apply", "policy", engineResponse.Policy.GetName())
+			log.V(3).Info("skip building annotation; policy failed to apply", "policy", engineResponse.Policy().GetName())
 			continue
 		}
 		rulePatches := annotationFromPolicyResponse(engineResponse.PolicyResponse, log)
 		if rulePatches == nil {
 			continue
 		}
-		policyName := engineResponse.Policy.GetName()
+		policyName := engineResponse.Policy().GetName()
 		for _, rulePatch := range rulePatches {
 			annotationContent[rulePatch.RuleName+"."+policyName+".kyverno.io"] = OperationToPastTense[rulePatch.Op] + " " + rulePatch.Path
 		}
diff --git a/pkg/utils/report/results.go b/pkg/utils/report/results.go
index f6185d1071..fa368b71ba 100644
--- a/pkg/utils/report/results.go
+++ b/pkg/utils/report/results.go
@@ -82,10 +82,10 @@ func severityFromString(severity string) policyreportv1alpha2.PolicySeverity {
 }
 
 func EngineResponseToReportResults(response engineapi.EngineResponse) []policyreportv1alpha2.PolicyReportResult {
-	key, _ := cache.MetaNamespaceKeyFunc(response.Policy)
+	key, _ := cache.MetaNamespaceKeyFunc(response.Policy())
 	var results []policyreportv1alpha2.PolicyReportResult
 	for _, ruleResult := range response.PolicyResponse.Rules {
-		annotations := response.Policy.GetAnnotations()
+		annotations := response.Policy().GetAnnotations()
 		result := policyreportv1alpha2.PolicyReportResult{
 			Source:  kyvernov1.ValueKyvernoApp,
 			Policy:  key,
@@ -157,7 +157,7 @@ func SetResults(report kyvernov1alpha2.ReportInterface, results ...policyreportv
 func SetResponses(report kyvernov1alpha2.ReportInterface, engineResponses ...engineapi.EngineResponse) {
 	var ruleResults []policyreportv1alpha2.PolicyReportResult
 	for _, result := range engineResponses {
-		SetPolicyLabel(report, result.Policy)
+		SetPolicyLabel(report, result.Policy())
 		ruleResults = append(ruleResults, EngineResponseToReportResults(result)...)
 	}
 	SetResults(report, ruleResults...)
diff --git a/pkg/webhooks/resource/utils.go b/pkg/webhooks/resource/utils.go
index e5daf4338a..882229f3e6 100644
--- a/pkg/webhooks/resource/utils.go
+++ b/pkg/webhooks/resource/utils.go
@@ -70,10 +70,10 @@ func applyUpdateRequest(
 
 func transform(admissionRequestInfo kyvernov1beta1.AdmissionRequestInfoObject, userRequestInfo kyvernov1beta1.RequestInfo, er *engineapi.EngineResponse, ruleType kyvernov1beta1.RequestType) kyvernov1beta1.UpdateRequestSpec {
 	var PolicyNameNamespaceKey string
-	if er.Policy.GetNamespace() != "" {
-		PolicyNameNamespaceKey = er.Policy.GetNamespace() + "/" + er.Policy.GetName()
+	if er.Policy().GetNamespace() != "" {
+		PolicyNameNamespaceKey = er.Policy().GetNamespace() + "/" + er.Policy().GetName()
 	} else {
-		PolicyNameNamespaceKey = er.Policy.GetName()
+		PolicyNameNamespaceKey = er.Policy().GetName()
 	}
 
 	ur := kyvernov1beta1.UpdateRequestSpec{
diff --git a/pkg/webhooks/utils/block.go b/pkg/webhooks/utils/block.go
index bebe764933..1043df2012 100644
--- a/pkg/webhooks/utils/block.go
+++ b/pkg/webhooks/utils/block.go
@@ -26,7 +26,7 @@ func getAction(hasViolations bool, i int) string {
 func BlockRequest(engineResponses []engineapi.EngineResponse, failurePolicy kyvernov1.FailurePolicyType, log logr.Logger) bool {
 	for _, er := range engineResponses {
 		if engineutils.BlockRequest(er, failurePolicy) {
-			log.V(2).Info("blocking admission request", "policy", er.Policy.GetName())
+			log.V(2).Info("blocking admission request", "policy", er.Policy().GetName())
 			return true
 		}
 	}
@@ -52,7 +52,7 @@ func GetBlockedMessages(engineResponses []engineapi.EngineResponse) string {
 			}
 		}
 		if len(ruleToReason) != 0 {
-			failures[er.Policy.GetName()] = ruleToReason
+			failures[er.Policy().GetName()] = ruleToReason
 		}
 	}
 	if len(failures) == 0 {
diff --git a/pkg/webhooks/utils/error.go b/pkg/webhooks/utils/error.go
index b54be16193..298804b7f4 100644
--- a/pkg/webhooks/utils/error.go
+++ b/pkg/webhooks/utils/error.go
@@ -14,7 +14,7 @@ func GetErrorMsg(engineReponses []engineapi.EngineResponse) string {
 		if !er.IsSuccessful() {
 			// resource in engineReponses is identical as this was called per admission request
 			resourceInfo = fmt.Sprintf("%s/%s/%s", er.Resource.GetKind(), er.Resource.GetNamespace(), er.Resource.GetName())
-			str = append(str, fmt.Sprintf("failed policy %s:", er.Policy.GetName()))
+			str = append(str, fmt.Sprintf("failed policy %s:", er.Policy().GetName()))
 			for _, rule := range er.PolicyResponse.Rules {
 				if rule.Status() != engineapi.RuleStatusPass {
 					str = append(str, rule.String())
diff --git a/pkg/webhooks/utils/warning.go b/pkg/webhooks/utils/warning.go
index 9b9b15fae7..6119352097 100644
--- a/pkg/webhooks/utils/warning.go
+++ b/pkg/webhooks/utils/warning.go
@@ -11,7 +11,7 @@ func GetWarningMessages(engineResponses []engineapi.EngineResponse) []string {
 	for _, er := range engineResponses {
 		for _, rule := range er.PolicyResponse.Rules {
 			if rule.Status() != engineapi.RuleStatusPass && rule.Status() != engineapi.RuleStatusSkip {
-				msg := fmt.Sprintf("policy %s.%s: %s", er.Policy.GetName(), rule.Name(), rule.Message())
+				msg := fmt.Sprintf("policy %s.%s: %s", er.Policy().GetName(), rule.Name(), rule.Message())
 				warnings = append(warnings, msg)
 			}
 		}
diff --git a/pkg/webhooks/utils/warning_test.go b/pkg/webhooks/utils/warning_test.go
index d7e4c969a2..697433969e 100644
--- a/pkg/webhooks/utils/warning_test.go
+++ b/pkg/webhooks/utils/warning_test.go
@@ -28,18 +28,17 @@ func TestGetWarningMessages(t *testing.T) {
 	}, {
 		name: "warning",
 		args: args{[]engineapi.EngineResponse{
-			{
-				Policy: &v1.ClusterPolicy{
-					ObjectMeta: metav1.ObjectMeta{
-						Name: "test",
-					},
-				},
+			engineapi.EngineResponse{
 				PolicyResponse: engineapi.PolicyResponse{
 					Rules: []engineapi.RuleResponse{
 						*engineapi.NewRuleResponse("rule", engineapi.Validation, "message warn", engineapi.RuleStatusWarn),
 					},
 				},
-			},
+			}.WithPolicy(&v1.ClusterPolicy{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "test",
+				},
+			}),
 		}},
 		want: []string{
 			"policy test.rule: message warn",
@@ -47,12 +46,7 @@ func TestGetWarningMessages(t *testing.T) {
 	}, {
 		name: "multiple rules",
 		args: args{[]engineapi.EngineResponse{
-			{
-				Policy: &v1.ClusterPolicy{
-					ObjectMeta: metav1.ObjectMeta{
-						Name: "test",
-					},
-				},
+			engineapi.EngineResponse{
 				PolicyResponse: engineapi.PolicyResponse{
 					Rules: []engineapi.RuleResponse{
 						*engineapi.RulePass("rule-pass", engineapi.Validation, "message pass"),
@@ -62,7 +56,11 @@ func TestGetWarningMessages(t *testing.T) {
 						*engineapi.RuleSkip("rule-skip", engineapi.Validation, "message skip"),
 					},
 				},
-			},
+			}.WithPolicy(&v1.ClusterPolicy{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "test",
+				},
+			}),
 		}},
 		want: []string{
 			"policy test.rule-warn: message warn",