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:
parent
9da2d44ee1
commit
0776b438d3
2 changed files with 171 additions and 3 deletions
|
@ -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) {
|
||||
|
|
|
@ -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(`{
|
||||
|
|
Loading…
Reference in a new issue