mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 10:28:36 +00:00
feat: separate webhook rules per GVK/rule (#4986)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
2d475c1b85
commit
e4c493093e
2 changed files with 67 additions and 52 deletions
|
@ -646,11 +646,9 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(caBundle []byte)
|
|||
result.Webhooks = append(
|
||||
result.Webhooks,
|
||||
admissionregistrationv1.MutatingWebhook{
|
||||
Name: config.MutatingWebhookName + "-ignore",
|
||||
ClientConfig: c.clientConfig(caBundle, config.MutatingWebhookServicePath+"/ignore"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
ignore.buildRuleWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update),
|
||||
},
|
||||
Name: config.MutatingWebhookName + "-ignore",
|
||||
ClientConfig: c.clientConfig(caBundle, config.MutatingWebhookServicePath+"/ignore"),
|
||||
Rules: ignore.buildRulesWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update),
|
||||
FailurePolicy: &ignore.failurePolicy,
|
||||
SideEffects: &noneOnDryRun,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
|
@ -665,11 +663,9 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(caBundle []byte)
|
|||
result.Webhooks = append(
|
||||
result.Webhooks,
|
||||
admissionregistrationv1.MutatingWebhook{
|
||||
Name: config.MutatingWebhookName + "-fail",
|
||||
ClientConfig: c.clientConfig(caBundle, config.MutatingWebhookServicePath+"/fail"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
fail.buildRuleWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update),
|
||||
},
|
||||
Name: config.MutatingWebhookName + "-fail",
|
||||
ClientConfig: c.clientConfig(caBundle, config.MutatingWebhookServicePath+"/fail"),
|
||||
Rules: fail.buildRulesWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update),
|
||||
FailurePolicy: &fail.failurePolicy,
|
||||
SideEffects: &noneOnDryRun,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
|
@ -761,11 +757,9 @@ func (c *controller) buildResourceValidatingWebhookConfiguration(caBundle []byte
|
|||
result.Webhooks = append(
|
||||
result.Webhooks,
|
||||
admissionregistrationv1.ValidatingWebhook{
|
||||
Name: config.ValidatingWebhookName + "-ignore",
|
||||
ClientConfig: c.clientConfig(caBundle, config.ValidatingWebhookServicePath+"/ignore"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
ignore.buildRuleWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete, admissionregistrationv1.Connect),
|
||||
},
|
||||
Name: config.ValidatingWebhookName + "-ignore",
|
||||
ClientConfig: c.clientConfig(caBundle, config.ValidatingWebhookServicePath+"/ignore"),
|
||||
Rules: ignore.buildRulesWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete, admissionregistrationv1.Connect),
|
||||
FailurePolicy: &ignore.failurePolicy,
|
||||
SideEffects: sideEffects,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
|
@ -779,11 +773,9 @@ func (c *controller) buildResourceValidatingWebhookConfiguration(caBundle []byte
|
|||
result.Webhooks = append(
|
||||
result.Webhooks,
|
||||
admissionregistrationv1.ValidatingWebhook{
|
||||
Name: config.ValidatingWebhookName + "-fail",
|
||||
ClientConfig: c.clientConfig(caBundle, config.ValidatingWebhookServicePath+"/fail"),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{
|
||||
fail.buildRuleWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete, admissionregistrationv1.Connect),
|
||||
},
|
||||
Name: config.ValidatingWebhookName + "-fail",
|
||||
ClientConfig: c.clientConfig(caBundle, config.ValidatingWebhookServicePath+"/fail"),
|
||||
Rules: fail.buildRulesWithOperations(admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete, admissionregistrationv1.Connect),
|
||||
FailurePolicy: &fail.failurePolicy,
|
||||
SideEffects: sideEffects,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
|
@ -878,20 +870,7 @@ func (c *controller) mergeWebhook(dst *webhook, policy kyvernov1.PolicyInterface
|
|||
}
|
||||
}
|
||||
for _, gvr := range gvrList {
|
||||
dst.groups.Insert(gvr.Group)
|
||||
if gvr.Version == "*" {
|
||||
dst.versions = sets.NewString()
|
||||
dst.versions.Insert(gvr.Version)
|
||||
} else if !dst.versions.Has("*") {
|
||||
dst.versions.Insert(gvr.Version)
|
||||
}
|
||||
dst.resources.Insert(gvr.Resource)
|
||||
}
|
||||
if dst.resources.Has("pods") {
|
||||
dst.resources.Insert("pods/ephemeralcontainers")
|
||||
}
|
||||
if dst.resources.Has("services") {
|
||||
dst.resources.Insert("services/status")
|
||||
dst.set(gvr)
|
||||
}
|
||||
spec := policy.GetSpec()
|
||||
if spec.WebhookTimeoutSeconds != nil {
|
||||
|
|
|
@ -5,8 +5,10 @@ import (
|
|||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"golang.org/x/exp/slices"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
|
@ -15,40 +17,74 @@ import (
|
|||
type webhook struct {
|
||||
maxWebhookTimeout int32
|
||||
failurePolicy admissionregistrationv1.FailurePolicyType
|
||||
groups sets.String
|
||||
versions sets.String
|
||||
resources sets.String
|
||||
rules map[schema.GroupVersionResource]struct{}
|
||||
}
|
||||
|
||||
func newWebhook(timeout int32, failurePolicy admissionregistrationv1.FailurePolicyType) *webhook {
|
||||
return &webhook{
|
||||
maxWebhookTimeout: timeout,
|
||||
failurePolicy: failurePolicy,
|
||||
groups: sets.NewString(),
|
||||
versions: sets.NewString(),
|
||||
resources: sets.NewString(),
|
||||
rules: map[schema.GroupVersionResource]struct{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func (wh *webhook) buildRuleWithOperations(ops ...admissionregistrationv1.OperationType) admissionregistrationv1.RuleWithOperations {
|
||||
return admissionregistrationv1.RuleWithOperations{
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: wh.groups.List(),
|
||||
APIVersions: wh.versions.List(),
|
||||
Resources: wh.resources.List(),
|
||||
},
|
||||
Operations: ops,
|
||||
func (wh *webhook) buildRulesWithOperations(ops ...admissionregistrationv1.OperationType) []admissionregistrationv1.RuleWithOperations {
|
||||
var rules []admissionregistrationv1.RuleWithOperations
|
||||
for gvr := range wh.rules {
|
||||
resources := sets.NewString(gvr.Resource)
|
||||
if resources.Has("pods") {
|
||||
resources.Insert("pods/ephemeralcontainers")
|
||||
}
|
||||
if resources.Has("services") {
|
||||
resources.Insert("services/status")
|
||||
}
|
||||
rules = append(rules, admissionregistrationv1.RuleWithOperations{
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{gvr.Group},
|
||||
APIVersions: []string{gvr.Version},
|
||||
Resources: resources.List(),
|
||||
},
|
||||
Operations: ops,
|
||||
})
|
||||
}
|
||||
less := func(a []string, b []string) (bool, bool) {
|
||||
if len(a) != len(b) {
|
||||
return len(a) < len(b), true
|
||||
}
|
||||
for i := range a {
|
||||
if a[i] != b[i] {
|
||||
return a[i] < b[i], true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
slices.SortFunc(rules, func(a admissionregistrationv1.RuleWithOperations, b admissionregistrationv1.RuleWithOperations) bool {
|
||||
if less, match := less(a.APIGroups, b.APIGroups); match {
|
||||
return less
|
||||
}
|
||||
if less, match := less(a.APIVersions, b.APIVersions); match {
|
||||
return less
|
||||
}
|
||||
if less, match := less(a.Resources, b.Resources); match {
|
||||
return less
|
||||
}
|
||||
return false
|
||||
})
|
||||
return rules
|
||||
}
|
||||
|
||||
func (wh *webhook) set(gvr schema.GroupVersionResource) {
|
||||
wh.rules[gvr] = struct{}{}
|
||||
}
|
||||
|
||||
func (wh *webhook) isEmpty() bool {
|
||||
return wh.groups.Len() == 0 || wh.versions.Len() == 0 || wh.resources.Len() == 0
|
||||
return len(wh.rules) == 0
|
||||
}
|
||||
|
||||
func (wh *webhook) setWildcard() {
|
||||
wh.groups = sets.NewString("*")
|
||||
wh.versions = sets.NewString("*")
|
||||
wh.resources = sets.NewString("*/*")
|
||||
wh.rules = map[schema.GroupVersionResource]struct{}{
|
||||
{Group: "*", Version: "*", Resource: "*/*"}: {},
|
||||
}
|
||||
}
|
||||
|
||||
func hasWildcard(policies ...kyvernov1.PolicyInterface) bool {
|
||||
|
|
Loading…
Add table
Reference in a new issue