1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/engine/validation_test.go

982 lines
17 KiB
Go
Raw Normal View History

2019-05-16 21:37:54 +03:00
package engine
import (
"encoding/json"
"testing"
2019-05-21 11:00:09 -07:00
kubepolicy "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
2019-05-16 21:37:54 +03:00
"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2019-05-16 21:37:54 +03:00
)
func TestWrappedWithParentheses_StringIsWrappedWithParentheses(t *testing.T) {
str := "(something)"
assert.Assert(t, wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_StringHasOnlyParentheses(t *testing.T) {
str := "()"
assert.Assert(t, wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_StringHasNoParentheses(t *testing.T) {
str := "something"
assert.Assert(t, !wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_StringHasLeftParentheses(t *testing.T) {
str := "(something"
assert.Assert(t, !wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_StringHasRightParentheses(t *testing.T) {
str := "something)"
assert.Assert(t, !wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_StringParenthesesInside(t *testing.T) {
str := "so)m(et(hin)g"
assert.Assert(t, !wrappedWithParentheses(str))
}
func TestWrappedWithParentheses_Empty(t *testing.T) {
str := ""
assert.Assert(t, !wrappedWithParentheses(str))
}
func TestCheckForWildcard_AsteriskTest(t *testing.T) {
pattern := "*"
value := "anything"
empty := ""
assert.Assert(t, checkForWildcard(value, pattern))
assert.Assert(t, checkForWildcard(empty, pattern))
}
func TestCheckForWildcard_LeftAsteriskTest(t *testing.T) {
pattern := "*right"
value := "leftright"
right := "right"
assert.Assert(t, checkForWildcard(value, pattern))
assert.Assert(t, checkForWildcard(right, pattern))
value = "leftmiddle"
middle := "middle"
assert.Assert(t, checkForWildcard(value, pattern) != nil)
assert.Assert(t, checkForWildcard(middle, pattern) != nil)
2019-05-16 21:37:54 +03:00
}
func TestCheckForWildcard_MiddleAsteriskTest(t *testing.T) {
pattern := "ab*ba"
value := "abbeba"
assert.NilError(t, checkForWildcard(value, pattern))
2019-05-16 21:37:54 +03:00
value = "abbca"
assert.Assert(t, checkForWildcard(value, pattern) != nil)
2019-05-16 21:37:54 +03:00
}
func TestCheckForWildcard_QuestionMark(t *testing.T) {
pattern := "ab?ba"
value := "abbba"
assert.NilError(t, checkForWildcard(value, pattern))
2019-05-16 21:37:54 +03:00
value = "abbbba"
assert.Assert(t, checkForWildcard(value, pattern) != nil)
2019-05-16 21:37:54 +03:00
}
func TestSkipArrayObject_OneAnchor(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawAnchors := []byte(`{
"(name)":"nirmata-*"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
2019-06-05 10:24:18 +03:00
"namespace":"kyverno",
2019-06-04 17:33:21 +03:00
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
2019-05-16 21:37:54 +03:00
var resource, anchor map[string]interface{}
json.Unmarshal(rawAnchors, &anchor)
json.Unmarshal(rawResource, &resource)
assert.Assert(t, !skipArrayObject(resource, anchor))
}
func TestSkipArrayObject_OneNumberAnchorPass(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawAnchors := []byte(`{
"(count)":1
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
"count":1,
2019-06-05 10:24:18 +03:00
"namespace":"kyverno",
2019-06-04 17:33:21 +03:00
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
2019-05-16 21:37:54 +03:00
var resource, anchor map[string]interface{}
json.Unmarshal(rawAnchors, &anchor)
json.Unmarshal(rawResource, &resource)
assert.Assert(t, !skipArrayObject(resource, anchor))
}
func TestSkipArrayObject_TwoAnchorsPass(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawAnchors := []byte(`{
"(name)":"nirmata-*",
"(namespace)":"kube-?olicy"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
2019-06-05 10:24:18 +03:00
"namespace":"kyverno",
2019-06-04 17:33:21 +03:00
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
2019-05-16 21:37:54 +03:00
var resource, anchor map[string]interface{}
json.Unmarshal(rawAnchors, &anchor)
json.Unmarshal(rawResource, &resource)
assert.Assert(t, !skipArrayObject(resource, anchor))
}
func TestSkipArrayObject_TwoAnchorsSkip(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawAnchors := []byte(`{
"(name)":"nirmata-*",
"(namespace)":"some-?olicy"
}`)
rawResource := []byte(`{
"name":"nirmata-resource",
2019-06-05 10:24:18 +03:00
"namespace":"kyverno",
2019-06-04 17:33:21 +03:00
"object":{
"label":"app",
"array":[
1,
2,
3
]
}
}`)
2019-05-16 21:37:54 +03:00
var resource, anchor map[string]interface{}
json.Unmarshal(rawAnchors, &anchor)
json.Unmarshal(rawResource, &resource)
assert.Assert(t, skipArrayObject(resource, anchor))
}
func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawMap := []byte(`{
"(name)":"nirmata-*",
"notAnchor1":123,
"(namespace)":"kube-?olicy",
"notAnchor2":"sample-text",
"object":{
"key1":"value1",
"(key2)":"value2"
}
}`)
2019-05-16 21:37:54 +03:00
var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled)
2019-05-21 18:27:56 +03:00
actualMap := GetAnchorsFromMap(unmarshalled)
2019-05-16 21:37:54 +03:00
assert.Equal(t, len(actualMap), 2)
assert.Equal(t, actualMap["(name)"].(string), "nirmata-*")
assert.Equal(t, actualMap["(namespace)"].(string), "kube-?olicy")
}
func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawMap := []byte(`{
"name":"nirmata-*",
"notAnchor1":123,
"namespace":"kube-?olicy",
"notAnchor2":"sample-text",
"object":{
"key1":"value1",
"(key2)":"value2"
}
}`)
2019-05-16 21:37:54 +03:00
var unmarshalled map[string]interface{}
json.Unmarshal(rawMap, &unmarshalled)
2019-05-21 18:27:56 +03:00
actualMap := GetAnchorsFromMap(unmarshalled)
2019-05-16 21:37:54 +03:00
assert.Assert(t, len(actualMap) == 0)
}
func TestValidateMap(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"?*",
"resources":{
"requests":{
"cpu":"<4|8"
}
}
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec":{
"replicas":3,
"selector":{
"matchLabels":{
"app":"nginx"
}
},
"template":{
"metadata":{
"labels":{
"app":"nginx"
}
},
"spec":{
"securityContext":{
"runAsNonRoot":true
},
"containers":[
{
"name":"nginx",
"image":"https://nirmata/nginx:latest",
"imagePullPolicy":"Always",
"readinessProbe":{
"exec":{
"command":[
"cat",
"/tmp/healthy"
]
},
"initialDelaySeconds":5,
"periodSeconds":10
},
"livenessProbe":{
"tcpSocket":{
"port":8080
},
"initialDelaySeconds":15,
"periodSeconds":11
},
"resources":{
"limits":{
"memory":"2Gi",
"cpu":8
},
"requests":{
"memory":"512Mi",
"cpu":"8"
}
},
"ports":[
{
"containerPort":80
}
]
}
]
}
}
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
2019-06-04 17:33:21 +03:00
func TestValidateMap_AsteriskForInt(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":{
"periodSeconds":"*"
}
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}
`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskForMap(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":"*"
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskForArray(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":"*"
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":{
"periodSeconds":11
}
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMap(resource, pattern))
}
func TestValidateMap_AsteriskFieldIsMissing(t *testing.T) {
rawPattern := []byte(`{
"spec":{
"template":{
"spec":{
"containers":[
{
"name":"*",
"livenessProbe":"*"
}
]
}
}
}
}`)
rawMap := []byte(`{
"apiVersion":"apps/v1",
"kind":"StatefulSet",
"metadata":{
"name":"game-web",
"labels":{
"originalLabel":"isHere"
}
},
"spec":{
"selector":{
"matchLabels":{
"app":"nginxo"
}
},
"serviceName":"nginxo",
"replicas":3,
"template":{
"metadata":{
"labels":{
"app":"nginxo"
}
},
"spec":{
"terminationGracePeriodSeconds":10,
"containers":[
{
"name":"nginxo",
"image":"k8s.gcr.io/nginx-but-no-slim:0.8",
"ports":[
{
"containerPort":8780,
"name":"webp"
}
],
"volumeMounts":[
{
"name":"www",
"mountPath":"/usr/share/nginxo/html"
}
],
"livenessProbe":null
}
]
}
},
"volumeClaimTemplates":[
{
"metadata":{
"name":"www"
},
"spec":{
"accessModes":[
"ReadWriteOnce"
],
"storageClassName":"my-storage-class",
"resources":{
"requests":{
"storage":"1Gi"
}
}
}
}
]
}
}`)
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.Assert(t, validateMap(resource, pattern) != nil)
}
2019-05-16 21:37:54 +03:00
func TestValidateMapElement_TwoElementsInArrayOnePass(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value1",
"key2":"value2"
}
]
},
{
"name":"nirmata-1",
"object":[
{
"key1":"not_value",
"key2":"not_value"
}
]
}
]`)
2019-05-16 21:37:54 +03:00
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMapElement(resource, pattern))
2019-05-16 21:37:54 +03:00
}
func TestValidateMapElement_OneElementInArrayPass(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value1",
"key2":"value2"
}
]
}
]`)
2019-05-16 21:37:54 +03:00
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.NilError(t, validateMapElement(resource, pattern))
2019-05-16 21:37:54 +03:00
}
func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPattern := []byte(`[
{
"(name)":"nirmata-*",
"object":[
{
"(key1)":"value*",
"key2":"value*"
}
]
}
]`)
rawMap := []byte(`[
{
"name":"nirmata-1",
"object":[
{
"key1":"value5",
"key2":"1value1"
}
]
}
]`)
2019-05-16 21:37:54 +03:00
var pattern, resource interface{}
json.Unmarshal(rawPattern, &pattern)
json.Unmarshal(rawMap, &resource)
assert.Assert(t, validateMapElement(resource, pattern) != nil)
}
func TestValidate_ServiceTest(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPolicy := []byte(`{
"apiVersion":"kyverno.nirmata.io/v1alpha1",
"kind":"Policy",
"metadata":{
"name":"policy-service"
},
"spec":{
"rules":[
{
"name":"ps1",
"resource":{
"kinds":[
"Service"
],
"name":"game-service*"
},
"mutate":{
"patches":[
{
"path":"/metadata/labels/isMutated",
"op":"add",
"value":"true"
},
{
"path":"/metadata/labels/secretLabel",
"op":"replace",
"value":"weKnow"
},
{
"path":"/metadata/labels/originalLabel",
"op":"remove"
},
{
"path":"/spec/selector/app",
"op":"replace",
"value":"mutedApp"
}
]
},
"validate":{
"message":"This resource is broken",
"pattern":{
"spec":{
"ports":[
{
"name":"hs",
"protocol":32
}
]
}
}
}
}
]
}
}`)
rawResource := []byte(`{
"kind":"Service",
"apiVersion":"v1",
"metadata":{
"name":"game-service",
"labels":{
"originalLabel":"isHere",
"secretLabel":"thisIsMySecret"
}
},
"spec":{
"selector":{
"app":"MyApp"
},
"ports":[
{
"name":"http",
"protocol":"TCP",
"port":80,
"targetPort":9376
}
]
}
}
`)
var policy kubepolicy.Policy
json.Unmarshal(rawPolicy, &policy)
gvk := metav1.GroupVersionKind{
Kind: "Service",
}
assert.Assert(t, Validate(policy, rawResource, gvk) != nil)
2019-05-16 21:37:54 +03:00
}
2019-05-20 17:07:09 +03:00
func TestValidate_MapHasFloats(t *testing.T) {
2019-06-04 17:33:21 +03:00
rawPolicy := []byte(`{
"apiVersion":"kyverno.nirmata.io/v1alpha1",
"kind":"Policy",
"metadata":{
"name":"policy-deployment-changed"
},
"spec":{
"rules":[
{
"name":"First policy v2",
"resource":{
"kinds":[
"Deployment"
],
"name":"nginx-*"
},
"mutate":{
"patches":[
{
"path":"/metadata/labels/isMutated",
"op":"add",
"value":"true"
},
{
"path":"/metadata/labels/app",
"op":"replace",
"value":"nginx_is_mutated"
}
]
},
"validate":{
"message":"replicas number is wrong",
"pattern":{
"metadata":{
"labels":{
"app":"*"
}
},
"spec":{
"replicas":3
}
}
}
}
]
}
}`)
rawResource := []byte(`{
"apiVersion":"apps/v1",
"kind":"Deployment",
"metadata":{
"name":"nginx-deployment",
"labels":{
"app":"nginx"
}
},
"spec":{
"replicas":3,
"selector":{
"matchLabels":{
"app":"nginx"
}
},
"template":{
"metadata":{
"labels":{
"app":"nginx"
}
},
"spec":{
"containers":[
{
"name":"nginx",
"image":"nginx:1.7.9",
"ports":[
{
"containerPort":80
}
]
}
]
}
}
}
}
`)
2019-05-20 17:07:09 +03:00
var policy kubepolicy.Policy
json.Unmarshal(rawPolicy, &policy)
gvk := metav1.GroupVersionKind{
Kind: "Deployment",
}
assert.NilError(t, Validate(policy, rawResource, gvk))
}