mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
add validation check to ensure the annotations quoted (#3976)
This commit is contained in:
parent
85b486eb27
commit
bea0b794d5
3 changed files with 82 additions and 40 deletions
1
go.mod
1
go.mod
|
@ -195,6 +195,7 @@ require (
|
|||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jedisct1/go-minisign v0.0.0-20210703085342-c1f07ee84431 // indirect
|
||||
github.com/jhump/protoreflect v1.9.0 // indirect
|
||||
github.com/jmoiron/jsonq v0.0.0-20150511023944-e874b168d07e // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -1310,6 +1310,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
|
|||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=
|
||||
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
|
||||
github.com/jmoiron/jsonq v0.0.0-20150511023944-e874b168d07e h1:ZZCvgaRDZg1gC9/1xrsgaJzQUCQgniKtw0xjWywWAOE=
|
||||
github.com/jmoiron/jsonq v0.0.0-20150511023944-e874b168d07e/go.mod h1:+rHyWac2R9oAZwFe1wGY2HBzFJJy++RHBg1cU23NkD8=
|
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/distribution/distribution/reference"
|
||||
jsonpatch "github.com/evanphx/json-patch/v5"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/jmoiron/jsonq"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
|
@ -562,34 +563,26 @@ func validateMatchKindHelper(rule kyvernov1.Rule) error {
|
|||
|
||||
// isLabelAndAnnotationsString :- Validate if labels and annotations contains only string values
|
||||
func isLabelAndAnnotationsString(rule kyvernov1.Rule) bool {
|
||||
// checkMetadata - Verify if the labels and annotations contains string value inside metadata
|
||||
checkMetadata := func(patternMap map[string]interface{}) bool {
|
||||
for k := range patternMap {
|
||||
if k == "metadata" {
|
||||
metaKey, ok := patternMap[k].(map[string]interface{})
|
||||
|
||||
checkLabelAnnotation := func(metaKey map[string]interface{}) bool {
|
||||
for mk := range metaKey {
|
||||
if mk == "labels" {
|
||||
labelKey, ok := metaKey[mk].(map[string]interface{})
|
||||
if ok {
|
||||
// range over metadata
|
||||
for mk := range metaKey {
|
||||
if mk == "labels" {
|
||||
labelKey, ok := metaKey[mk].(map[string]interface{})
|
||||
if ok {
|
||||
// range over labels
|
||||
for _, val := range labelKey {
|
||||
if reflect.TypeOf(val).String() != "string" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if mk == "annotations" {
|
||||
annotationKey, ok := metaKey[mk].(map[string]interface{})
|
||||
if ok {
|
||||
// range over annotations
|
||||
for _, val := range annotationKey {
|
||||
if reflect.TypeOf(val).String() != "string" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
// range over labels
|
||||
for _, val := range labelKey {
|
||||
if reflect.TypeOf(val).String() != "string" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if mk == "annotations" {
|
||||
annotationKey, ok := metaKey[mk].(map[string]interface{})
|
||||
if ok {
|
||||
// range over annotations
|
||||
for _, val := range annotationKey {
|
||||
if reflect.TypeOf(val).String() != "string" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -598,26 +591,72 @@ func isLabelAndAnnotationsString(rule kyvernov1.Rule) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
patternMap, ok := rule.Validation.GetPattern().(map[string]interface{})
|
||||
if ok {
|
||||
return checkMetadata(patternMap)
|
||||
} else if rule.Validation.GetAnyPattern() != nil {
|
||||
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
|
||||
if err != nil {
|
||||
log.Log.Error(err, "failed to deserialize anyPattern, expect type array")
|
||||
return false
|
||||
// checkMetadata - Verify if the labels and annotations contains string value inside metadata
|
||||
checkMetadata := func(patternMap map[string]interface{}) bool {
|
||||
for k := range patternMap {
|
||||
if k == "metadata" {
|
||||
metaKey, ok := patternMap[k].(map[string]interface{})
|
||||
if ok {
|
||||
// range over metadata
|
||||
return checkLabelAnnotation(metaKey)
|
||||
}
|
||||
}
|
||||
if k == "spec" {
|
||||
metadata, _ := jsonq.NewQuery(patternMap).Object("spec", "template", "metadata")
|
||||
return checkLabelAnnotation(metadata)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
for _, pattern := range anyPatterns {
|
||||
patternMap, ok := pattern.(map[string]interface{})
|
||||
if rule.HasValidate() {
|
||||
if rule.Validation.ForEachValidation != nil {
|
||||
for _, foreach := range rule.Validation.ForEachValidation {
|
||||
patternMap, ok := foreach.GetPattern().(map[string]interface{})
|
||||
if ok {
|
||||
return checkMetadata(patternMap)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
patternMap, ok := rule.Validation.GetPattern().(map[string]interface{})
|
||||
if ok {
|
||||
ret := checkMetadata(patternMap)
|
||||
if !ret {
|
||||
return ret
|
||||
return checkMetadata(patternMap)
|
||||
} else if rule.Validation.GetAnyPattern() != nil {
|
||||
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
|
||||
if err != nil {
|
||||
log.Log.Error(err, "failed to deserialize anyPattern, expect type array")
|
||||
return false
|
||||
}
|
||||
|
||||
for _, pattern := range anyPatterns {
|
||||
patternMap, ok := pattern.(map[string]interface{})
|
||||
if ok {
|
||||
ret := checkMetadata(patternMap)
|
||||
if !ret {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if rule.HasMutate() {
|
||||
if rule.Mutation.ForEachMutation != nil {
|
||||
for _, foreach := range rule.Mutation.ForEachMutation {
|
||||
forEachStrategicMergeMap, ok := foreach.GetPatchStrategicMerge().(map[string]interface{})
|
||||
if ok {
|
||||
return checkMetadata(forEachStrategicMergeMap)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strategicMergeMap, ok := rule.Mutation.GetPatchStrategicMerge().(map[string]interface{})
|
||||
if ok {
|
||||
return checkMetadata(strategicMergeMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue