1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

refactor: engine matching/filtering (#6289)

* refactor: improve engine logger management

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* logger

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* refactor: engine matching/filtering

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* more

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix cli tests

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix cli test

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* match in the engine first

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* match in the engine first

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-03-23 17:03:40 +01:00 committed by GitHub
parent 437d908fb8
commit 36964a3d95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 90 additions and 53 deletions

View file

@ -309,8 +309,8 @@ func (c *controller) reconcileReport(
if result.Error != nil {
return result.Error
} else {
ruleResults = append(ruleResults, reportutils.EngineResponseToReportResults(*result.EngineResponse)...)
utils.GenerateEvents(logger, c.eventGen, c.config, *result.EngineResponse)
ruleResults = append(ruleResults, reportutils.EngineResponseToReportResults(result.EngineResponse)...)
utils.GenerateEvents(logger, c.eventGen, c.config, result.EngineResponse)
}
}
}

View file

@ -20,7 +20,7 @@ type scanner struct {
}
type ScanResult struct {
EngineResponse *engineapi.EngineResponse
EngineResponse engineapi.EngineResponse
Error error
}
@ -62,7 +62,7 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
response.PolicyResponse.Rules = append(response.PolicyResponse.Rules, ivResponse.PolicyResponse.Rules...)
}
}
results[policy] = ScanResult{response, multierr.Combine(errors...)}
results[policy] = ScanResult{*response, multierr.Combine(errors...)}
}
return results
}

View file

@ -31,11 +31,7 @@ func (e *engine) filterRules(
logger logr.Logger,
startTime time.Time,
) engineapi.EngineResponse {
newResource := policyContext.NewResource()
policy := policyContext.Policy()
kind := newResource.GetKind()
name := newResource.GetName()
namespace := newResource.GetNamespace()
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
resp.PolicyResponse = engineapi.PolicyResponse{
Stats: engineapi.PolicyStats{
@ -44,12 +40,6 @@ func (e *engine) filterRules(
},
},
}
if e.configuration.ToFilter(kind, namespace, name) {
logger.Info("resource excluded")
return resp
}
applyRules := policy.GetSpec().GetApplyRules()
for _, rule := range autogen.ComputeRules(policy) {
logger := internal.LoggerWithRule(logger, rule)
@ -60,7 +50,6 @@ func (e *engine) filterRules(
}
}
}
return resp
}

View file

@ -43,6 +43,9 @@ func (e *engine) Validate(
policyContext engineapi.PolicyContext,
) engineapi.EngineResponse {
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.validate"), policyContext)
if !internal.MatchPolicyContext(logger, policyContext, e.configuration) {
return engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
}
return e.validate(ctx, logger, policyContext)
}
@ -51,6 +54,9 @@ func (e *engine) Mutate(
policyContext engineapi.PolicyContext,
) engineapi.EngineResponse {
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.mutate"), policyContext)
if !internal.MatchPolicyContext(logger, policyContext, e.configuration) {
return engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
}
return e.mutate(ctx, logger, policyContext)
}
@ -59,6 +65,9 @@ func (e *engine) VerifyAndPatchImages(
policyContext engineapi.PolicyContext,
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.verify"), policyContext)
if !internal.MatchPolicyContext(logger, policyContext, e.configuration) {
return engineapi.NewEngineResponseFromPolicyContext(policyContext, nil), engineapi.ImageVerificationMetadata{}
}
return e.verifyAndPatchImages(ctx, logger, policyContext)
}
@ -67,6 +76,9 @@ func (e *engine) ApplyBackgroundChecks(
policyContext engineapi.PolicyContext,
) engineapi.EngineResponse {
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.background"), policyContext)
if !internal.MatchPolicyContext(logger, policyContext, e.configuration) {
return engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
}
return e.applyBackgroundChecks(ctx, logger, policyContext)
}
@ -76,6 +88,9 @@ func (e *engine) GenerateResponse(
gr kyvernov1beta1.UpdateRequest,
) engineapi.EngineResponse {
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.generate"), policyContext)
if !internal.MatchPolicyContext(logger, policyContext, e.configuration) {
return engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
}
return e.generateResponse(ctx, logger, policyContext, gr)
}

View file

@ -27,10 +27,6 @@ func (e *engine) filterGenerateRules(
policyNameKey string,
startTime time.Time,
) engineapi.EngineResponse {
newResource := policyContext.NewResource()
kind := newResource.GetKind()
name := newResource.GetName()
namespace := newResource.GetNamespace()
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
resp.PolicyResponse = engineapi.PolicyResponse{
Stats: engineapi.PolicyStats{
@ -39,10 +35,6 @@ func (e *engine) filterGenerateRules(
},
},
}
if e.configuration.ToFilter(kind, namespace, name) {
logger.Info("resource excluded")
return resp
}
for _, rule := range autogen.ComputeRules(policyContext.Policy()) {
logger := internal.LoggerWithRule(logger, rule)
if ruleResp := e.filterRule(rule, logger, policyContext); ruleResp != nil {

View file

@ -26,11 +26,12 @@ func (e *engine) verifyAndPatchImages(
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
policy := policyContext.Policy()
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
startTime := time.Now()
defer func() {
logger.V(4).Info(
"processed image verification rules",
internal.BuildResponse(policyContext, &resp, startTime)
logger.V(4).Info("processed image verification rules",
"time", resp.PolicyResponse.Stats.ProcessingTime.String(),
"applied", resp.PolicyResponse.Stats.RulesAppliedCount,
"successful", resp.IsSuccessful(),

View file

@ -0,0 +1,51 @@
package internal
import (
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func MatchPolicyContext(logger logr.Logger, policyContext engineapi.PolicyContext, configuration config.Configuration) bool {
policy := policyContext.Policy()
old := policyContext.OldResource()
new := policyContext.NewResource()
if !checkNamespacedPolicy(policy, new, old) {
logger.V(2).Info("policy namespace doesn't match resource namespace")
return false
}
if !checkResourceFilters(configuration, new, old) {
logger.V(2).Info("configuration resource filters doesn't match resource")
return false
}
return true
}
func checkResourceFilters(configuration config.Configuration, resources ...unstructured.Unstructured) bool {
for _, resource := range resources {
if resource.Object != nil {
// TODO: account for generate name here ?
if configuration.ToFilter(resource.GetKind(), resource.GetNamespace(), resource.GetName()) {
return false
}
}
}
return true
}
func checkNamespacedPolicy(policy kyvernov1.PolicyInterface, resources ...unstructured.Unstructured) bool {
if policy.IsNamespaced() {
policyNamespace := policy.GetNamespace()
for _, resource := range resources {
if resource.Object != nil {
resourceNamespace := resource.GetNamespace()
if resourceNamespace != policyNamespace || resourceNamespace == "" {
return false
}
}
}
}
return true
}

View file

@ -25,9 +25,10 @@ func (e *engine) mutate(
logger logr.Logger,
policyContext engineapi.PolicyContext,
) engineapi.EngineResponse {
startTime := time.Now()
policy := policyContext.Policy()
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
startTime := time.Now()
matchedResource := policyContext.NewResource()
var skippedRules []string

View file

@ -46,34 +46,22 @@ func (e *engine) validate(
func (e *engine) validateResource(
ctx context.Context,
logger logr.Logger,
enginectx engineapi.PolicyContext,
policyContext engineapi.PolicyContext,
) *engineapi.PolicyResponse {
resp := &engineapi.PolicyResponse{}
enginectx.JSONContext().Checkpoint()
defer enginectx.JSONContext().Restore()
policyContext.JSONContext().Checkpoint()
defer policyContext.JSONContext().Restore()
rules := autogen.ComputeRules(enginectx.Policy())
rules := autogen.ComputeRules(policyContext.Policy())
matchCount := 0
applyRules := enginectx.Policy().GetSpec().GetApplyRules()
newResource := enginectx.NewResource()
oldResource := enginectx.OldResource()
if enginectx.Policy().IsNamespaced() {
polNs := enginectx.Policy().GetNamespace()
if enginectx.NewResource().Object != nil && (newResource.GetNamespace() != polNs || newResource.GetNamespace() == "") {
return resp
}
if enginectx.OldResource().Object != nil && (oldResource.GetNamespace() != polNs || oldResource.GetNamespace() == "") {
return resp
}
}
applyRules := policyContext.Policy().GetSpec().GetApplyRules()
for i := range rules {
rule := &rules[i]
logger := internal.LoggerWithRule(logger, rules[i])
logger.V(3).Info("processing validation rule", "matchCount", matchCount)
enginectx.JSONContext().Reset()
policyContext.JSONContext().Reset()
startTime := time.Now()
ruleResp := tracing.ChildSpan1(
ctx,
@ -86,22 +74,21 @@ func (e *engine) validateResource(
if !hasValidate && !hasValidateImage {
return nil
}
if !matches(logger, rule, enginectx, e.configuration) {
if !matches(logger, rule, policyContext, e.configuration) {
return nil
}
// check if there is a corresponding policy exception
ruleResp := hasPolicyExceptions(logger, engineapi.Validation, e.exceptionSelector, enginectx, rule, e.configuration)
ruleResp := hasPolicyExceptions(logger, engineapi.Validation, e.exceptionSelector, policyContext, rule, e.configuration)
if ruleResp != nil {
return ruleResp
}
enginectx.JSONContext().Reset()
policyContext.JSONContext().Reset()
if hasValidate && !hasYAMLSignatureVerify {
return e.processValidationRule(ctx, logger, enginectx, rule)
return e.processValidationRule(ctx, logger, policyContext, rule)
} else if hasValidateImage {
return e.processImageValidationRule(ctx, logger, enginectx, rule)
return e.processImageValidationRule(ctx, logger, policyContext, rule)
} else if hasYAMLSignatureVerify {
return processYAMLValidationRule(e.client, logger, enginectx, rule)
return processYAMLValidationRule(e.client, logger, policyContext, rule)
}
return nil
},

View file

@ -90,8 +90,9 @@ func (h *imageVerificationHandler) handleVerifyImages(
func(ctx context.Context, span trace.Span) {
policyContext := policyContext.WithPolicy(policy)
resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
engineResponses = append(engineResponses, resp)
if !resp.IsEmpty() {
engineResponses = append(engineResponses, resp)
}
patches = append(patches, resp.GetPatches()...)
verifiedImageData.Merge(ivm)
},