2022-10-12 08:52:42 +02:00
|
|
|
package webhook
|
|
|
|
|
|
|
|
import (
|
2023-09-19 14:06:53 +02:00
|
|
|
"cmp"
|
2022-10-27 15:35:32 +05:30
|
|
|
"strings"
|
|
|
|
|
2023-07-06 10:00:36 +02:00
|
|
|
"github.com/kyverno/kyverno/api/kyverno"
|
2022-10-12 08:52:42 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2024-01-27 21:00:22 +08:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
2023-12-07 13:58:31 +01:00
|
|
|
"golang.org/x/exp/maps"
|
2022-10-12 08:52:42 +02:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
|
|
)
|
|
|
|
|
2024-10-21 14:56:21 +02:00
|
|
|
func collectResourceDescriptions(rule kyvernov1.Rule, defaultOps ...kyvernov1.AdmissionOperation) webhookConfig {
|
|
|
|
out := map[string]sets.Set[kyvernov1.AdmissionOperation]{}
|
|
|
|
for _, kind := range rule.MatchResources.ResourceDescription.Kinds {
|
|
|
|
if out[kind] == nil {
|
|
|
|
out[kind] = sets.New[kyvernov1.AdmissionOperation]()
|
2024-01-31 21:16:53 +05:30
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
ops := rule.MatchResources.ResourceDescription.Operations
|
|
|
|
if len(ops) == 0 {
|
|
|
|
ops = defaultOps
|
|
|
|
}
|
|
|
|
out[kind].Insert(ops...)
|
2024-01-31 21:16:53 +05:30
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
for _, value := range rule.MatchResources.All {
|
|
|
|
for _, kind := range value.Kinds {
|
|
|
|
if out[kind] == nil {
|
|
|
|
out[kind] = sets.New[kyvernov1.AdmissionOperation]()
|
2024-09-05 17:12:40 +05:30
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
ops := value.Operations
|
|
|
|
if len(ops) == 0 {
|
|
|
|
ops = defaultOps
|
2024-09-05 17:12:40 +05:30
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
out[kind].Insert(ops...)
|
2024-09-05 17:12:40 +05:30
|
|
|
}
|
2024-09-25 14:12:08 +02:00
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
for _, value := range rule.MatchResources.Any {
|
|
|
|
for _, kind := range value.Kinds {
|
|
|
|
if out[kind] == nil {
|
|
|
|
out[kind] = sets.New[kyvernov1.AdmissionOperation]()
|
2022-11-07 17:05:56 +01:00
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
ops := value.Operations
|
|
|
|
if len(ops) == 0 {
|
|
|
|
ops = defaultOps
|
2024-01-31 21:16:53 +05:30
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
out[kind].Insert(ops...)
|
2024-01-31 21:16:53 +05:30
|
|
|
}
|
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
// we consider only `exclude.any` elements and only if `kinds` is empty or if there's a corresponding kind in the match statement
|
|
|
|
// nothing else than `kinds` and `operations` must be set
|
|
|
|
if rule.ExcludeResources != nil {
|
|
|
|
for _, value := range rule.ExcludeResources.Any {
|
|
|
|
if !value.UserInfo.IsEmpty() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if value.Name != "" ||
|
|
|
|
len(value.Names) != 0 ||
|
|
|
|
len(value.Namespaces) != 0 ||
|
|
|
|
len(value.Annotations) != 0 ||
|
|
|
|
value.Selector != nil ||
|
|
|
|
value.NamespaceSelector != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
kinds := value.Kinds
|
|
|
|
if len(kinds) == 0 {
|
|
|
|
kinds = maps.Keys(out)
|
|
|
|
}
|
|
|
|
ops := value.Operations
|
|
|
|
if len(ops) == 0 {
|
|
|
|
// if only kind was specified, clear all operations
|
|
|
|
ops = allOperations
|
|
|
|
}
|
|
|
|
for _, kind := range kinds {
|
|
|
|
if out[kind] != nil {
|
|
|
|
out[kind] = out[kind].Delete(ops...)
|
|
|
|
}
|
2024-01-31 21:16:53 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
return out
|
2024-01-27 21:00:22 +08:00
|
|
|
}
|
|
|
|
|
2023-12-07 13:58:31 +01:00
|
|
|
func objectMeta(name string, annotations map[string]string, labels map[string]string, owner ...metav1.OwnerReference) metav1.ObjectMeta {
|
|
|
|
desiredLabels := make(map[string]string)
|
|
|
|
defaultLabels := map[string]string{
|
|
|
|
kyverno.LabelWebhookManagedBy: kyverno.ValueKyvernoApp,
|
|
|
|
}
|
|
|
|
maps.Copy(desiredLabels, labels)
|
|
|
|
maps.Copy(desiredLabels, defaultLabels)
|
2022-10-12 08:52:42 +02:00
|
|
|
return metav1.ObjectMeta{
|
2023-12-07 13:58:31 +01:00
|
|
|
Name: name,
|
|
|
|
Labels: desiredLabels,
|
2023-03-15 14:17:37 +01:00
|
|
|
Annotations: annotations,
|
2022-10-12 08:52:42 +02:00
|
|
|
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
|
|
|
|
}
|
2023-03-29 09:02:52 +02:00
|
|
|
|
|
|
|
func capTimeout(maxWebhookTimeout int32) int32 {
|
|
|
|
if maxWebhookTimeout > 30 {
|
|
|
|
return 30
|
|
|
|
}
|
|
|
|
return maxWebhookTimeout
|
|
|
|
}
|
2024-01-27 21:00:22 +08:00
|
|
|
|
|
|
|
func webhookNameAndPath(wh webhook, baseName, basePath string) (name string, path string) {
|
|
|
|
if wh.failurePolicy == ignore {
|
|
|
|
name = baseName + "-ignore"
|
|
|
|
path = basePath + "/ignore"
|
|
|
|
} else {
|
|
|
|
name = baseName + "-fail"
|
|
|
|
path = basePath + "/fail"
|
|
|
|
}
|
|
|
|
if wh.policyMeta.Name != "" {
|
|
|
|
name = name + "-finegrained-" + wh.key("-")
|
|
|
|
path = path + config.FineGrainedWebhookPath + "/" + wh.key("/")
|
|
|
|
}
|
|
|
|
return name, path
|
|
|
|
}
|
2024-10-21 14:56:21 +02:00
|
|
|
|
|
|
|
func less[T cmp.Ordered](a []T, b []T) int {
|
|
|
|
if x := cmp.Compare(len(a), len(b)); x != 0 {
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
for i := range a {
|
|
|
|
if x := cmp.Compare(a[i], b[i]); x != 0 {
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|