1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00

feat: add match conditions support in webhooks (#8042)

* feat: add match conditions support in webhooks

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* chart

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* release notes

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* changelog

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix configmap

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* warning

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: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-08-18 10:32:15 +02:00 committed by GitHub
parent 57a0f81040
commit a3403131d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 54 additions and 0 deletions

View file

@ -4,6 +4,7 @@
### Note ### Note
- Added match conditions support in kyverno config map.
- Deprecated flag `--imageSignatureRepository`. Will be removed in 1.12. Use per rule configuration `verifyImages.Repository` instead. - Deprecated flag `--imageSignatureRepository`. Will be removed in 1.12. Use per rule configuration `verifyImages.Repository` instead.
- Added `--aggregateReports` flag for reports controller to enable/disable aggregated reports (default value is `true`). - Added `--aggregateReports` flag for reports controller to enable/disable aggregated reports (default value is `true`).
- Added `--policyReports` flag for reports controller to enable/disable policy reports (default value is `true`). - Added `--policyReports` flag for reports controller to enable/disable policy reports (default value is `true`).

View file

@ -64,3 +64,5 @@ annotations:
description: Add helper to handle the labels for cleanup jobs, add component label description: Add helper to handle the labels for cleanup jobs, add component label
- kind: added - kind: added
description: allow podSecurityContext and securityContext for webhooksCleanup description: allow podSecurityContext and securityContext for webhooksCleanup
- kind: added
description: match conditions support in webhooks

View file

@ -272,6 +272,7 @@ The chart values are organised per component.
| config.resourceFilters | list | See [values.yaml](values.yaml) | Resource types to be skipped by the Kyverno policy engine. Make sure to surround each entry in quotes so that it doesn't get parsed as a nested YAML list. These are joined together without spaces, run through `tpl`, and the result is set in the config map. | | config.resourceFilters | list | See [values.yaml](values.yaml) | Resource types to be skipped by the Kyverno policy engine. Make sure to surround each entry in quotes so that it doesn't get parsed as a nested YAML list. These are joined together without spaces, run through `tpl`, and the result is set in the config map. |
| config.webhooks | list | `[]` | Defines the `namespaceSelector` in the webhook configurations. Note that it takes a list of `namespaceSelector` and/or `objectSelector` in the JSON format, and only the first element will be forwarded to the webhook configurations. The Kyverno namespace is excluded if `excludeKyvernoNamespace` is `true` (default) | | config.webhooks | list | `[]` | Defines the `namespaceSelector` in the webhook configurations. Note that it takes a list of `namespaceSelector` and/or `objectSelector` in the JSON format, and only the first element will be forwarded to the webhook configurations. The Kyverno namespace is excluded if `excludeKyvernoNamespace` is `true` (default) |
| config.webhookAnnotations | object | `{}` | Defines annotations to set on webhook configurations. | | config.webhookAnnotations | object | `{}` | Defines annotations to set on webhook configurations. |
| config.matchConditions | list | `[]` | Defines match conditions to set on webhook configurations (requires Kubernetes 1.27+). |
| config.excludeKyvernoNamespace | bool | `true` | Exclude Kyverno namespace Determines if default Kyverno namespace exclusion is enabled for webhooks and resourceFilters | | config.excludeKyvernoNamespace | bool | `true` | Exclude Kyverno namespace Determines if default Kyverno namespace exclusion is enabled for webhooks and resourceFilters |
| config.resourceFiltersExcludeNamespaces | list | `[]` | resourceFilter namespace exclude Namespaces to exclude from the default resourceFilters | | config.resourceFiltersExcludeNamespaces | list | `[]` | resourceFilter namespace exclude Namespaces to exclude from the default resourceFilters |

View file

@ -32,3 +32,7 @@ The following components have been installed in your cluster:
{{- if semverCompare "<1.21.0" .Capabilities.KubeVersion.Version }} {{- if semverCompare "<1.21.0" .Capabilities.KubeVersion.Version }}
⚠️ WARNING: The minimal Kubernetes version officially supported by Kyverno is 1.21. Earlier versions are untested and Kyverno is not guaranteed to work with Kubernetes {{ .Capabilities.KubeVersion.Version }}. ⚠️ WARNING: The minimal Kubernetes version officially supported by Kyverno is 1.21. Earlier versions are untested and Kyverno is not guaranteed to work with Kubernetes {{ .Capabilities.KubeVersion.Version }}.
{{- end }} {{- end }}
{{- with .Values.config.matchConditions }}
⚠️ WARNING: Match conditions require a Kubernetes 1.27+ cluster with `AdmissionWebhookMatchConditions` feature gate enabled.
{{- end }}

View file

@ -42,4 +42,7 @@ data:
{{- with .Values.config.webhookAnnotations }} {{- with .Values.config.webhookAnnotations }}
webhookAnnotations: {{ toJson . | quote }} webhookAnnotations: {{ toJson . | quote }}
{{- end }} {{- end }}
{{- with .Values.config.matchConditions }}
matchConditions: {{ toJson . | quote }}
{{- end }}
{{- end -}} {{- end -}}

View file

@ -210,6 +210,9 @@ config:
# Example to disable admission enforcer on AKS: # Example to disable admission enforcer on AKS:
# 'admissions.enforcer/disabled': 'true' # 'admissions.enforcer/disabled': 'true'
# -- Defines match conditions to set on webhook configurations (requires Kubernetes 1.27+).
matchConditions: []
# -- Exclude Kyverno namespace # -- Exclude Kyverno namespace
# Determines if default Kyverno namespace exclusion is enabled for webhooks and resourceFilters # Determines if default Kyverno namespace exclusion is enabled for webhooks and resourceFilters
excludeKyvernoNamespace: true excludeKyvernoNamespace: true

View file

@ -9,6 +9,7 @@ import (
valid "github.com/asaskevich/govalidator" valid "github.com/asaskevich/govalidator"
osutils "github.com/kyverno/kyverno/pkg/utils/os" osutils "github.com/kyverno/kyverno/pkg/utils/os"
"github.com/kyverno/kyverno/pkg/utils/wildcard" "github.com/kyverno/kyverno/pkg/utils/wildcard"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -87,6 +88,7 @@ const (
generateSuccessEvents = "generateSuccessEvents" generateSuccessEvents = "generateSuccessEvents"
webhooks = "webhooks" webhooks = "webhooks"
webhookAnnotations = "webhookAnnotations" webhookAnnotations = "webhookAnnotations"
matchConditions = "matchConditions"
) )
var ( var (
@ -160,6 +162,8 @@ type Configuration interface {
GetWebhooks() []WebhookConfig GetWebhooks() []WebhookConfig
// GetWebhookAnnotations returns annotations to set on webhook configs // GetWebhookAnnotations returns annotations to set on webhook configs
GetWebhookAnnotations() map[string]string GetWebhookAnnotations() map[string]string
// GetMatchConditions returns match conditions to set on webhook configs
GetMatchConditions() []admissionregistrationv1.MatchCondition
// Load loads configuration from a configmap // Load loads configuration from a configmap
Load(*corev1.ConfigMap) Load(*corev1.ConfigMap)
// OnChanged adds a callback to be invoked when the configuration is reloaded // OnChanged adds a callback to be invoked when the configuration is reloaded
@ -177,6 +181,7 @@ type configuration struct {
generateSuccessEvents bool generateSuccessEvents bool
webhooks []WebhookConfig webhooks []WebhookConfig
webhookAnnotations map[string]string webhookAnnotations map[string]string
matchConditions []admissionregistrationv1.MatchCondition
mux sync.RWMutex mux sync.RWMutex
callbacks []func() callbacks []func()
} }
@ -295,6 +300,12 @@ func (cd *configuration) GetWebhookAnnotations() map[string]string {
return cd.webhookAnnotations return cd.webhookAnnotations
} }
func (cd *configuration) GetMatchConditions() []admissionregistrationv1.MatchCondition {
cd.mux.RLock()
defer cd.mux.RUnlock()
return cd.matchConditions
}
func (cd *configuration) Load(cm *corev1.ConfigMap) { func (cd *configuration) Load(cm *corev1.ConfigMap) {
if cm != nil { if cm != nil {
cd.load(cm) cd.load(cm)
@ -321,6 +332,7 @@ func (cd *configuration) load(cm *corev1.ConfigMap) {
cd.generateSuccessEvents = false cd.generateSuccessEvents = false
cd.webhooks = nil cd.webhooks = nil
cd.webhookAnnotations = nil cd.webhookAnnotations = nil
cd.matchConditions = nil
// load filters // load filters
cd.filters = parseKinds(data[resourceFilters]) cd.filters = parseKinds(data[resourceFilters])
logger.Info("filters configured", "filters", cd.filters) logger.Info("filters configured", "filters", cd.filters)
@ -425,6 +437,20 @@ func (cd *configuration) load(cm *corev1.ConfigMap) {
logger.Info("webhookAnnotations configured") logger.Info("webhookAnnotations configured")
} }
} }
// load match conditions
matchConditions, ok := data[matchConditions]
if !ok {
logger.Info("matchConditions not set")
} else {
logger := logger.WithValues("matchConditions", matchConditions)
matchConditions, err := parseMatchConditions(matchConditions)
if err != nil {
logger.Error(err, "failed to parse match conditions")
} else {
cd.matchConditions = matchConditions
logger.Info("matchConditions configured")
}
}
} }
func (cd *configuration) unload() { func (cd *configuration) unload() {

View file

@ -6,6 +6,7 @@ import (
"strings" "strings"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -52,6 +53,14 @@ func parseWebhookAnnotations(in string) (map[string]string, error) {
return out, nil return out, nil
} }
func parseMatchConditions(in string) ([]admissionregistrationv1.MatchCondition, error) {
var out []admissionregistrationv1.MatchCondition
if err := json.Unmarshal([]byte(in), &out); err != nil {
return nil, err
}
return out, nil
}
type namespacesConfig struct { type namespacesConfig struct {
IncludeNamespaces []string `json:"include,omitempty"` IncludeNamespaces []string `json:"include,omitempty"`
ExcludeNamespaces []string `json:"exclude,omitempty"` ExcludeNamespaces []string `json:"exclude,omitempty"`

View file

@ -178,6 +178,7 @@ func (c *controller) build(cfg config.Configuration, caBundle []byte) (*admissio
SideEffects: c.sideEffects, SideEffects: c.sideEffects,
AdmissionReviewVersions: []string{"v1"}, AdmissionReviewVersions: []string{"v1"},
ObjectSelector: c.labelSelector, ObjectSelector: c.labelSelector,
MatchConditions: cfg.GetMatchConditions(),
}}, }},
}, },
nil nil

View file

@ -659,6 +659,7 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Conte
ObjectSelector: webhookCfg.ObjectSelector, ObjectSelector: webhookCfg.ObjectSelector,
TimeoutSeconds: &timeout, TimeoutSeconds: &timeout,
ReinvocationPolicy: &ifNeeded, ReinvocationPolicy: &ifNeeded,
MatchConditions: cfg.GetMatchConditions(),
}, },
) )
} }
@ -677,6 +678,7 @@ func (c *controller) buildResourceMutatingWebhookConfiguration(ctx context.Conte
ObjectSelector: webhookCfg.ObjectSelector, ObjectSelector: webhookCfg.ObjectSelector,
TimeoutSeconds: &timeout, TimeoutSeconds: &timeout,
ReinvocationPolicy: &ifNeeded, ReinvocationPolicy: &ifNeeded,
MatchConditions: cfg.GetMatchConditions(),
}, },
) )
} }
@ -786,6 +788,7 @@ func (c *controller) buildResourceValidatingWebhookConfiguration(ctx context.Con
NamespaceSelector: webhookCfg.NamespaceSelector, NamespaceSelector: webhookCfg.NamespaceSelector,
ObjectSelector: webhookCfg.ObjectSelector, ObjectSelector: webhookCfg.ObjectSelector,
TimeoutSeconds: &timeout, TimeoutSeconds: &timeout,
MatchConditions: cfg.GetMatchConditions(),
}, },
) )
} }
@ -803,6 +806,7 @@ func (c *controller) buildResourceValidatingWebhookConfiguration(ctx context.Con
NamespaceSelector: webhookCfg.NamespaceSelector, NamespaceSelector: webhookCfg.NamespaceSelector,
ObjectSelector: webhookCfg.ObjectSelector, ObjectSelector: webhookCfg.ObjectSelector,
TimeoutSeconds: &timeout, TimeoutSeconds: &timeout,
MatchConditions: cfg.GetMatchConditions(),
}, },
) )
} }