mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +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 {
|
if result.Error != nil {
|
||||||
return result.Error
|
return result.Error
|
||||||
} else {
|
} else {
|
||||||
ruleResults = append(ruleResults, reportutils.EngineResponseToReportResults(*result.EngineResponse)...)
|
ruleResults = append(ruleResults, reportutils.EngineResponseToReportResults(result.EngineResponse)...)
|
||||||
utils.GenerateEvents(logger, c.eventGen, c.config, *result.EngineResponse)
|
utils.GenerateEvents(logger, c.eventGen, c.config, result.EngineResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ type scanner struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScanResult struct {
|
type ScanResult struct {
|
||||||
EngineResponse *engineapi.EngineResponse
|
EngineResponse engineapi.EngineResponse
|
||||||
Error error
|
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...)
|
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
|
return results
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,7 @@ func (e *engine) filterRules(
|
||||||
logger logr.Logger,
|
logger logr.Logger,
|
||||||
startTime time.Time,
|
startTime time.Time,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
newResource := policyContext.NewResource()
|
|
||||||
policy := policyContext.Policy()
|
policy := policyContext.Policy()
|
||||||
kind := newResource.GetKind()
|
|
||||||
name := newResource.GetName()
|
|
||||||
namespace := newResource.GetNamespace()
|
|
||||||
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
||||||
resp.PolicyResponse = engineapi.PolicyResponse{
|
resp.PolicyResponse = engineapi.PolicyResponse{
|
||||||
Stats: engineapi.PolicyStats{
|
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()
|
applyRules := policy.GetSpec().GetApplyRules()
|
||||||
for _, rule := range autogen.ComputeRules(policy) {
|
for _, rule := range autogen.ComputeRules(policy) {
|
||||||
logger := internal.LoggerWithRule(logger, rule)
|
logger := internal.LoggerWithRule(logger, rule)
|
||||||
|
@ -60,7 +50,6 @@ func (e *engine) filterRules(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ func (e *engine) Validate(
|
||||||
policyContext engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.validate"), policyContext)
|
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)
|
return e.validate(ctx, logger, policyContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +54,9 @@ func (e *engine) Mutate(
|
||||||
policyContext engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.mutate"), policyContext)
|
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)
|
return e.mutate(ctx, logger, policyContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +65,9 @@ func (e *engine) VerifyAndPatchImages(
|
||||||
policyContext engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
|
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
|
||||||
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.verify"), policyContext)
|
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)
|
return e.verifyAndPatchImages(ctx, logger, policyContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +76,9 @@ func (e *engine) ApplyBackgroundChecks(
|
||||||
policyContext engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.background"), policyContext)
|
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)
|
return e.applyBackgroundChecks(ctx, logger, policyContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +88,9 @@ func (e *engine) GenerateResponse(
|
||||||
gr kyvernov1beta1.UpdateRequest,
|
gr kyvernov1beta1.UpdateRequest,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
logger := internal.LoggerWithPolicyContext(logging.WithName("engine.generate"), policyContext)
|
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)
|
return e.generateResponse(ctx, logger, policyContext, gr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,6 @@ func (e *engine) filterGenerateRules(
|
||||||
policyNameKey string,
|
policyNameKey string,
|
||||||
startTime time.Time,
|
startTime time.Time,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
newResource := policyContext.NewResource()
|
|
||||||
kind := newResource.GetKind()
|
|
||||||
name := newResource.GetName()
|
|
||||||
namespace := newResource.GetNamespace()
|
|
||||||
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
||||||
resp.PolicyResponse = engineapi.PolicyResponse{
|
resp.PolicyResponse = engineapi.PolicyResponse{
|
||||||
Stats: engineapi.PolicyStats{
|
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()) {
|
for _, rule := range autogen.ComputeRules(policyContext.Policy()) {
|
||||||
logger := internal.LoggerWithRule(logger, rule)
|
logger := internal.LoggerWithRule(logger, rule)
|
||||||
if ruleResp := e.filterRule(rule, logger, policyContext); ruleResp != nil {
|
if ruleResp := e.filterRule(rule, logger, policyContext); ruleResp != nil {
|
||||||
|
|
|
@ -26,11 +26,12 @@ func (e *engine) verifyAndPatchImages(
|
||||||
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
|
) (engineapi.EngineResponse, engineapi.ImageVerificationMetadata) {
|
||||||
policy := policyContext.Policy()
|
policy := policyContext.Policy()
|
||||||
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
||||||
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
logger.V(4).Info(
|
internal.BuildResponse(policyContext, &resp, startTime)
|
||||||
"processed image verification rules",
|
logger.V(4).Info("processed image verification rules",
|
||||||
"time", resp.PolicyResponse.Stats.ProcessingTime.String(),
|
"time", resp.PolicyResponse.Stats.ProcessingTime.String(),
|
||||||
"applied", resp.PolicyResponse.Stats.RulesAppliedCount,
|
"applied", resp.PolicyResponse.Stats.RulesAppliedCount,
|
||||||
"successful", resp.IsSuccessful(),
|
"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,
|
logger logr.Logger,
|
||||||
policyContext engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) engineapi.EngineResponse {
|
) engineapi.EngineResponse {
|
||||||
startTime := time.Now()
|
|
||||||
policy := policyContext.Policy()
|
policy := policyContext.Policy()
|
||||||
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
resp := engineapi.NewEngineResponseFromPolicyContext(policyContext, nil)
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
matchedResource := policyContext.NewResource()
|
matchedResource := policyContext.NewResource()
|
||||||
var skippedRules []string
|
var skippedRules []string
|
||||||
|
|
||||||
|
|
|
@ -46,34 +46,22 @@ func (e *engine) validate(
|
||||||
func (e *engine) validateResource(
|
func (e *engine) validateResource(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
logger logr.Logger,
|
logger logr.Logger,
|
||||||
enginectx engineapi.PolicyContext,
|
policyContext engineapi.PolicyContext,
|
||||||
) *engineapi.PolicyResponse {
|
) *engineapi.PolicyResponse {
|
||||||
resp := &engineapi.PolicyResponse{}
|
resp := &engineapi.PolicyResponse{}
|
||||||
|
|
||||||
enginectx.JSONContext().Checkpoint()
|
policyContext.JSONContext().Checkpoint()
|
||||||
defer enginectx.JSONContext().Restore()
|
defer policyContext.JSONContext().Restore()
|
||||||
|
|
||||||
rules := autogen.ComputeRules(enginectx.Policy())
|
rules := autogen.ComputeRules(policyContext.Policy())
|
||||||
matchCount := 0
|
matchCount := 0
|
||||||
applyRules := enginectx.Policy().GetSpec().GetApplyRules()
|
applyRules := policyContext.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range rules {
|
for i := range rules {
|
||||||
rule := &rules[i]
|
rule := &rules[i]
|
||||||
logger := internal.LoggerWithRule(logger, rules[i])
|
logger := internal.LoggerWithRule(logger, rules[i])
|
||||||
logger.V(3).Info("processing validation rule", "matchCount", matchCount)
|
logger.V(3).Info("processing validation rule", "matchCount", matchCount)
|
||||||
enginectx.JSONContext().Reset()
|
policyContext.JSONContext().Reset()
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
ruleResp := tracing.ChildSpan1(
|
ruleResp := tracing.ChildSpan1(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -86,22 +74,21 @@ func (e *engine) validateResource(
|
||||||
if !hasValidate && !hasValidateImage {
|
if !hasValidate && !hasValidateImage {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if !matches(logger, rule, policyContext, e.configuration) {
|
||||||
if !matches(logger, rule, enginectx, e.configuration) {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// check if there is a corresponding policy exception
|
// 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 {
|
if ruleResp != nil {
|
||||||
return ruleResp
|
return ruleResp
|
||||||
}
|
}
|
||||||
enginectx.JSONContext().Reset()
|
policyContext.JSONContext().Reset()
|
||||||
if hasValidate && !hasYAMLSignatureVerify {
|
if hasValidate && !hasYAMLSignatureVerify {
|
||||||
return e.processValidationRule(ctx, logger, enginectx, rule)
|
return e.processValidationRule(ctx, logger, policyContext, rule)
|
||||||
} else if hasValidateImage {
|
} else if hasValidateImage {
|
||||||
return e.processImageValidationRule(ctx, logger, enginectx, rule)
|
return e.processImageValidationRule(ctx, logger, policyContext, rule)
|
||||||
} else if hasYAMLSignatureVerify {
|
} else if hasYAMLSignatureVerify {
|
||||||
return processYAMLValidationRule(e.client, logger, enginectx, rule)
|
return processYAMLValidationRule(e.client, logger, policyContext, rule)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -90,8 +90,9 @@ func (h *imageVerificationHandler) handleVerifyImages(
|
||||||
func(ctx context.Context, span trace.Span) {
|
func(ctx context.Context, span trace.Span) {
|
||||||
policyContext := policyContext.WithPolicy(policy)
|
policyContext := policyContext.WithPolicy(policy)
|
||||||
resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
|
resp, ivm := h.engine.VerifyAndPatchImages(ctx, policyContext)
|
||||||
|
if !resp.IsEmpty() {
|
||||||
engineResponses = append(engineResponses, resp)
|
engineResponses = append(engineResponses, resp)
|
||||||
|
}
|
||||||
patches = append(patches, resp.GetPatches()...)
|
patches = append(patches, resp.GetPatches()...)
|
||||||
verifiedImageData.Merge(ivm)
|
verifiedImageData.Merge(ivm)
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue