1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/webhooks/resource/handlers_test.go
Charles-Edouard Brétéché 665e513c5e
fix: split webhook handlers per failure policy (#4650)
* fix: split webhook handlers per failure policy

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* fix handlers

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* rolling update

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

* better error message

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>

Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com>
2022-09-26 15:55:46 +00:00

285 lines
7 KiB
Go

package resource
import (
"context"
"encoding/json"
"testing"
"time"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/policycache"
"gotest.tools/assert"
v1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/runtime"
log "sigs.k8s.io/controller-runtime/pkg/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
var policyCheckLabel = `{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "check-label-app"
},
"spec": {
"validationFailureAction": "audit",
"rules": [
{
"name": "check-label-app",
"match": {
"resources": {
"kinds": [
"Pod"
]
}
},
"validate": {
"message": "The label 'app' is required.",
"pattern": {
"metadata": {
"labels": {
"app": "?*"
}
}
}
}
}
]
}
}
`
var policyInvalid = `{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "check-label-app"
},
"spec": {
"validationFailureAction": "audit",
"rules": [
{
"name": "check-label-app",
"match": {
"resources": {
"kinds": [
"Pod"
]
}
},
"validate": {
"message": "The label 'app' is required.",
"pattern": {
"metadata": {
"labels": {
"app": "{{ invalid-jmespath }}"
}
}
}
}
}
]
}
}
`
var policyVerifySignature = `
{
"apiVersion": "kyverno.io/v1",
"kind": "ClusterPolicy",
"metadata": {
"name": "check-image",
"annotations": {
"pod-policies.kyverno.io/autogen-controllers": "none"
}
},
"spec": {
"validationFailureAction": "enforce",
"background": false,
"webhookTimeoutSeconds": 30,
"failurePolicy": "Fail",
"rules": [
{
"name": "check-signature",
"match": {
"resources": {
"kinds": [
"Pod"
]
}
},
"verifyImages": [
{
"imageReferences": [
"*"
],
"attestors": [
{
"entries": [
{
"keys": {
"publicKeys": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM\n5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----"
}
}
]
}
]
}
]
}
]
}
}
`
var pod = `{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "test-pod",
"namespace": ""
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:latest"
}
]
}
}
`
func Test_AdmissionResponseValid(t *testing.T) {
policyCache := policycache.NewCache()
logger := log.Log.WithName("Test_AdmissionResponseValid")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
handlers := NewFakeHandlers(ctx, policyCache)
var validPolicy kyverno.ClusterPolicy
err := json.Unmarshal([]byte(policyCheckLabel), &validPolicy)
assert.NilError(t, err)
key := makeKey(&validPolicy)
policyCache.Set(key, &validPolicy)
request := &v1.AdmissionRequest{
Operation: v1.Create,
Kind: metav1.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
Resource: metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "Pod"},
Object: runtime.RawExtension{
Raw: []byte(pod),
},
}
response := handlers.Mutate(logger, request, "", time.Now())
assert.Assert(t, response != nil)
assert.Equal(t, response.Allowed, true)
response = handlers.Validate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, true)
assert.Equal(t, len(response.Warnings), 0)
validPolicy.Spec.ValidationFailureAction = kyverno.Enforce
policyCache.Set(key, &validPolicy)
response = handlers.Validate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, false)
assert.Equal(t, len(response.Warnings), 0)
policyCache.Unset(key)
}
func Test_AdmissionResponseInvalid(t *testing.T) {
policyCache := policycache.NewCache()
logger := log.Log.WithName("Test_AdmissionResponseInvalid")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
handlers := NewFakeHandlers(ctx, policyCache)
var invalidPolicy kyverno.ClusterPolicy
err := json.Unmarshal([]byte(policyInvalid), &invalidPolicy)
assert.NilError(t, err)
request := &v1.AdmissionRequest{
Operation: v1.Create,
Kind: metav1.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
Resource: metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "Pod"},
Object: runtime.RawExtension{
Raw: []byte(pod),
},
}
keyInvalid := makeKey(&invalidPolicy)
invalidPolicy.Spec.ValidationFailureAction = kyverno.Enforce
policyCache.Set(keyInvalid, &invalidPolicy)
response := handlers.Validate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, false)
assert.Equal(t, len(response.Warnings), 0)
var ignore kyverno.FailurePolicyType = kyverno.Ignore
invalidPolicy.Spec.FailurePolicy = &ignore
policyCache.Set(keyInvalid, &invalidPolicy)
response = handlers.Validate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, true)
assert.Equal(t, len(response.Warnings), 1)
}
func Test_ImageVerify(t *testing.T) {
policyCache := policycache.NewCache()
logger := log.Log.WithName("Test_ImageVerify")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
handlers := NewFakeHandlers(ctx, policyCache)
var policy kyverno.ClusterPolicy
err := json.Unmarshal([]byte(policyVerifySignature), &policy)
assert.NilError(t, err)
key := makeKey(&policy)
policyCache.Set(key, &policy)
request := &v1.AdmissionRequest{
Operation: v1.Create,
Kind: metav1.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"},
Resource: metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "Pod"},
Object: runtime.RawExtension{
Raw: []byte(pod),
},
}
policy.Spec.ValidationFailureAction = kyverno.Enforce
policyCache.Set(key, &policy)
response := handlers.Mutate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, false)
assert.Equal(t, len(response.Warnings), 0)
var ignore kyverno.FailurePolicyType = kyverno.Ignore
policy.Spec.FailurePolicy = &ignore
policyCache.Set(key, &policy)
response = handlers.Mutate(logger, request, "", time.Now())
assert.Equal(t, response.Allowed, false)
assert.Equal(t, len(response.Warnings), 0)
}
func makeKey(policy kyverno.PolicyInterface) string {
name := policy.GetName()
namespace := policy.GetNamespace()
if namespace == "" {
return name
}
return namespace + "/" + name
}