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:
parent
437d908fb8
commit
36964a3d95
10 changed files with 90 additions and 53 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
51
pkg/engine/internal/match.go
Normal file
51
pkg/engine/internal/match.go
Normal 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
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue