2022-10-12 08:52:42 +02:00
|
|
|
package webhook
|
|
|
|
|
|
|
|
import (
|
2022-10-27 15:35:32 +05:30
|
|
|
"strings"
|
|
|
|
|
2022-10-12 08:52:42 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2022-11-07 17:05:56 +01:00
|
|
|
"golang.org/x/exp/slices"
|
2022-10-12 08:52:42 +02:00
|
|
|
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2022-11-07 17:05:56 +01:00
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
2022-10-12 08:52:42 +02:00
|
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
|
|
)
|
|
|
|
|
|
|
|
// webhook is the instance that aggregates the GVK of existing policies
|
|
|
|
// based on kind, failurePolicy and webhookTimeout
|
|
|
|
type webhook struct {
|
|
|
|
maxWebhookTimeout int32
|
|
|
|
failurePolicy admissionregistrationv1.FailurePolicyType
|
2022-11-07 17:05:56 +01:00
|
|
|
rules map[schema.GroupVersionResource]struct{}
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func newWebhook(timeout int32, failurePolicy admissionregistrationv1.FailurePolicyType) *webhook {
|
|
|
|
return &webhook{
|
|
|
|
maxWebhookTimeout: timeout,
|
|
|
|
failurePolicy: failurePolicy,
|
2022-11-07 17:05:56 +01:00
|
|
|
rules: map[schema.GroupVersionResource]struct{}{},
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-07 17:05:56 +01:00
|
|
|
func (wh *webhook) buildRulesWithOperations(ops ...admissionregistrationv1.OperationType) []admissionregistrationv1.RuleWithOperations {
|
|
|
|
var rules []admissionregistrationv1.RuleWithOperations
|
|
|
|
for gvr := range wh.rules {
|
2022-12-21 23:33:51 +01:00
|
|
|
resources := sets.New(gvr.Resource)
|
2023-01-06 19:10:35 +05:30
|
|
|
ephemeralContainersGVR := schema.GroupVersionResource{Resource: "pods/ephemeralcontainers", Group: "", Version: "v1"}
|
|
|
|
_, rulesContainEphemeralContainers := wh.rules[ephemeralContainersGVR]
|
|
|
|
if resources.Has("pods") && !rulesContainEphemeralContainers {
|
|
|
|
resources.Insert("pods/ephemeralcontainers")
|
|
|
|
}
|
2022-11-07 17:05:56 +01:00
|
|
|
rules = append(rules, admissionregistrationv1.RuleWithOperations{
|
|
|
|
Rule: admissionregistrationv1.Rule{
|
|
|
|
APIGroups: []string{gvr.Group},
|
|
|
|
APIVersions: []string{gvr.Version},
|
2022-12-21 23:33:51 +01:00
|
|
|
Resources: sets.List(resources),
|
2022-11-07 17:05:56 +01:00
|
|
|
},
|
|
|
|
Operations: ops,
|
|
|
|
})
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
2022-11-07 17:05:56 +01:00
|
|
|
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{}{}
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wh *webhook) isEmpty() bool {
|
2022-11-07 17:05:56 +01:00
|
|
|
return len(wh.rules) == 0
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (wh *webhook) setWildcard() {
|
2022-11-07 17:05:56 +01:00
|
|
|
wh.rules = map[schema.GroupVersionResource]struct{}{
|
|
|
|
{Group: "*", Version: "*", Resource: "*/*"}: {},
|
|
|
|
}
|
2022-10-12 08:52:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func hasWildcard(policies ...kyvernov1.PolicyInterface) bool {
|
|
|
|
for _, policy := range policies {
|
|
|
|
spec := policy.GetSpec()
|
|
|
|
for _, rule := range spec.Rules {
|
2022-11-29 09:04:49 +01:00
|
|
|
if kinds := rule.MatchResources.GetKinds(); slices.Contains(kinds, "*") {
|
2022-10-12 08:52:42 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func objectMeta(name string, owner ...metav1.OwnerReference) metav1.ObjectMeta {
|
|
|
|
return metav1.ObjectMeta{
|
|
|
|
Name: name,
|
|
|
|
Labels: map[string]string{
|
|
|
|
managedByLabel: kyvernov1.ValueKyvernoApp,
|
|
|
|
},
|
|
|
|
OwnerReferences: owner,
|
|
|
|
}
|
|
|
|
}
|
2022-10-27 15:35:32 +05:30
|
|
|
|
|
|
|
func setRuleCount(rules []kyvernov1.Rule, status *kyvernov1.PolicyStatus) {
|
|
|
|
validateCount, generateCount, mutateCount, verifyImagesCount := 0, 0, 0, 0
|
|
|
|
for _, rule := range rules {
|
|
|
|
if !strings.HasPrefix(rule.Name, "autogen-") {
|
|
|
|
if rule.HasGenerate() {
|
|
|
|
generateCount += 1
|
|
|
|
}
|
|
|
|
if rule.HasValidate() {
|
|
|
|
validateCount += 1
|
|
|
|
}
|
|
|
|
if rule.HasMutate() {
|
|
|
|
mutateCount += 1
|
|
|
|
}
|
|
|
|
if rule.HasVerifyImages() {
|
|
|
|
verifyImagesCount += 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
status.RuleCount.Validate = validateCount
|
|
|
|
status.RuleCount.Generate = generateCount
|
|
|
|
status.RuleCount.Mutate = mutateCount
|
|
|
|
status.RuleCount.VerifyImages = verifyImagesCount
|
|
|
|
}
|