1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

add messages and set rule to skip when pattern does not match

Signed-off-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Jim Bugwadia 2021-09-30 23:34:04 -07:00
parent 6ae3063038
commit 1ebd2c99f2
3 changed files with 44 additions and 24 deletions

View file

@ -335,7 +335,7 @@ func checkCondition(logger logr.Logger, pattern *yaml.RNode, resource *yaml.RNod
return err
}
err, _ = validate.MatchPattern(logger, resourceInterface, patternInterface)
err = validate.MatchPattern(logger, resourceInterface, patternInterface)
if err != nil {
return err
}

View file

@ -12,9 +12,24 @@ import (
"github.com/kyverno/kyverno/pkg/engine/wildcards"
)
type PatternError struct {
Err error
Path string
Skip bool
}
func (e *PatternError) Error() string {
if e.Err == nil {
return ""
}
return e.Err.Error()
}
// MatchPattern is a start of element-by-element pattern validation process.
// It assumes that validation is started from root, so "/" is passed
func MatchPattern(logger logr.Logger, resource, pattern interface{}) (error, string) {
func MatchPattern(logger logr.Logger, resource, pattern interface{}) error {
// newAnchorMap - to check anchor key has values
ac := common.NewAnchorMap()
elemPath, err := validateResourceElement(logger, resource, pattern, pattern, "/", ac)
@ -22,19 +37,19 @@ func MatchPattern(logger logr.Logger, resource, pattern interface{}) (error, str
// if conditional or global anchors report errors, the rule does not apply to the resource
if common.IsConditionalAnchorError(err.Error()) || common.IsGlobalAnchorError(err.Error()) {
logger.V(3).Info("skipping resource as anchor does not apply", "msg", ac.AnchorError.Error())
return nil, ""
return &PatternError{nil, "", true}
}
// check if an anchor defined in the policy rule is missing in the resource
if ac.IsAnchorError() {
logger.V(3).Info("missing anchor in resource")
return err, ""
return &PatternError{err, "", false}
}
return err, elemPath
return &PatternError{err, elemPath, false}
}
return nil, ""
return &PatternError{nil, "", false}
}
// validateResourceElement detects the element type (map, array, nil, string, int, bool, float)

View file

@ -193,7 +193,7 @@ func (v *validator) validate() *response.RuleResponse {
if err != nil {
return ruleError(v.rule, "failed to evaluate preconditions", err)
} else if !preconditionsPassed {
return ruleResponse(v.rule, "", response.RuleStatusSkip)
return ruleResponse(v.rule, "preconditions not met", response.RuleStatusSkip)
}
if v.pattern != nil || v.anyPattern != nil {
@ -222,7 +222,7 @@ func (v *validator) validateForEach() *response.RuleResponse {
if err != nil {
return ruleError(v.rule, "failed to evaluate preconditions", err)
} else if !preconditionsPassed {
return ruleResponse(v.rule, "", response.RuleStatusSkip)
return ruleResponse(v.rule, "preconditions not met", response.RuleStatusSkip)
}
foreach := v.rule.Validation.ForEachValidation
@ -266,10 +266,10 @@ func (v *validator) validateForEach() *response.RuleResponse {
}
if applyCount == 0 {
return ruleResponse(v.rule, "", response.RuleStatusSkip)
return ruleResponse(v.rule, "rule skipped", response.RuleStatusSkip)
}
return ruleResponse(v.rule, "", response.RuleStatusPass)
return ruleResponse(v.rule, "rule passed", response.RuleStatusPass)
}
func addElementToContext(ctx *PolicyContext, e interface{}) error {
@ -436,13 +436,16 @@ func isSameRuleResponse(r1 *response.RuleResponse, r2 *response.RuleResponse) bo
// validatePatterns validate pattern and anyPattern
func (v *validator) validatePatterns(resource unstructured.Unstructured) *response.RuleResponse {
if v.pattern != nil {
if err, path := validate.MatchPattern(v.log, resource.Object, v.pattern); err != nil {
v.log.V(3).Info("validation error", "path", path, "error", err.Error())
if path == "" {
return ruleResponse(v.rule, v.buildErrorMessage(err, ""), response.RuleStatusError)
}
if err := validate.MatchPattern(v.log, resource.Object, v.pattern); err != nil {
return ruleResponse(v.rule, v.buildErrorMessage(err, path), response.RuleStatusFail)
if pe, ok := err.(*validate.PatternError); ok{
v.log.V(3).Info("validation error", "path", pe.Path, "error", err.Error())
if pe.Path == "" {
return ruleResponse(v.rule, v.buildErrorMessage(err, ""), response.RuleStatusError)
}
return ruleResponse(v.rule, v.buildErrorMessage(err, pe.Path), response.RuleStatusFail)
}
}
v.log.V(4).Info("successfully processed rule")
@ -461,19 +464,21 @@ func (v *validator) validatePatterns(resource unstructured.Unstructured) *respon
}
for idx, pattern := range anyPatterns {
err, path := validate.MatchPattern(v.log, resource.Object, pattern)
err := validate.MatchPattern(v.log, resource.Object, pattern)
if err == nil {
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
return ruleResponse(v.rule, msg, response.RuleStatusPass)
}
v.log.V(3).Info("validation rule failed", "anyPattern[%d]", idx, "path", path)
if path == "" {
patternErr := fmt.Errorf("Rule %s[%d] failed: %s.", v.rule.Name, idx, err.Error())
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
} else {
patternErr := fmt.Errorf("Rule %s[%d] failed at path %s.", v.rule.Name, idx, path)
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
if pe, ok := err.(*validate.PatternError); ok {
v.log.V(3).Info("validation rule failed", "anyPattern[%d]", idx, "path", pe.Path)
if pe.Path == "" {
patternErr := fmt.Errorf("Rule %s[%d] failed: %s.", v.rule.Name, idx, err.Error())
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
} else {
patternErr := fmt.Errorf("Rule %s[%d] failed at path %s.", v.rule.Name, idx, pe.Path)
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
}
}
}