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

Support operators (>=, <, etc ...) on list values (#1838)

Signed-off-by: Max Goncharenko <kacejot@fex.net>
This commit is contained in:
Max Goncharenko 2021-04-28 23:31:55 +03:00 committed by GitHub
parent 9da2d44ee1
commit 0776b438d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 171 additions and 3 deletions

View file

@ -59,8 +59,18 @@ func validateResourceElement(log logr.Logger, resourceElement, patternElement, o
case string, float64, int, int64, bool, nil:
/*Analyze pattern */
if !ValidateValueWithPattern(log, resourceElement, patternElement) {
return path, fmt.Errorf("Validation rule failed at '%s' to validate value '%v' with pattern '%v'", path, resourceElement, patternElement)
switch resource := resourceElement.(type) {
case []interface{}:
for _, res := range resource {
if !ValidateValueWithPattern(log, res, patternElement) {
return path, fmt.Errorf("Validation rule failed at '%s' to validate value '%v' with pattern '%v'", path, resourceElement, patternElement)
}
}
return "", nil
default:
if !ValidateValueWithPattern(log, resourceElement, patternElement) {
return path, fmt.Errorf("Validation rule failed at '%s' to validate value '%v' with pattern '%v'", path, resourceElement, patternElement)
}
}
default:
@ -117,7 +127,6 @@ func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{}
}
func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, originPattern interface{}, path string, ac *common.AnchorKey) (string, error) {
if 0 == len(patternArray) {
return path, fmt.Errorf("Pattern Array empty")
}
@ -130,6 +139,11 @@ func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, o
if err != nil {
return elemPath, err
}
case string, float64, int, int64, bool, nil:
elemPath, err := validateResourceElement(log, resourceArray, typedPatternElement, originPattern, path, ac)
if err != nil {
return elemPath, err
}
default:
// In all other cases - detect type and handle each array element with validateResourceElement
if len(resourceArray) >= len(patternArray) {

View file

@ -713,6 +713,160 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
assert.Assert(t, er.IsSuccessful())
}
func TestValidate_inequality_List_Processing(t *testing.T) {
// anchor not present in resource
rawPolicy := []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "policy-secaas-k8s"
},
"spec": {
"rules": [
{
"name": "pod rule 2",
"match": {
"resources": {
"kinds": [
"Pod"
]
}
},
"validate": {
"message": "pod: validate run as non root user",
"pattern": {
"spec": {
"=(supplementalGroups)": ">0"
}
}
}
}
]
}
} `)
rawResource := []byte(`
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "myapp-pod",
"labels": {
"app": "v1"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx"
}
],
"supplementalGroups": [
"2",
"5",
"10"
]
}
}
`)
var policy kyverno.ClusterPolicy
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(&PolicyContext{Policy: policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index])
}
assert.Assert(t, er.IsSuccessful())
}
func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
// anchor not present in resource
rawPolicy := []byte(`{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "policy-secaas-k8s"
},
"spec": {
"rules": [
{
"name": "pod rule 2",
"match": {
"resources": {
"kinds": [
"Pod"
]
}
},
"validate": {
"message": "pod: validate run as non root user",
"pattern": {
"spec": {
"=(supplementalGroups)": [
">0 & <100001"
]
}
}
}
}
]
}
} `)
rawResource := []byte(`
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "myapp-pod",
"labels": {
"app": "v1"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx"
}
],
"supplementalGroups": [
"2",
"5",
"10",
"100",
"10000",
"1000",
"543"
]
}
}
`)
var policy kyverno.ClusterPolicy
err := json.Unmarshal(rawPolicy, &policy)
assert.NilError(t, err)
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err)
er := Validate(&PolicyContext{Policy: policy, NewResource: *resourceUnstructured, JSONContext: context.NewContext()})
msgs := []string{"validation rule 'pod rule 2' passed."}
for index, r := range er.PolicyResponse.Rules {
assert.Equal(t, r.Message, msgs[index])
}
assert.Assert(t, er.IsSuccessful())
}
func TestValidate_anchor_map_found_invalid(t *testing.T) {
// anchor not present in resource
rawPolicy := []byte(`{