1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-26 01:24:26 +00:00
kyverno/pkg/controllers/webhook/utils.go
shuting 5c5a5fc0b0
feat: reconcile ivpol.status (#12392)
* feat: update ivpol.status api

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: fix unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update codegen

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: update codegen

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: reconcile ivpol.status

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: linter issues

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* fix: autogen fields replacement

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* chore: add unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: update ivpol autogen rules

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* feat: invoke ivpol webhook handler

Signed-off-by: ShutingZhao <shuting@nirmata.com>

---------

Signed-off-by: ShutingZhao <shuting@nirmata.com>
Signed-off-by: shuting <shuting@nirmata.com>
2025-03-15 05:29:19 +05:30

201 lines
5.2 KiB
Go

package webhook
import (
"cmp"
"fmt"
"strings"
"github.com/kyverno/kyverno/api/kyverno"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"golang.org/x/exp/maps"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
)
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]()
}
ops := rule.MatchResources.ResourceDescription.Operations
if len(ops) == 0 {
ops = defaultOps
}
out[kind].Insert(ops...)
}
for _, value := range rule.MatchResources.All {
for _, kind := range value.Kinds {
if out[kind] == nil {
out[kind] = sets.New[kyvernov1.AdmissionOperation]()
}
ops := value.Operations
if len(ops) == 0 {
ops = defaultOps
}
out[kind].Insert(ops...)
}
}
for _, value := range rule.MatchResources.Any {
for _, kind := range value.Kinds {
if out[kind] == nil {
out[kind] = sets.New[kyvernov1.AdmissionOperation]()
}
ops := value.Operations
if len(ops) == 0 {
ops = defaultOps
}
out[kind].Insert(ops...)
}
}
// 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...)
}
}
}
}
return out
}
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)
return metav1.ObjectMeta{
Name: name,
Labels: desiredLabels,
Annotations: annotations,
OwnerReferences: owner,
}
}
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
}
func capTimeout(maxWebhookTimeout int32) int32 {
if maxWebhookTimeout > 30 {
return 30
}
return maxWebhookTimeout
}
func newClientConfig(server string, servicePort int32, caBundle []byte, path string) admissionregistrationv1.WebhookClientConfig {
clientConfig := admissionregistrationv1.WebhookClientConfig{
CABundle: caBundle,
}
if server == "" {
clientConfig.Service = &admissionregistrationv1.ServiceReference{
Namespace: config.KyvernoNamespace(),
Name: config.KyvernoServiceName(),
Path: &path,
Port: &servicePort,
}
} else {
url := fmt.Sprintf("https://%s%s", server, path)
clientConfig.URL = &url
}
return clientConfig
}
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
}
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
}
const (
ValidatingPolicyType = "ValidatingPolicy"
ImageVerificationPolicy = "ImageVerificationPolicy"
)
// ParsePolicyKey builds policy key in kind/name format
func BuildPolicyKey(policyType, name string) string {
switch policyType {
case ValidatingPolicyType:
return ValidatingPolicyType + "/" + name
case ImageVerificationPolicy:
return ImageVerificationPolicy + "/" + name
}
return ""
}
// ParsePolicyKey parses policy key in kind/name format
func ParsePolicyKey(key string) (policyType, name string) {
vars := strings.Split(key, "/")
if len(vars) < 2 {
return "", ""
}
return vars[0], vars[1]
}