1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00

fix: range through all resources to build webhook (#10748)

* fix: range through all resources to build webhook

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* chore: add tests

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* chore: correct conformance

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* chore: correct conformance pod all subresources

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* fix: append resource when operations and scope is same

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* fix: correct tests

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* fix: chainsaw tests

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* fix: flaky test

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

* chore: remove debug lines

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>

---------

Signed-off-by: anushkamittal20 <anumittal4641@gmail.com>
Co-authored-by: anushkamittal20 <anumittal4641@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Anushka Mittal 2024-09-05 17:12:40 +05:30 committed by GitHub
parent bc0f83b175
commit 37ab9ba824
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 99 additions and 41 deletions

View file

@ -52,6 +52,42 @@ func TestAddOperationsForValidatingWebhookConfMultiplePolicies(t *testing.T) {
expectedResult: map[string][]admissionregistrationv1.OperationType{ expectedResult: map[string][]admissionregistrationv1.OperationType{
"ConfigMap": {"CREATE", "UPDATE", "DELETE", "CONNECT"}, "ConfigMap": {"CREATE", "UPDATE", "DELETE", "CONNECT"},
}, },
}, {
name: "test-2",
policies: []kyverno.ClusterPolicy{
{
Spec: kyverno.Spec{
Rules: []kyverno.Rule{
{
MatchResources: kyverno.MatchResources{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Role"},
Operations: []kyverno.AdmissionOperation{"DELETE"},
},
},
},
},
},
},
{
Spec: kyverno.Spec{
Rules: []kyverno.Rule{
{
MatchResources: kyverno.MatchResources{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Secrets"},
Operations: []kyverno.AdmissionOperation{"CONNECT"},
},
},
},
},
},
},
},
expectedResult: map[string][]admissionregistrationv1.OperationType{
"Role": {"DELETE"},
"Secrets": {"CONNECT"},
},
}, },
} }

View file

@ -2,6 +2,7 @@ package webhook
import ( import (
"cmp" "cmp"
"reflect"
"slices" "slices"
"strings" "strings"
@ -75,30 +76,37 @@ func (wh *webhook) buildRulesWithOperations(final map[string][]admissionregistra
rules := make([]admissionregistrationv1.RuleWithOperations, 0, len(wh.rules)) rules := make([]admissionregistrationv1.RuleWithOperations, 0, len(wh.rules))
for gv, resources := range wh.rules { for gv, resources := range wh.rules {
firstResource := sets.List(resources)[0] ruleforset := make([]admissionregistrationv1.RuleWithOperations, 0, len(resources))
// if we have pods, we add pods/ephemeralcontainers by default for res := range resources {
if (gv.Group == "" || gv.Group == "*") && (gv.Version == "v1" || gv.Version == "*") && (resources.Has("pods") || resources.Has("*")) { resource := sets.New(res)
resources.Insert("pods/ephemeralcontainers") // if we have pods, we add pods/ephemeralcontainers by default
if (gv.Group == "" || gv.Group == "*") && (gv.Version == "v1" || gv.Version == "*") && (resource.Has("pods") || resource.Has("*")) {
resource.Insert("pods/ephemeralcontainers")
}
operations := findKeyContainingSubstring(final, res, defaultOpn)
if len(operations) == 0 {
continue
}
slices.SortFunc(operations, func(a, b admissionregistrationv1.OperationType) int {
return cmp.Compare(a, b)
})
var added bool
ruleforset, added = appendResourceInRule(resource, operations, ruleforset)
if !added {
ruleforset = append(ruleforset, admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{gv.Group},
APIVersions: []string{gv.Version},
Resources: sets.List(resource),
Scope: ptr.To(gv.scopeType),
},
Operations: operations,
})
}
} }
rules = append(rules, ruleforset...)
operations := findKeyContainingSubstring(final, firstResource, defaultOpn)
if len(operations) == 0 {
continue
}
slices.SortFunc(operations, func(a, b admissionregistrationv1.OperationType) int {
return cmp.Compare(a, b)
})
rules = append(rules, admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{gv.Group},
APIVersions: []string{gv.Version},
Resources: sets.List(resources),
Scope: ptr.To(gv.scopeType),
},
Operations: operations,
})
} }
less := func(a []string, b []string) (int, bool) { less := func(a []string, b []string) (int, bool) {
if x := cmp.Compare(len(a), len(b)); x != 0 { if x := cmp.Compare(len(a), len(b)); x != 0 {
@ -129,6 +137,16 @@ func (wh *webhook) buildRulesWithOperations(final map[string][]admissionregistra
return rules return rules
} }
func appendResourceInRule(resource sets.Set[string], operations []admissionregistrationv1.OperationType, ruleforset []admissionregistrationv1.RuleWithOperations) ([]admissionregistrationv1.RuleWithOperations, bool) {
for i, rule := range ruleforset {
if reflect.DeepEqual(rule.Operations, operations) {
ruleforset[i].Rule.Resources = append(rule.Rule.Resources, resource.UnsortedList()...)
return ruleforset, true
}
}
return ruleforset, false
}
func scanResourceFilterForResources(resFilter kyvernov1.ResourceFilters) []string { func scanResourceFilterForResources(resFilter kyvernov1.ResourceFilters) []string {
var resources []string var resources []string
for _, rf := range resFilter { for _, rf := range resFilter {

View file

@ -374,12 +374,6 @@ func TestBuildRulesWithOperations(t *testing.T) {
{ {
name: "Test Case 1", name: "Test Case 1",
rules: map[groupVersionScope]sets.Set[string]{ rules: map[groupVersionScope]sets.Set[string]{
groupVersionScope{
GroupVersion: corev1.SchemeGroupVersion,
scopeType: admissionregistrationv1.AllScopes,
}: {
"namespaces": sets.Empty{},
},
groupVersionScope{ groupVersionScope{
GroupVersion: corev1.SchemeGroupVersion, GroupVersion: corev1.SchemeGroupVersion,
scopeType: admissionregistrationv1.NamespacedScope, scopeType: admissionregistrationv1.NamespacedScope,
@ -389,16 +383,24 @@ func TestBuildRulesWithOperations(t *testing.T) {
}, },
}, },
mapResourceToOpnType: map[string][]admissionregistrationv1.OperationType{ mapResourceToOpnType: map[string][]admissionregistrationv1.OperationType{
"Namespace": {}, "Pod": {webhookCreate, webhookUpdate},
"Pod": {webhookCreate, webhookUpdate}, "ConfigMaps": {webhookCreate},
}, },
expectedResult: []admissionregistrationv1.RuleWithOperations{ expectedResult: []admissionregistrationv1.RuleWithOperations{
{ {
Operations: []admissionregistrationv1.OperationType{webhookCreate},
Rule: admissionregistrationv1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"configmaps"},
Scope: ptr.To(admissionregistrationv1.NamespacedScope),
},
}, {
Operations: []admissionregistrationv1.OperationType{webhookCreate, webhookUpdate}, Operations: []admissionregistrationv1.OperationType{webhookCreate, webhookUpdate},
Rule: admissionregistrationv1.Rule{ Rule: admissionregistrationv1.Rule{
APIGroups: []string{""}, APIGroups: []string{""},
APIVersions: []string{"v1"}, APIVersions: []string{"v1"},
Resources: []string{"configmaps", "pods", "pods/ephemeralcontainers"}, Resources: []string{"pods", "pods/ephemeralcontainers"},
Scope: ptr.To(admissionregistrationv1.NamespacedScope), Scope: ptr.To(admissionregistrationv1.NamespacedScope),
}, },
}, },

View file

@ -16,13 +16,14 @@ webhooks:
- DELETE - DELETE
- UPDATE - UPDATE
resources: resources:
- pods/attach (contains(@,'pods/status')): true
- pods/binding (contains(@,'pods/log')): true
- pods/ephemeralcontainers (contains(@,'pods/attach')): true
- pods/eviction (contains(@,'pods/ephemeralcontainers')): true
- pods/exec (contains(@,'pods/eviction')): true
- pods/log (contains(@,'pods/exec')): true
- pods/portforward (contains(@,'pods/portforward')): true
- pods/proxy (contains(@,'pods/binding')): true
- pods/status (contains(@,'pods/proxy')): true
scope: 'Namespaced' scope: 'Namespaced'

View file

@ -20,3 +20,4 @@ webhooks:
- 'configmaps' - 'configmaps'
- 'secrets' - 'secrets'
scope: 'Namespaced' scope: 'Namespaced'