mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 07:26:55 +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:
parent
6ae3063038
commit
1ebd2c99f2
3 changed files with 44 additions and 24 deletions
|
@ -335,7 +335,7 @@ func checkCondition(logger logr.Logger, pattern *yaml.RNode, resource *yaml.RNod
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err, _ = validate.MatchPattern(logger, resourceInterface, patternInterface)
|
err = validate.MatchPattern(logger, resourceInterface, patternInterface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,24 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/engine/wildcards"
|
"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.
|
// MatchPattern is a start of element-by-element pattern validation process.
|
||||||
// It assumes that validation is started from root, so "/" is passed
|
// 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
|
// newAnchorMap - to check anchor key has values
|
||||||
ac := common.NewAnchorMap()
|
ac := common.NewAnchorMap()
|
||||||
elemPath, err := validateResourceElement(logger, resource, pattern, pattern, "/", ac)
|
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 conditional or global anchors report errors, the rule does not apply to the resource
|
||||||
if common.IsConditionalAnchorError(err.Error()) || common.IsGlobalAnchorError(err.Error()) {
|
if common.IsConditionalAnchorError(err.Error()) || common.IsGlobalAnchorError(err.Error()) {
|
||||||
logger.V(3).Info("skipping resource as anchor does not apply", "msg", ac.AnchorError.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
|
// check if an anchor defined in the policy rule is missing in the resource
|
||||||
if ac.IsAnchorError() {
|
if ac.IsAnchorError() {
|
||||||
logger.V(3).Info("missing anchor in resource")
|
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)
|
// validateResourceElement detects the element type (map, array, nil, string, int, bool, float)
|
||||||
|
|
|
@ -193,7 +193,7 @@ func (v *validator) validate() *response.RuleResponse {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, "failed to evaluate preconditions", err)
|
return ruleError(v.rule, "failed to evaluate preconditions", err)
|
||||||
} else if !preconditionsPassed {
|
} 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 {
|
if v.pattern != nil || v.anyPattern != nil {
|
||||||
|
@ -222,7 +222,7 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ruleError(v.rule, "failed to evaluate preconditions", err)
|
return ruleError(v.rule, "failed to evaluate preconditions", err)
|
||||||
} else if !preconditionsPassed {
|
} else if !preconditionsPassed {
|
||||||
return ruleResponse(v.rule, "", response.RuleStatusSkip)
|
return ruleResponse(v.rule, "preconditions not met", response.RuleStatusSkip)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach := v.rule.Validation.ForEachValidation
|
foreach := v.rule.Validation.ForEachValidation
|
||||||
|
@ -266,10 +266,10 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
if applyCount == 0 {
|
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 {
|
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
|
// validatePatterns validate pattern and anyPattern
|
||||||
func (v *validator) validatePatterns(resource unstructured.Unstructured) *response.RuleResponse {
|
func (v *validator) validatePatterns(resource unstructured.Unstructured) *response.RuleResponse {
|
||||||
if v.pattern != nil {
|
if v.pattern != nil {
|
||||||
if err, path := validate.MatchPattern(v.log, resource.Object, v.pattern); err != nil {
|
if err := 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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")
|
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 {
|
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 {
|
if err == nil {
|
||||||
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
msg := fmt.Sprintf("validation rule '%s' anyPattern[%d] passed.", v.rule.Name, idx)
|
||||||
return ruleResponse(v.rule, msg, response.RuleStatusPass)
|
return ruleResponse(v.rule, msg, response.RuleStatusPass)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.log.V(3).Info("validation rule failed", "anyPattern[%d]", idx, "path", path)
|
if pe, ok := err.(*validate.PatternError); ok {
|
||||||
if path == "" {
|
v.log.V(3).Info("validation rule failed", "anyPattern[%d]", idx, "path", pe.Path)
|
||||||
patternErr := fmt.Errorf("Rule %s[%d] failed: %s.", v.rule.Name, idx, err.Error())
|
if pe.Path == "" {
|
||||||
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
|
patternErr := fmt.Errorf("Rule %s[%d] failed: %s.", v.rule.Name, idx, err.Error())
|
||||||
} else {
|
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
|
||||||
patternErr := fmt.Errorf("Rule %s[%d] failed at path %s.", v.rule.Name, idx, path)
|
} else {
|
||||||
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
|
patternErr := fmt.Errorf("Rule %s[%d] failed at path %s.", v.rule.Name, idx, pe.Path)
|
||||||
|
failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue