mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
validate existing anchor of validate rule
This commit is contained in:
parent
a72a73b8a9
commit
28bb9c80b4
2 changed files with 111 additions and 22 deletions
|
@ -69,3 +69,16 @@ func containString(list []string, element string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// hasExstingAnchor checks if str has existing anchor
|
||||
// strip anchor if necessary
|
||||
func hasExstingAnchor(str string) (bool, string) {
|
||||
left := "^("
|
||||
right := ")"
|
||||
|
||||
if len(str) < len(left)+len(right) {
|
||||
return false, str
|
||||
}
|
||||
|
||||
return (str[:len(left)] == left && str[len(str)-len(right):] == right), str[len(left) : len(str)-len(right)]
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
|
@ -12,8 +14,9 @@ func (p ClusterPolicy) Validate() error {
|
|||
var errs []error
|
||||
|
||||
for _, rule := range p.Spec.Rules {
|
||||
err := rule.Validate()
|
||||
errs = append(errs, err...)
|
||||
if ruleErrs := rule.Validate(); ruleErrs != nil {
|
||||
errs = append(errs, ruleErrs...)
|
||||
}
|
||||
}
|
||||
|
||||
if err := p.ValidateUniqueRuleName(); err != nil {
|
||||
|
@ -23,6 +26,19 @@ func (p ClusterPolicy) Validate() error {
|
|||
return joinErrs(errs)
|
||||
}
|
||||
|
||||
// ValidateUniqueRuleName checks if the rule names are unique across a policy
|
||||
func (p ClusterPolicy) ValidateUniqueRuleName() error {
|
||||
var ruleNames []string
|
||||
|
||||
for _, rule := range p.Spec.Rules {
|
||||
if containString(ruleNames, rule.Name) {
|
||||
return fmt.Errorf(`duplicate rule name: '%s'`, rule.Name)
|
||||
}
|
||||
ruleNames = append(ruleNames, rule.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate checks if rule is not empty and all substructures are valid
|
||||
func (r Rule) Validate() []error {
|
||||
var errs []error
|
||||
|
@ -46,6 +62,10 @@ func (r Rule) Validate() []error {
|
|||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
if patternErrs := r.ValidateExistingAnchor(); patternErrs != nil {
|
||||
errs = append(errs, patternErrs...)
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
|
@ -66,26 +86,6 @@ func (r Rule) ValidateOverlayPattern() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidateExistingAnchor
|
||||
// existing acnchor must define on array
|
||||
func (r Rule) ValidateExistingAnchor() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateUniqueRuleName checks if the rule names are unique across a policy
|
||||
func (p ClusterPolicy) ValidateUniqueRuleName() error {
|
||||
var ruleNames []string
|
||||
|
||||
for _, rule := range p.Spec.Rules {
|
||||
if containString(ruleNames, rule.Name) {
|
||||
return fmt.Errorf(`duplicate rule name: '%s'`, rule.Name)
|
||||
}
|
||||
ruleNames = append(ruleNames, rule.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateRuleType checks only one type of rule is defined per rule
|
||||
func (r Rule) ValidateRuleType() error {
|
||||
mutate := r.HasMutate()
|
||||
|
@ -174,3 +174,79 @@ func (gen *Generation) Validate() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateExistingAnchor
|
||||
// existing acnchor must define on array
|
||||
func (r Rule) ValidateExistingAnchor() []error {
|
||||
var errs []error
|
||||
|
||||
if r.Validation.Pattern != nil {
|
||||
if _, err := validateExistingAnchorOnPattern(r.Validation.Pattern, "/"); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.Validation.AnyPattern) != 0 {
|
||||
for _, pattern := range r.Validation.AnyPattern {
|
||||
if _, err := validateExistingAnchorOnPattern(pattern, "/"); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// validateExistingAnchorOnPattern validates ^() only defined on array
|
||||
func validateExistingAnchorOnPattern(pattern interface{}, path string) (string, error) {
|
||||
switch typedPattern := pattern.(type) {
|
||||
case map[string]interface{}:
|
||||
return validateMap(typedPattern, path)
|
||||
case []interface{}:
|
||||
return validateArray(typedPattern, path)
|
||||
case string, float64, int, int64, bool, nil:
|
||||
// check on type string
|
||||
if checkedPattern := reflect.ValueOf(pattern); checkedPattern.Kind() == reflect.String {
|
||||
if hasAnchor, str := hasExstingAnchor(checkedPattern.String()); hasAnchor {
|
||||
return path, fmt.Errorf("existing anchor at %s must be of type array, found: %T", path+str, checkedPattern.Kind())
|
||||
}
|
||||
}
|
||||
|
||||
// return nil on all other cases
|
||||
return "", nil
|
||||
default:
|
||||
glog.V(4).Infof("Pattern contains unknown type %T. Path: %s", pattern, path)
|
||||
return path, fmt.Errorf("pattern contains unknown type, path: %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
func validateMap(pattern map[string]interface{}, path string) (string, error) {
|
||||
for key, patternElement := range pattern {
|
||||
if hasAnchor, str := hasExstingAnchor(key); hasAnchor {
|
||||
if checkedPattern := reflect.ValueOf(patternElement); checkedPattern.Kind() != reflect.Slice {
|
||||
return path, fmt.Errorf("existing anchor at %s must be of type array, found: %T", path+str, patternElement)
|
||||
}
|
||||
}
|
||||
|
||||
if path, err := validateExistingAnchorOnPattern(patternElement, path+key+"/"); err != nil {
|
||||
return path, err
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func validateArray(patternArray []interface{}, path string) (string, error) {
|
||||
if len(patternArray) == 0 {
|
||||
return path, fmt.Errorf("pattern array at %s is empty", path)
|
||||
}
|
||||
|
||||
for i, pattern := range patternArray {
|
||||
currentPath := path + strconv.Itoa(i) + "/"
|
||||
if path, err := validateExistingAnchorOnPattern(pattern, currentPath); err != nil {
|
||||
return path, err
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue