From 5ec66918f641647d0406b1cc4cb6a2980734cbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 5 Apr 2023 15:51:07 +0200 Subject: [PATCH] feat: add subresource support to resource filters (#6780) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add subresource support to resource filters Signed-off-by: Charles-Edouard Brétéché * filter Signed-off-by: Charles-Edouard Brétéché * values Signed-off-by: Charles-Edouard Brétéché --------- Signed-off-by: Charles-Edouard Brétéché --- charts/kyverno/templates/config/_helpers.tpl | 26 ++-- .../kyverno/templates/config/configmap.yaml | 3 +- charts/kyverno/values.yaml | 41 ++++++- config/install-latest-testing.yaml | 112 +++++++++++++++++- pkg/config/config.go | 29 ++++- pkg/config/types.go | 31 ++++- pkg/config/types_test.go | 48 +++++--- pkg/engine/background.go | 3 +- pkg/engine/internal/context.go | 18 --- pkg/engine/internal/match.go | 8 +- pkg/metrics/metrics.go | 4 +- pkg/tracing/config.go | 4 +- pkg/utils/{kube => tls}/cert.go | 2 +- pkg/webhooks/handlers/filter.go | 2 +- .../modify-resource-filters.sh | 3 +- .../modify-resource-filters.sh | 4 +- .../modify-resource-filters.sh | 3 +- 17 files changed, 266 insertions(+), 75 deletions(-) delete mode 100644 pkg/engine/internal/context.go rename pkg/utils/{kube => tls}/cert.go (98%) diff --git a/charts/kyverno/templates/config/_helpers.tpl b/charts/kyverno/templates/config/_helpers.tpl index 4d979d5d85..64ec92c634 100644 --- a/charts/kyverno/templates/config/_helpers.tpl +++ b/charts/kyverno/templates/config/_helpers.tpl @@ -31,18 +31,20 @@ {{- end -}} {{- define "kyverno.config.resourceFilters" -}} -{{- $resourceFilters := .Values.config.resourceFilters }} -{{- if .Values.config.excludeKyvernoNamespace }} - {{- $resourceFilters = prepend .Values.config.resourceFilters (printf "[*,%s,*]" (include "kyverno.namespace" .)) }} -{{- end }} -{{- range $exclude := .Values.config.resourceFiltersExcludeNamespaces }} - {{- range $filter := $resourceFilters }} - {{- if (contains (printf ",%s," $exclude) $filter) }} - {{- $resourceFilters = without $resourceFilters $filter }} - {{- end }} - {{- end }} -{{- end }} -{{- tpl (join "" $resourceFilters) . }} +{{- $resourceFilters := .Values.config.resourceFilters -}} +{{- if .Values.config.excludeKyvernoNamespace -}} + {{- $resourceFilters = prepend .Values.config.resourceFilters (printf "[*/*,%s,*]" (include "kyverno.namespace" .)) -}} +{{- end -}} +{{- range $exclude := .Values.config.resourceFiltersExcludeNamespaces -}} + {{- range $filter := $resourceFilters -}} + {{- if (contains (printf ",%s," $exclude) $filter) -}} + {{- $resourceFilters = without $resourceFilters $filter -}} + {{- end -}} + {{- end -}} +{{- end -}} +{{- range $resourceFilter := $resourceFilters }} +{{ tpl $resourceFilter $ }} +{{- end -}} {{- end -}} {{- define "kyverno.config.webhooks" -}} diff --git a/charts/kyverno/templates/config/configmap.yaml b/charts/kyverno/templates/config/configmap.yaml index 16dfbd3648..2304c12663 100644 --- a/charts/kyverno/templates/config/configmap.yaml +++ b/charts/kyverno/templates/config/configmap.yaml @@ -29,7 +29,8 @@ data: excludeClusterRoles: {{ join "," . | quote }} {{- end -}} {{- if .Values.config.resourceFilters }} - resourceFilters: {{ include "kyverno.config.resourceFilters" . | quote }} + resourceFilters: >- + {{- include "kyverno.config.resourceFilters" . | trim | nindent 4 }} {{- end -}} {{- if and .Values.config.webhooks .Values.config.excludeKyvernoNamespace }} webhooks: {{ include "kyverno.config.webhooks" . | quote }} diff --git a/charts/kyverno/values.yaml b/charts/kyverno/values.yaml index 7ed206c76b..9c6ae4a86f 100644 --- a/charts/kyverno/values.yaml +++ b/charts/kyverno/values.yaml @@ -73,20 +73,28 @@ config: # @default -- See [values.yaml](values.yaml) resourceFilters: - '[Event,*,*]' - - '[*,kube-system,*]' - - '[*,kube-public,*]' - - '[*,kube-node-lease,*]' + - '[*/*,kube-system,*]' + - '[*/*,kube-public,*]' + - '[*/*,kube-node-lease,*]' - '[Node,*,*]' + - '[Node/*,*,*]' - '[APIService,*,*]' + - '[APIService/*,*,*]' - '[TokenReview,*,*]' - '[SubjectAccessReview,*,*]' - '[SelfSubjectAccessReview,*,*]' - '[Binding,*,*]' + - '[Pod/binding,*,*]' - '[ReplicaSet,*,*]' + - '[ReplicaSet/*,*,*]' - '[AdmissionReport,*,*]' + - '[AdmissionReport/*,*,*]' - '[ClusterAdmissionReport,*,*]' + - '[ClusterAdmissionReport/*,*,*]' - '[BackgroundScanReport,*,*]' + - '[BackgroundScanReport/*,*,*]' - '[ClusterBackgroundScanReport,*,*]' + - '[ClusterBackgroundScanReport/*,*,*]' # exclude resources from the chart - '[ClusterRole,*,{{ template "kyverno.admission-controller.roleName" . }}]' - '[ClusterRole,*,{{ template "kyverno.admission-controller.roleName" . }}:core]' @@ -105,9 +113,13 @@ config: - '[ClusterRoleBinding,*,{{ template "kyverno.cleanup-controller.roleName" . }}]' - '[ClusterRoleBinding,*,{{ template "kyverno.reports-controller.roleName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceAccountName" . }}]' + - '[ServiceAccount/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.serviceAccountName" . }}]' + - '[ServiceAccount/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.serviceAccountName" . }}]' + - '[ServiceAccount/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.serviceAccountName" . }}]' - '[ServiceAccount,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.serviceAccountName" . }}]' + - '[ServiceAccount/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.serviceAccountName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.roleName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.roleName" . }}]' - '[Role,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.roleName" . }}]' @@ -119,28 +131,51 @@ config: - '[ConfigMap,{{ include "kyverno.namespace" . }},{{ template "kyverno.config.configMapName" . }}]' - '[ConfigMap,{{ include "kyverno.namespace" . }},{{ template "kyverno.config.metricsConfigMapName" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' + - '[Deployment/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' + - '[Deployment/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' + - '[Deployment/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Deployment,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' + - '[Deployment/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}-*]' + - '[Pod/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-*]' + - '[Pod/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-*]' + - '[Pod/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-*]' - '[Pod,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-*]' + - '[Pod/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-*]' - '[Job,{{ include "kyverno.namespace" . }},{{ template "kyverno.fullname" . }}-hook-pre-delete]' + - '[Job/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.fullname" . }}-hook-pre-delete]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' + - '[NetworkPolicy/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' + - '[NetworkPolicy/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' + - '[NetworkPolicy/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[NetworkPolicy,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' + - '[NetworkPolicy/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' + - '[PodDisruptionBudget/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' + - '[PodDisruptionBudget/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' + - '[PodDisruptionBudget/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[PodDisruptionBudget,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' + - '[PodDisruptionBudget/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}-metrics]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.admission-controller.serviceName" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-metrics]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.background-controller.name" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-metrics]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.cleanup-controller.name" . }}-metrics]' - '[Service,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-metrics]' + - '[Service/*,{{ include "kyverno.namespace" . }},{{ template "kyverno.reports-controller.name" . }}-metrics]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.admission-controller.name" . }}]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.background-controller.name" . }}]' - '[ServiceMonitor,{{ if .Values.admissionController.serviceMonitor.namespace }}{{ .Values.admissionController.serviceMonitor.namespace }}{{ else }}{{ template "kyverno.namespace" . }}{{ end }},{{ template "kyverno.cleanup-controller.name" . }}]' diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 10db70bbb8..9d537292b6 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -67,7 +67,117 @@ data: defaultRegistry: "docker.io" generateSuccessEvents: "false" excludeGroups: "system:serviceaccounts:kube-system,system:nodes" - resourceFilters: "[*,kyverno,*][Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][SelfSubjectAccessReview,*,*][Binding,*,*][ReplicaSet,*,*][AdmissionReport,*,*][ClusterAdmissionReport,*,*][BackgroundScanReport,*,*][ClusterBackgroundScanReport,*,*][ClusterRole,*,kyverno:admission-controller][ClusterRole,*,kyverno:admission-controller:core][ClusterRole,*,kyverno:admission-controller:additional][ClusterRole,*,kyverno:background-controller][ClusterRole,*,kyverno:background-controller:core][ClusterRole,*,kyverno:background-controller:additional][ClusterRole,*,kyverno:cleanup-controller][ClusterRole,*,kyverno:cleanup-controller:core][ClusterRole,*,kyverno:cleanup-controller:additional][ClusterRole,*,kyverno:reports-controller][ClusterRole,*,kyverno:reports-controller:core][ClusterRole,*,kyverno:reports-controller:additional][ClusterRoleBinding,*,kyverno:admission-controller][ClusterRoleBinding,*,kyverno:background-controller][ClusterRoleBinding,*,kyverno:cleanup-controller][ClusterRoleBinding,*,kyverno:reports-controller][ServiceAccount,kyverno,kyverno-admission-controller][ServiceAccount,kyverno,kyverno-background-controller][ServiceAccount,kyverno,kyverno-cleanup-controller][ServiceAccount,kyverno,kyverno-reports-controller][Role,kyverno,kyverno:admission-controller][Role,kyverno,kyverno:background-controller][Role,kyverno,kyverno:cleanup-controller][Role,kyverno,kyverno:reports-controller][RoleBinding,kyverno,kyverno:admission-controller][RoleBinding,kyverno,kyverno:background-controller][RoleBinding,kyverno,kyverno:cleanup-controller][RoleBinding,kyverno,kyverno:reports-controller][ConfigMap,kyverno,kyverno][ConfigMap,kyverno,kyverno-metrics][Deployment,kyverno,kyverno-admission-controller][Deployment,kyverno,kyverno-background-controller][Deployment,kyverno,kyverno-cleanup-controller][Deployment,kyverno,kyverno-reports-controller][Pod,kyverno,kyverno-admission-controller-*][Pod,kyverno,kyverno-background-controller-*][Pod,kyverno,kyverno-cleanup-controller-*][Pod,kyverno,kyverno-reports-controller-*][Job,kyverno,kyverno-hook-pre-delete][NetworkPolicy,kyverno,kyverno-admission-controller][NetworkPolicy,kyverno,kyverno-background-controller][NetworkPolicy,kyverno,kyverno-cleanup-controller][NetworkPolicy,kyverno,kyverno-reports-controller][PodDisruptionBudget,kyverno,kyverno-admission-controller][PodDisruptionBudget,kyverno,kyverno-background-controller][PodDisruptionBudget,kyverno,kyverno-cleanup-controller][PodDisruptionBudget,kyverno,kyverno-reports-controller][Service,kyverno,kyverno-svc][Service,kyverno,kyverno-svc-metrics][Service,kyverno,kyverno-background-controller-metrics][Service,kyverno,kyverno-cleanup-controller][Service,kyverno,kyverno-cleanup-controller-metrics][Service,kyverno,kyverno-reports-controller-metrics][ServiceMonitor,kyverno,kyverno-admission-controller][ServiceMonitor,kyverno,kyverno-background-controller][ServiceMonitor,kyverno,kyverno-cleanup-controller][ServiceMonitor,kyverno,kyverno-reports-controller][Secret,kyverno,kyverno-svc.kyverno.svc.*][Secret,kyverno,kyverno-cleanup-controller.kyverno.svc.*]" + resourceFilters: >- + [*/*,kyverno,*] + [Event,*,*] + [*/*,kube-system,*] + [*/*,kube-public,*] + [*/*,kube-node-lease,*] + [Node,*,*] + [Node/*,*,*] + [APIService,*,*] + [APIService/*,*,*] + [TokenReview,*,*] + [SubjectAccessReview,*,*] + [SelfSubjectAccessReview,*,*] + [Binding,*,*] + [Pod/binding,*,*] + [ReplicaSet,*,*] + [ReplicaSet/*,*,*] + [AdmissionReport,*,*] + [AdmissionReport/*,*,*] + [ClusterAdmissionReport,*,*] + [ClusterAdmissionReport/*,*,*] + [BackgroundScanReport,*,*] + [BackgroundScanReport/*,*,*] + [ClusterBackgroundScanReport,*,*] + [ClusterBackgroundScanReport/*,*,*] + [ClusterRole,*,kyverno:admission-controller] + [ClusterRole,*,kyverno:admission-controller:core] + [ClusterRole,*,kyverno:admission-controller:additional] + [ClusterRole,*,kyverno:background-controller] + [ClusterRole,*,kyverno:background-controller:core] + [ClusterRole,*,kyverno:background-controller:additional] + [ClusterRole,*,kyverno:cleanup-controller] + [ClusterRole,*,kyverno:cleanup-controller:core] + [ClusterRole,*,kyverno:cleanup-controller:additional] + [ClusterRole,*,kyverno:reports-controller] + [ClusterRole,*,kyverno:reports-controller:core] + [ClusterRole,*,kyverno:reports-controller:additional] + [ClusterRoleBinding,*,kyverno:admission-controller] + [ClusterRoleBinding,*,kyverno:background-controller] + [ClusterRoleBinding,*,kyverno:cleanup-controller] + [ClusterRoleBinding,*,kyverno:reports-controller] + [ServiceAccount,kyverno,kyverno-admission-controller] + [ServiceAccount/*,kyverno,kyverno-admission-controller] + [ServiceAccount,kyverno,kyverno-background-controller] + [ServiceAccount/*,kyverno,kyverno-background-controller] + [ServiceAccount,kyverno,kyverno-cleanup-controller] + [ServiceAccount/*,kyverno,kyverno-cleanup-controller] + [ServiceAccount,kyverno,kyverno-reports-controller] + [ServiceAccount/*,kyverno,kyverno-reports-controller] + [Role,kyverno,kyverno:admission-controller] + [Role,kyverno,kyverno:background-controller] + [Role,kyverno,kyverno:cleanup-controller] + [Role,kyverno,kyverno:reports-controller] + [RoleBinding,kyverno,kyverno:admission-controller] + [RoleBinding,kyverno,kyverno:background-controller] + [RoleBinding,kyverno,kyverno:cleanup-controller] + [RoleBinding,kyverno,kyverno:reports-controller] + [ConfigMap,kyverno,kyverno] + [ConfigMap,kyverno,kyverno-metrics] + [Deployment,kyverno,kyverno-admission-controller] + [Deployment/*,kyverno,kyverno-admission-controller] + [Deployment,kyverno,kyverno-background-controller] + [Deployment/*,kyverno,kyverno-background-controller] + [Deployment,kyverno,kyverno-cleanup-controller] + [Deployment/*,kyverno,kyverno-cleanup-controller] + [Deployment,kyverno,kyverno-reports-controller] + [Deployment/*,kyverno,kyverno-reports-controller] + [Pod,kyverno,kyverno-admission-controller-*] + [Pod/*,kyverno,kyverno-admission-controller-*] + [Pod,kyverno,kyverno-background-controller-*] + [Pod/*,kyverno,kyverno-background-controller-*] + [Pod,kyverno,kyverno-cleanup-controller-*] + [Pod/*,kyverno,kyverno-cleanup-controller-*] + [Pod,kyverno,kyverno-reports-controller-*] + [Pod/*,kyverno,kyverno-reports-controller-*] + [Job,kyverno,kyverno-hook-pre-delete] + [Job/*,kyverno,kyverno-hook-pre-delete] + [NetworkPolicy,kyverno,kyverno-admission-controller] + [NetworkPolicy/*,kyverno,kyverno-admission-controller] + [NetworkPolicy,kyverno,kyverno-background-controller] + [NetworkPolicy/*,kyverno,kyverno-background-controller] + [NetworkPolicy,kyverno,kyverno-cleanup-controller] + [NetworkPolicy/*,kyverno,kyverno-cleanup-controller] + [NetworkPolicy,kyverno,kyverno-reports-controller] + [NetworkPolicy/*,kyverno,kyverno-reports-controller] + [PodDisruptionBudget,kyverno,kyverno-admission-controller] + [PodDisruptionBudget/*,kyverno,kyverno-admission-controller] + [PodDisruptionBudget,kyverno,kyverno-background-controller] + [PodDisruptionBudget/*,kyverno,kyverno-background-controller] + [PodDisruptionBudget,kyverno,kyverno-cleanup-controller] + [PodDisruptionBudget/*,kyverno,kyverno-cleanup-controller] + [PodDisruptionBudget,kyverno,kyverno-reports-controller] + [PodDisruptionBudget/*,kyverno,kyverno-reports-controller] + [Service,kyverno,kyverno-svc] + [Service/*,kyverno,kyverno-svc] + [Service,kyverno,kyverno-svc-metrics] + [Service/*,kyverno,kyverno-svc-metrics] + [Service,kyverno,kyverno-background-controller-metrics] + [Service/*,kyverno,kyverno-background-controller-metrics] + [Service,kyverno,kyverno-cleanup-controller] + [Service/*,kyverno,kyverno-cleanup-controller] + [Service,kyverno,kyverno-cleanup-controller-metrics] + [Service/*,kyverno,kyverno-cleanup-controller-metrics] + [Service,kyverno,kyverno-reports-controller-metrics] + [Service/*,kyverno,kyverno-reports-controller-metrics] + [ServiceMonitor,kyverno,kyverno-admission-controller] + [ServiceMonitor,kyverno,kyverno-background-controller] + [ServiceMonitor,kyverno,kyverno-cleanup-controller] + [ServiceMonitor,kyverno,kyverno-reports-controller] + [Secret,kyverno,kyverno-svc.kyverno.svc.*] + [Secret,kyverno,kyverno-cleanup-controller.kyverno.svc.*] webhooks: '[{"namespaceSelector": {"matchExpressions": [{"key":"kubernetes.io/metadata.name","operator":"NotIn","values":["kyverno"]}]}}]' --- apiVersion: v1 diff --git a/pkg/config/config.go b/pkg/config/config.go index 11620a589c..be7afae758 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,6 +11,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" ) @@ -134,7 +135,7 @@ type Configuration interface { // GetEnableDefaultRegistryMutation return if should mutate image registry GetEnableDefaultRegistryMutation() bool // ToFilter checks if the given resource is set to be filtered in the configuration - ToFilter(kind, namespace, name string) bool + ToFilter(kind schema.GroupVersionKind, subresource, namespace, name string) bool // GetExcludedGroups return excluded groups GetExcludedGroups() []string // GetExcludedUsernames return excluded usernames @@ -191,19 +192,35 @@ func NewConfiguration(client kubernetes.Interface, skipResourceFilters bool) (Co return cd, nil } -func (cd *configuration) ToFilter(kind, namespace, name string) bool { +func (cd *configuration) ToFilter(gvk schema.GroupVersionKind, subresource, namespace, name string) bool { cd.mux.RLock() defer cd.mux.RUnlock() if !cd.skipResourceFilters { for _, f := range cd.filters { - if wildcard.Match(f.Kind, kind) && wildcard.Match(f.Namespace, namespace) && wildcard.Match(f.Name, name) { + if wildcard.Match(f.Group, gvk.Group) && + wildcard.Match(f.Version, gvk.Version) && + wildcard.Match(f.Kind, gvk.Kind) && + wildcard.Match(f.Subresource, subresource) && + wildcard.Match(f.Namespace, namespace) && + wildcard.Match(f.Name, name) { return true } - if kind == "Namespace" { - // [Namespace,kube-system,*] || [*,kube-system,*] - if (f.Kind == "Namespace" || f.Kind == "*") && wildcard.Match(f.Namespace, name) { + // [Namespace,kube-system,*] || [*,kube-system,*] + if gvk.Group == "" && gvk.Version == "v1" && gvk.Kind == "Namespace" { + if wildcard.Match(f.Group, gvk.Group) && + wildcard.Match(f.Version, gvk.Version) && + wildcard.Match(f.Kind, gvk.Kind) && + wildcard.Match(f.Namespace, name) { return true } + if gvk.Group == "" && gvk.Version == "v1" && gvk.Kind == "Namespace" { + if wildcard.Match(f.Group, gvk.Group) && + wildcard.Match(f.Version, gvk.Version) && + wildcard.Match(f.Kind, gvk.Kind) && + wildcard.Match(f.Namespace, name) { + return true + } + } } } } diff --git a/pkg/config/types.go b/pkg/config/types.go index ef9a01593d..16c41332bf 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -5,6 +5,7 @@ import ( "regexp" "strings" + kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -52,9 +53,27 @@ func parseIncludeExcludeNamespacesFromNamespacesConfig(in string) (namespacesCon } type filter struct { - Kind string // TODO: as we currently only support one GVK version, we use the kind only. But if we support multiple GVK, then GV need to be added - Namespace string - Name string + Group string + Version string + Kind string + Subresource string + Namespace string + Name string +} + +func newFilter(kind, namespace, name string) filter { + if kind == "" { + return filter{} + } + g, v, k, s := kubeutils.ParseKindSelector(kind) + return filter{ + Group: g, + Version: v, + Kind: k, + Subresource: s, + Namespace: namespace, + Name: name, + } } // ParseKinds parses the kinds if a single string contains comma separated kinds @@ -72,13 +91,13 @@ func parseKinds(in string) []filter { continue } if len(elements) == 3 { - resource = filter{Kind: elements[0], Namespace: elements[1], Name: elements[2]} + resource = newFilter(elements[0], elements[1], elements[2]) } if len(elements) == 2 { - resource = filter{Kind: elements[0], Namespace: elements[1]} + resource = newFilter(elements[0], elements[1], "") } if len(elements) == 1 { - resource = filter{Kind: elements[0]} + resource = newFilter(elements[0], "", "") } resources = append(resources, resource) } diff --git a/pkg/config/types_test.go b/pkg/config/types_test.go index bc6b68d4dd..af97f5439d 100644 --- a/pkg/config/types_test.go +++ b/pkg/config/types_test.go @@ -64,56 +64,76 @@ func Test_parseKinds(t *testing.T) { }, { args: args{"[*]"}, want: []filter{ - {"*", "", ""}, + {"*", "*", "*", "", "", ""}, + }, + }, { + args: args{"[*/*]"}, + want: []filter{ + {"*", "*", "*", "*", "", ""}, + }, + }, { + args: args{"[Pod/*]"}, + want: []filter{ + {"*", "*", "Pod", "*", "", ""}, + }, + }, { + args: args{"[v1/Pod/*]"}, + want: []filter{ + {"*", "v1", "Pod", "*", "", ""}, + }, + }, { + args: args{"[v1/Pod]"}, + want: []filter{ + {"*", "v1", "Pod", "", "", ""}, }, }, { args: args{"[Node]"}, want: []filter{ - {"Node", "", ""}, + {"*", "*", "Node", "", "", ""}, }, }, { args: args{"[Node,*,*]"}, want: []filter{ - {"Node", "*", "*"}, + {"*", "*", "Node", "", "*", "*"}, }, }, { args: args{"[Pod,default,nginx]"}, want: []filter{ - {"Pod", "default", "nginx"}, + {"*", "*", "Pod", "", "default", "nginx"}, }, }, { args: args{"[Pod,*,nginx]"}, want: []filter{ - {"Pod", "*", "nginx"}, + {"*", "*", "Pod", "", "*", "nginx"}, }, }, { args: args{"[Pod,*]"}, want: []filter{ - {"Pod", "*", ""}, + {"*", "*", "Pod", "", "*", ""}, }, }, { args: args{"[Pod,default,nginx][Pod,kube-system,api-server]"}, want: []filter{ - {"Pod", "default", "nginx"}, - {"Pod", "kube-system", "api-server"}, + {"*", "*", "Pod", "", "default", "nginx"}, + {"*", "*", "Pod", "", "kube-system", "api-server"}, }, }, { args: args{"[Pod,default,nginx],[Pod,kube-system,api-server]"}, want: []filter{ - {"Pod", "default", "nginx"}, - {"Pod", "kube-system", "api-server"}, + {"*", "*", "Pod", "", "default", "nginx"}, + {"*", "*", "Pod", "", "kube-system", "api-server"}, }, }, { args: args{"[Pod,default,nginx] [Pod,kube-system,api-server]"}, want: []filter{ - {"Pod", "default", "nginx"}, - {"Pod", "kube-system", "api-server"}, + {"*", "*", "Pod", "", "default", "nginx"}, + {"*", "*", "Pod", "", "kube-system", "api-server"}, }, }, { args: args{"[Pod,default,nginx]Pod,kube-system,api-server[Pod,kube-system,api-server]"}, want: []filter{ - {"Pod", "default", "nginx"}, - {"Pod", "kube-system", "api-server"}, + {"*", "*", "Pod", "", "default", "nginx"}, + {"*", "*", "Pod", "", "kube-system", "api-server"}, }, }, { args: args{"[Pod,default,nginx,unexpected]"}, diff --git a/pkg/engine/background.go b/pkg/engine/background.go index 37c04c833d..73726d1a6a 100644 --- a/pkg/engine/background.go +++ b/pkg/engine/background.go @@ -89,7 +89,8 @@ func (e *engine) filterRule( policyContext.JSONContext().Checkpoint() defer policyContext.JSONContext().Restore() - if err := internal.LoadContext(context.TODO(), e, policyContext, rule); err != nil { + contextLoader := e.ContextLoader(policyContext.Policy(), rule) + if err := contextLoader(context.TODO(), rule.Context, policyContext.JSONContext()); err != nil { logger.V(4).Info("cannot add external data to the context", "reason", err.Error()) return nil } diff --git a/pkg/engine/internal/context.go b/pkg/engine/internal/context.go deleted file mode 100644 index 6d9d1f09f6..0000000000 --- a/pkg/engine/internal/context.go +++ /dev/null @@ -1,18 +0,0 @@ -package internal - -import ( - "context" - - kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" - engineapi "github.com/kyverno/kyverno/pkg/engine/api" -) - -func LoadContext( - ctx context.Context, - engine engineapi.Engine, - pContext engineapi.PolicyContext, - rule kyvernov1.Rule, -) error { - loader := engine.ContextLoader(pContext.Policy(), rule) - return loader(ctx, rule.Context, pContext.JSONContext()) -} diff --git a/pkg/engine/internal/match.go b/pkg/engine/internal/match.go index a0f1ea246f..3de8df54af 100644 --- a/pkg/engine/internal/match.go +++ b/pkg/engine/internal/match.go @@ -6,6 +6,7 @@ import ( "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" ) func MatchPolicyContext(logger logr.Logger, policyContext engineapi.PolicyContext, configuration config.Configuration) bool { @@ -16,18 +17,19 @@ func MatchPolicyContext(logger logr.Logger, policyContext engineapi.PolicyContex logger.V(2).Info("policy namespace doesn't match resource namespace") return false } - if !checkResourceFilters(configuration, new, old) { + gvk, subresource := policyContext.ResourceKind() + if !checkResourceFilters(configuration, gvk, subresource, new, old) { logger.V(2).Info("configuration resource filters doesn't match resource") return false } return true } -func checkResourceFilters(configuration config.Configuration, resources ...unstructured.Unstructured) bool { +func checkResourceFilters(configuration config.Configuration, gvk schema.GroupVersionKind, subresource string, resources ...unstructured.Unstructured) bool { for _, resource := range resources { if resource.Object != nil { // TODO: account for generate name here ? - if configuration.ToFilter(resource.GetKind(), resource.GetNamespace(), resource.GetName()) { + if configuration.ToFilter(gvk, subresource, resource.GetNamespace(), resource.GetName()) { return false } } diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index efdeaec283..729a0386f4 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -8,7 +8,7 @@ import ( "github.com/go-logr/logr" "github.com/kyverno/kyverno/pkg/config" kconfig "github.com/kyverno/kyverno/pkg/config" - "github.com/kyverno/kyverno/pkg/utils/kube" + tlsutils "github.com/kyverno/kyverno/pkg/utils/tls" "github.com/kyverno/kyverno/pkg/version" "github.com/prometheus/client_golang/prometheus/promhttp" "go.opentelemetry.io/otel" @@ -111,7 +111,7 @@ func NewOTLPGRPCConfig( options := []otlpmetricgrpc.Option{otlpmetricgrpc.WithEndpoint(endpoint), otlpmetricgrpc.WithAggregationSelector(aggregationSelector)} if certs != "" { // here the certificates are stored as configmaps - transportCreds, err := kube.FetchCert(ctx, certs, kubeClient) + transportCreds, err := tlsutils.FetchCert(ctx, certs, kubeClient) if err != nil { log.Error(err, "Error fetching certificate from secret") return nil, err diff --git a/pkg/tracing/config.go b/pkg/tracing/config.go index d2b8b9a7f5..be9b25af3f 100644 --- a/pkg/tracing/config.go +++ b/pkg/tracing/config.go @@ -5,7 +5,7 @@ import ( "time" "github.com/go-logr/logr" - "github.com/kyverno/kyverno/pkg/utils/kube" + tlsutils "github.com/kyverno/kyverno/pkg/utils/tls" "github.com/kyverno/kyverno/pkg/version" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace" @@ -23,7 +23,7 @@ func NewTraceConfig(log logr.Logger, tracerName, address, certs string, kubeClie var client otlptrace.Client if certs != "" { // here the certificates are stored as configmaps - transportCreds, err := kube.FetchCert(ctx, certs, kubeClient) + transportCreds, err := tlsutils.FetchCert(ctx, certs, kubeClient) if err != nil { log.Error(err, "Error fetching certificate from secret") } diff --git a/pkg/utils/kube/cert.go b/pkg/utils/tls/cert.go similarity index 98% rename from pkg/utils/kube/cert.go rename to pkg/utils/tls/cert.go index 1ff6e6e991..1d6c5d44fe 100644 --- a/pkg/utils/kube/cert.go +++ b/pkg/utils/tls/cert.go @@ -1,4 +1,4 @@ -package kube +package tls import ( "context" diff --git a/pkg/webhooks/handlers/filter.go b/pkg/webhooks/handlers/filter.go index 49f6a692eb..a71aaa0164 100644 --- a/pkg/webhooks/handlers/filter.go +++ b/pkg/webhooks/handlers/filter.go @@ -58,7 +58,7 @@ func (inner AdmissionHandler) withFilter(c config.Configuration) AdmissionHandle } } // filter by resource filters - if c.ToFilter(request.Kind.Kind, request.Namespace, request.Name) { + if c.ToFilter(request.GroupVersionKind, request.SubResource, request.Namespace, request.Name) { return admissionutils.ResponseSuccess(request.UID) } // filter kyverno resources diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-existing-node-status/modify-resource-filters.sh b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-existing-node-status/modify-resource-filters.sh index efec3e70b1..9594d5a6d2 100755 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-existing-node-status/modify-resource-filters.sh +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-existing-node-status/modify-resource-filters.sh @@ -9,6 +9,7 @@ fi if [ "$1" = "removeNode" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) resource_filters="${resource_filters//\[Node,\*,\*\]/}" + resource_filters="${resource_filters//\[Node\/\*,\*,\*\]/}" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi @@ -17,6 +18,6 @@ if [ "$1" = "addNode" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) resource_filters="${resource_filters%?}" - resource_filters="${resource_filters}""[Node,*,*]\"" + resource_filters="${resource_filters}""[Node,*,*][Node/*,*,*]\"" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-pod-on-binding-request/modify-resource-filters.sh b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-pod-on-binding-request/modify-resource-filters.sh index e4ecbb1f64..9260e2e065 100755 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-pod-on-binding-request/modify-resource-filters.sh +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/mutate-pod-on-binding-request/modify-resource-filters.sh @@ -8,7 +8,7 @@ fi if [ "$1" = "removeBinding" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) - resource_filters="${resource_filters//\[Binding,\*,\*\]/}" + resource_filters="${resource_filters//\[Pod\/binding,\*,\*\]/}" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi @@ -17,6 +17,6 @@ if [ "$1" = "addBinding" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) resource_filters="${resource_filters%?}" - resource_filters="${resource_filters}""[Binding,*,*]\"" + resource_filters="${resource_filters}""[Pod/binding,*,*]\"" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/mutate-node-status/modify-resource-filters.sh b/test/conformance/kuttl/mutate/clusterpolicy/standard/mutate-node-status/modify-resource-filters.sh index efec3e70b1..9594d5a6d2 100755 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/mutate-node-status/modify-resource-filters.sh +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/mutate-node-status/modify-resource-filters.sh @@ -9,6 +9,7 @@ fi if [ "$1" = "removeNode" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) resource_filters="${resource_filters//\[Node,\*,\*\]/}" + resource_filters="${resource_filters//\[Node\/\*,\*,\*\]/}" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi @@ -17,6 +18,6 @@ if [ "$1" = "addNode" ]; then resource_filters=$(kubectl get ConfigMap kyverno -n kyverno -o json | jq .data.resourceFilters) resource_filters="${resource_filters%?}" - resource_filters="${resource_filters}""[Node,*,*]\"" + resource_filters="${resource_filters}""[Node,*,*][Node/*,*,*]\"" kubectl patch ConfigMap kyverno -n kyverno --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/resourceFilters\", \"value\":""$resource_filters""}]" fi