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:
parent
bc0f83b175
commit
37ab9ba824
5 changed files with 99 additions and 41 deletions
|
@ -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"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -20,3 +20,4 @@ webhooks:
|
||||||
- 'configmaps'
|
- 'configmaps'
|
||||||
- 'secrets'
|
- 'secrets'
|
||||||
scope: 'Namespaced'
|
scope: 'Namespaced'
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue