mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-15 17:51:20 +00:00
cfc9683033
* Changes to dynamically configure webhooks Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add unit tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add kuttl tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Refactoring Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct unit test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Change way of webhooks configured Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct tests with new changes Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add delete operation by default Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct tests with new changes Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct order for operations Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add corrections Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add mutatingwebhookconfiguration test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct unit test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Added policy.yaml in mutate webhook test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add corrections in kuttl test and code Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Change name of test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Changes to update webhooks manifest Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add corrections for dynamic-op-mutate kuttl test Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Add minor changes; remove unnecessary file Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Correct adding operations for MutatingWebhookConf Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * dynamic op mutate and validate added Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Resolve conflicts Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Filter rules for mutatingwebhookconf correctly Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * replace TestStep with Test in chainsaw tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * converted to new chainsaw-test format Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * minor corrections Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * remove isMutationEmpty() Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * initial changes for dynamic opn enhancements Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * rename variables Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * resolve lint errors Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * refactor code Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * add changes for exclude operations Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * add conformance tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * add unit tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * corrections in conformance tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * modification in unit tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * correction in conformance tests Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * Update .vscode/launch.json Signed-off-by: shuting <shuting@nirmata.com> * update variable usage Signed-off-by: anushkamittal2001 <anushka@nirmata.com> * remove testresults Signed-off-by: anushkamittal2001 <anushka@nirmata.com> --------- Signed-off-by: anushkamittal2001 <anushka@nirmata.com> Signed-off-by: shuting <shuting@nirmata.com> Co-authored-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com> Co-authored-by: shuting <shuting@nirmata.com> Co-authored-by: Jim Bugwadia <jim@nirmata.com> Co-authored-by: Vishal Choudhary <vishal.choudhary@nirmata.com> Co-authored-by: shuting <shutting06@gmail.com>
364 lines
10 KiB
Go
364 lines
10 KiB
Go
package webhook
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"sort"
|
|
"testing"
|
|
|
|
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
|
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
|
"github.com/kyverno/kyverno/pkg/autogen"
|
|
"gotest.tools/assert"
|
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
)
|
|
|
|
func Test_webhook_isEmpty(t *testing.T) {
|
|
empty := newWebhook(DefaultWebhookTimeout, admissionregistrationv1.Ignore, []admissionregistrationv1.MatchCondition{})
|
|
assert.Equal(t, empty.isEmpty(), true)
|
|
notEmpty := newWebhook(DefaultWebhookTimeout, admissionregistrationv1.Ignore, []admissionregistrationv1.MatchCondition{})
|
|
notEmpty.set(GroupVersionResourceScope{
|
|
GroupVersionResource: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"},
|
|
Scope: admissionregistrationv1.NamespacedScope,
|
|
})
|
|
assert.Equal(t, notEmpty.isEmpty(), false)
|
|
}
|
|
|
|
var policy = `
|
|
{
|
|
"apiVersion": "kyverno.io/v1",
|
|
"kind": "ClusterPolicy",
|
|
"metadata": {
|
|
"name": "disallow-unsigned-images"
|
|
},
|
|
"spec": {
|
|
"validationFailureAction": "enforce",
|
|
"background": false,
|
|
"rules": [
|
|
{
|
|
"name": "replace-image-registry",
|
|
"match": {
|
|
"any": [
|
|
{
|
|
"resources": {
|
|
"kinds": [
|
|
"Pod"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"mutate": {
|
|
"foreach": [
|
|
{
|
|
"list": "request.object.spec.containers",
|
|
"patchStrategicMerge": {
|
|
"spec": {
|
|
"containers": [
|
|
{
|
|
"name": "{{ element.name }}",
|
|
"image": "{{ regex_replace_all_literal('.*(.*)/', '{{element.image}}', 'pratikrshah/' )}}"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "disallow-unsigned-images-rule",
|
|
"match": {
|
|
"any": [
|
|
{
|
|
"resources": {
|
|
"kinds": [
|
|
"Pod"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"verifyImages": [
|
|
{
|
|
"imageReferences": [
|
|
"*"
|
|
],
|
|
"verifyDigest": false,
|
|
"required": null,
|
|
"mutateDigest": false,
|
|
"attestors": [
|
|
{
|
|
"count": 1,
|
|
"entries": [
|
|
{
|
|
"keys": {
|
|
"publicKeys": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHsra9WSDxt9qv84KF4McNVCGjMFq\ne96mWCQxGimL9Ltj6F3iXmlo8sUalKfJ7SBXpy8hwyBfXBBAmCalsp5xEw==\n-----END PUBLIC KEY-----"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "check-image",
|
|
"match": {
|
|
"any": [
|
|
{
|
|
"resources": {
|
|
"kinds": [
|
|
"Pod"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"context": [
|
|
{
|
|
"name": "keys",
|
|
"configMap": {
|
|
"name": "keys",
|
|
"namespace": "default"
|
|
}
|
|
}
|
|
],
|
|
"verifyImages": [
|
|
{
|
|
"imageReferences": [
|
|
"ghcr.io/myorg/myimage*"
|
|
],
|
|
"required": true,
|
|
"attestors": [
|
|
{
|
|
"count": 1,
|
|
"entries": [
|
|
{
|
|
"keys": {
|
|
"publicKeys": "{{ keys.data.production }}"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`
|
|
|
|
func Test_RuleCount(t *testing.T) {
|
|
var cpol kyverno.ClusterPolicy
|
|
err := json.Unmarshal([]byte(policy), &cpol)
|
|
assert.NilError(t, err)
|
|
status := cpol.GetStatus()
|
|
rules := autogen.ComputeRules(&cpol)
|
|
setRuleCount(rules, status)
|
|
assert.Equal(t, status.RuleCount.Validate, 0)
|
|
assert.Equal(t, status.RuleCount.Generate, 0)
|
|
assert.Equal(t, status.RuleCount.Mutate, 1)
|
|
assert.Equal(t, status.RuleCount.VerifyImages, 2)
|
|
}
|
|
|
|
func TestGetMinimumOperations(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
inputMap map[string]bool
|
|
expectedResult []admissionregistrationv1.OperationType
|
|
}{
|
|
{
|
|
name: "Test Case 1",
|
|
inputMap: map[string]bool{
|
|
webhookCreate: true,
|
|
webhookUpdate: false,
|
|
webhookDelete: true,
|
|
},
|
|
expectedResult: []admissionregistrationv1.OperationType{webhookCreate, webhookDelete},
|
|
},
|
|
{
|
|
name: "Test Case 2",
|
|
inputMap: map[string]bool{
|
|
webhookCreate: false,
|
|
webhookUpdate: false,
|
|
webhookDelete: false,
|
|
webhookConnect: true,
|
|
},
|
|
expectedResult: []admissionregistrationv1.OperationType{webhookConnect},
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
result := getMinimumOperations(testCase.inputMap)
|
|
sort.Slice(result, func(i, j int) bool {
|
|
return result[i] < result[j]
|
|
})
|
|
sort.Slice(testCase.expectedResult, func(i, j int) bool {
|
|
return testCase.expectedResult[i] < testCase.expectedResult[j]
|
|
})
|
|
|
|
if !reflect.DeepEqual(result, testCase.expectedResult) {
|
|
t.Errorf("Expected %v, but got %v", testCase.expectedResult, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestComputeOperationsForMutatingWebhookConf(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
rules []kyverno.Rule
|
|
expectedResult map[string]bool
|
|
}{
|
|
{
|
|
name: "Test Case 1",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
Mutation: kyverno.Mutation{
|
|
PatchesJSON6902: "add",
|
|
},
|
|
MatchResources: kyverno.MatchResources{
|
|
ResourceDescription: kyverno.ResourceDescription{
|
|
Operations: []v1.AdmissionOperation{webhookCreate},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Test Case 2",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
Mutation: kyverno.Mutation{
|
|
PatchesJSON6902: "add",
|
|
},
|
|
MatchResources: kyverno.MatchResources{},
|
|
ExcludeResources: kyverno.MatchResources{},
|
|
},
|
|
{
|
|
Mutation: kyverno.Mutation{
|
|
PatchesJSON6902: "add",
|
|
},
|
|
MatchResources: kyverno.MatchResources{},
|
|
ExcludeResources: kyverno.MatchResources{},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: true,
|
|
webhookUpdate: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Test Case 2",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
Mutation: kyverno.Mutation{
|
|
PatchesJSON6902: "add",
|
|
},
|
|
MatchResources: kyverno.MatchResources{},
|
|
ExcludeResources: kyverno.MatchResources{
|
|
ResourceDescription: kyverno.ResourceDescription{
|
|
Operations: []v1.AdmissionOperation{webhookCreate},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: false,
|
|
webhookUpdate: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
var result map[string]bool
|
|
for _, r := range testCase.rules {
|
|
result = computeOperationsForMutatingWebhookConf(r, make(map[string]bool))
|
|
}
|
|
if !reflect.DeepEqual(result, testCase.expectedResult) {
|
|
t.Errorf("Expected %v, but got %v", testCase.expectedResult, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestComputeOperationsForValidatingWebhookConf(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
rules []kyverno.Rule
|
|
expectedResult map[string]bool
|
|
}{
|
|
{
|
|
name: "Test Case 1",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
MatchResources: kyverno.MatchResources{
|
|
ResourceDescription: kyverno.ResourceDescription{
|
|
Operations: []v1.AdmissionOperation{webhookCreate},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Test Case 2",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
MatchResources: kyverno.MatchResources{},
|
|
ExcludeResources: kyverno.MatchResources{},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: true,
|
|
webhookUpdate: true,
|
|
webhookConnect: true,
|
|
webhookDelete: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Test Case 3",
|
|
rules: []kyverno.Rule{
|
|
{
|
|
MatchResources: kyverno.MatchResources{
|
|
ResourceDescription: kyverno.ResourceDescription{
|
|
Operations: []v1.AdmissionOperation{webhookCreate, webhookUpdate},
|
|
},
|
|
},
|
|
ExcludeResources: kyverno.MatchResources{
|
|
ResourceDescription: kyverno.ResourceDescription{
|
|
Operations: []v1.AdmissionOperation{webhookDelete},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedResult: map[string]bool{
|
|
webhookCreate: true,
|
|
webhookUpdate: true,
|
|
webhookDelete: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
t.Run(testCase.name, func(t *testing.T) {
|
|
var result map[string]bool
|
|
for _, r := range testCase.rules {
|
|
result = computeOperationsForValidatingWebhookConf(r, make(map[string]bool))
|
|
}
|
|
if !reflect.DeepEqual(result, testCase.expectedResult) {
|
|
t.Errorf("Expected %v, but got %v", testCase.expectedResult, result)
|
|
}
|
|
})
|
|
}
|
|
}
|