2019-03-21 16:09:14 +00:00
|
|
|
package config
|
2019-03-21 13:57:30 +00:00
|
|
|
|
2019-11-18 19:41:37 +00:00
|
|
|
import (
|
2022-05-04 16:05:03 +00:00
|
|
|
"context"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
2020-07-01 21:50:49 +00:00
|
|
|
|
2022-04-01 06:59:44 +00:00
|
|
|
osutils "github.com/kyverno/kyverno/pkg/utils/os"
|
2022-08-25 05:23:01 +00:00
|
|
|
wildcard "github.com/kyverno/kyverno/pkg/utils/wildcard"
|
2022-05-17 14:14:31 +00:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2022-05-04 16:05:03 +00:00
|
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"k8s.io/client-go/kubernetes"
|
2019-11-18 19:41:37 +00:00
|
|
|
)
|
2019-05-30 19:28:56 +00:00
|
|
|
|
2020-01-24 20:05:53 +00:00
|
|
|
// These constants MUST be equal to the corresponding names in service definition in definitions/install.yaml
|
2022-12-15 08:34:44 +00:00
|
|
|
|
|
|
|
// webhook configuration names
|
2019-03-21 13:57:30 +00:00
|
|
|
const (
|
2022-12-15 08:34:44 +00:00
|
|
|
// PolicyValidatingWebhookConfigurationName default policy validating webhook configuration name
|
|
|
|
PolicyValidatingWebhookConfigurationName = "kyverno-policy-validating-webhook-cfg"
|
2022-05-04 16:05:03 +00:00
|
|
|
// ValidatingWebhookConfigurationName ...
|
|
|
|
ValidatingWebhookConfigurationName = "kyverno-resource-validating-webhook-cfg"
|
2022-12-22 06:13:32 +00:00
|
|
|
// ExceptionValidatingWebhookConfigurationName ...
|
2022-12-15 08:34:44 +00:00
|
|
|
ExceptionValidatingWebhookConfigurationName = "kyverno-exception-validating-webhook-cfg"
|
2022-12-22 06:13:32 +00:00
|
|
|
// CleanupValidatingWebhookConfigurationName ...
|
|
|
|
CleanupValidatingWebhookConfigurationName = "kyverno-cleanup-validating-webhook-cfg"
|
2022-12-15 08:34:44 +00:00
|
|
|
// PolicyMutatingWebhookConfigurationName default policy mutating webhook configuration name
|
|
|
|
PolicyMutatingWebhookConfigurationName = "kyverno-policy-mutating-webhook-cfg"
|
|
|
|
// MutatingWebhookConfigurationName default resource mutating webhook configuration name
|
|
|
|
MutatingWebhookConfigurationName = "kyverno-resource-mutating-webhook-cfg"
|
2022-05-17 06:19:03 +00:00
|
|
|
// VerifyMutatingWebhookConfigurationName default verify mutating webhook configuration name
|
2020-01-24 20:05:53 +00:00
|
|
|
VerifyMutatingWebhookConfigurationName = "kyverno-verify-mutating-webhook-cfg"
|
2022-12-15 08:34:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// webhook names
|
|
|
|
const (
|
2022-05-17 06:19:03 +00:00
|
|
|
// PolicyValidatingWebhookName default policy validating webhook name
|
2020-11-27 00:07:06 +00:00
|
|
|
PolicyValidatingWebhookName = "validate-policy.kyverno.svc"
|
2022-12-15 08:34:44 +00:00
|
|
|
// ValidatingWebhookName ...
|
|
|
|
ValidatingWebhookName = "validate.kyverno.svc"
|
2022-05-17 06:19:03 +00:00
|
|
|
// PolicyMutatingWebhookName default policy mutating webhook name
|
2020-11-27 00:07:06 +00:00
|
|
|
PolicyMutatingWebhookName = "mutate-policy.kyverno.svc"
|
2022-12-15 08:34:44 +00:00
|
|
|
// MutatingWebhookName default resource mutating webhook name
|
|
|
|
MutatingWebhookName = "mutate.kyverno.svc"
|
|
|
|
// VerifyMutatingWebhookName default verify mutating webhook name
|
|
|
|
VerifyMutatingWebhookName = "monitor-webhooks.kyverno.svc"
|
|
|
|
)
|
|
|
|
|
|
|
|
// paths
|
|
|
|
const (
|
2022-05-17 06:19:03 +00:00
|
|
|
// PolicyValidatingWebhookServicePath is the path for policy validation webhook(used to validate policy resource)
|
2019-07-03 01:42:07 +00:00
|
|
|
PolicyValidatingWebhookServicePath = "/policyvalidate"
|
2022-12-15 08:34:44 +00:00
|
|
|
// ValidatingWebhookServicePath is the path for validation webhook
|
|
|
|
ValidatingWebhookServicePath = "/validate"
|
|
|
|
// ExceptionValidatingWebhookServicePath is the path for policy exception validation webhook(used to validate policy exception resource)
|
|
|
|
ExceptionValidatingWebhookServicePath = "/exceptionvalidate"
|
2022-12-22 06:13:32 +00:00
|
|
|
// CleanupValidatingWebhookServicePath is the path for cleanup policy validation webhook(used to validate cleanup policy resource)
|
|
|
|
CleanupValidatingWebhookServicePath = "/validate"
|
2022-05-17 06:19:03 +00:00
|
|
|
// PolicyMutatingWebhookServicePath is the path for policy mutation webhook(used to default)
|
2020-01-24 20:05:53 +00:00
|
|
|
PolicyMutatingWebhookServicePath = "/policymutate"
|
2022-12-15 08:34:44 +00:00
|
|
|
// MutatingWebhookServicePath is the path for mutation webhook
|
|
|
|
MutatingWebhookServicePath = "/mutate"
|
2022-05-17 06:19:03 +00:00
|
|
|
// VerifyMutatingWebhookServicePath is the path for verify webhook(used to veryfing if admission control is enabled and active)
|
2020-01-24 20:05:53 +00:00
|
|
|
VerifyMutatingWebhookServicePath = "/verifymutate"
|
2020-05-27 01:03:32 +00:00
|
|
|
// LivenessServicePath is the path for check liveness health
|
|
|
|
LivenessServicePath = "/health/liveness"
|
2020-07-01 21:50:49 +00:00
|
|
|
// ReadinessServicePath is the path for check readness health
|
2020-05-27 01:03:32 +00:00
|
|
|
ReadinessServicePath = "/health/readiness"
|
2022-12-09 09:49:45 +00:00
|
|
|
// MetricsPath is the path for exposing metrics
|
|
|
|
MetricsPath = "/metrics"
|
2019-03-25 13:44:53 +00:00
|
|
|
)
|
2019-05-30 19:28:56 +00:00
|
|
|
|
2022-12-15 08:34:44 +00:00
|
|
|
const (
|
|
|
|
// Due to kubernetes issue, we must use next literal constants instead of deployment TypeMeta fields
|
|
|
|
// Issue: https://github.com/kubernetes/kubernetes/pull/63972
|
|
|
|
// When the issue is closed, we should use TypeMeta struct instead of this constants
|
|
|
|
// ClusterRoleAPIVersion define the default clusterrole resource apiVersion
|
|
|
|
ClusterRoleAPIVersion = "rbac.authorization.k8s.io/v1"
|
|
|
|
// ClusterRoleKind define the default clusterrole resource kind
|
|
|
|
ClusterRoleKind = "ClusterRole"
|
|
|
|
)
|
|
|
|
|
2022-04-01 06:59:44 +00:00
|
|
|
var (
|
2022-05-11 06:14:30 +00:00
|
|
|
// kyvernoNamespace is the Kyverno namespace
|
|
|
|
kyvernoNamespace = osutils.GetEnvWithFallback("KYVERNO_NAMESPACE", "kyverno")
|
2022-09-06 15:43:04 +00:00
|
|
|
// kyvernoServiceAccountName is the Kyverno service account name
|
|
|
|
kyvernoServiceAccountName = osutils.GetEnvWithFallback("KYVERNO_SERVICEACCOUNT_NAME", "kyverno")
|
2022-05-11 06:14:30 +00:00
|
|
|
// kyvernoDeploymentName is the Kyverno deployment name
|
|
|
|
kyvernoDeploymentName = osutils.GetEnvWithFallback("KYVERNO_DEPLOYMENT", "kyverno")
|
|
|
|
// kyvernoServiceName is the Kyverno service name
|
|
|
|
kyvernoServiceName = osutils.GetEnvWithFallback("KYVERNO_SVC", "kyverno-svc")
|
|
|
|
// kyvernoPodName is the Kyverno pod name
|
|
|
|
kyvernoPodName = osutils.GetEnvWithFallback("KYVERNO_POD_NAME", "kyverno")
|
|
|
|
// kyvernoConfigMapName is the Kyverno configmap name
|
|
|
|
kyvernoConfigMapName = osutils.GetEnvWithFallback("INIT_CONFIG", "kyverno")
|
2022-05-04 16:05:03 +00:00
|
|
|
// defaultExcludeGroupRole ...
|
|
|
|
defaultExcludeGroupRole []string = []string{"system:serviceaccounts:kube-system", "system:nodes", "system:kube-scheduler"}
|
2022-11-17 08:17:45 +00:00
|
|
|
// kyvernoDryRunNamespace is the namespace for DryRun option of YAML verification
|
|
|
|
kyvernoDryrunNamespace = osutils.GetEnvWithFallback("KYVERNO_DRYRUN_NAMESPACE", "kyverno-dryrun")
|
2022-04-01 06:59:44 +00:00
|
|
|
)
|
|
|
|
|
2022-05-11 06:14:30 +00:00
|
|
|
func KyvernoNamespace() string {
|
|
|
|
return kyvernoNamespace
|
|
|
|
}
|
|
|
|
|
2022-11-17 08:17:45 +00:00
|
|
|
func KyvernoDryRunNamespace() string {
|
|
|
|
return kyvernoDryrunNamespace
|
|
|
|
}
|
|
|
|
|
2022-09-06 15:43:04 +00:00
|
|
|
func KyvernoServiceAccountName() string {
|
|
|
|
return kyvernoServiceAccountName
|
|
|
|
}
|
|
|
|
|
2022-05-11 06:14:30 +00:00
|
|
|
func KyvernoDeploymentName() string {
|
|
|
|
return kyvernoDeploymentName
|
|
|
|
}
|
|
|
|
|
|
|
|
func KyvernoServiceName() string {
|
|
|
|
return kyvernoServiceName
|
|
|
|
}
|
|
|
|
|
|
|
|
func KyvernoPodName() string {
|
|
|
|
return kyvernoPodName
|
|
|
|
}
|
|
|
|
|
|
|
|
func KyvernoConfigMapName() string {
|
|
|
|
return kyvernoConfigMapName
|
|
|
|
}
|
|
|
|
|
2022-05-04 16:05:03 +00:00
|
|
|
// Configuration to be used by consumer to check filters
|
|
|
|
type Configuration interface {
|
|
|
|
// ToFilter checks if the given resource is set to be filtered in the configuration
|
|
|
|
ToFilter(kind, namespace, name string) bool
|
|
|
|
// GetExcludeGroupRole return exclude roles
|
|
|
|
GetExcludeGroupRole() []string
|
|
|
|
// GetExcludeUsername return exclude username
|
|
|
|
GetExcludeUsername() []string
|
|
|
|
// GetGenerateSuccessEvents return if should generate success events
|
|
|
|
GetGenerateSuccessEvents() bool
|
|
|
|
// FilterNamespaces filters exclude namespace
|
|
|
|
FilterNamespaces(namespaces []string) []string
|
|
|
|
// GetWebhooks returns the webhook configs
|
|
|
|
GetWebhooks() []WebhookConfig
|
|
|
|
// Load loads configuration from a configmap
|
2022-05-17 14:14:31 +00:00
|
|
|
Load(cm *corev1.ConfigMap)
|
2022-05-04 16:05:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// configuration stores the configuration
|
|
|
|
type configuration struct {
|
2022-11-07 16:48:25 +00:00
|
|
|
mux sync.RWMutex
|
|
|
|
filters []filter
|
|
|
|
excludeGroupRole []string
|
|
|
|
excludeUsername []string
|
|
|
|
webhooks []WebhookConfig
|
|
|
|
generateSuccessEvents bool
|
2022-05-04 16:05:03 +00:00
|
|
|
}
|
|
|
|
|
2022-11-25 13:14:55 +00:00
|
|
|
// NewDefaultConfiguration ...
|
2022-10-12 06:52:42 +00:00
|
|
|
func NewDefaultConfiguration() *configuration {
|
2022-10-07 11:32:38 +00:00
|
|
|
return &configuration{
|
2022-11-07 16:48:25 +00:00
|
|
|
excludeGroupRole: defaultExcludeGroupRole,
|
2022-05-04 16:05:03 +00:00
|
|
|
}
|
2022-10-07 11:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewConfiguration ...
|
2022-10-12 06:52:42 +00:00
|
|
|
func NewConfiguration(client kubernetes.Interface) (Configuration, error) {
|
|
|
|
cd := NewDefaultConfiguration()
|
2022-05-11 06:14:30 +00:00
|
|
|
if cm, err := client.CoreV1().ConfigMaps(kyvernoNamespace).Get(context.TODO(), kyvernoConfigMapName, metav1.GetOptions{}); err != nil {
|
2022-05-04 16:05:03 +00:00
|
|
|
if !errors.IsNotFound(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cd.load(cm)
|
|
|
|
}
|
|
|
|
return cd, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) ToFilter(kind, namespace, name string) bool {
|
|
|
|
cd.mux.RLock()
|
|
|
|
defer cd.mux.RUnlock()
|
|
|
|
for _, f := range cd.filters {
|
|
|
|
if wildcard.Match(f.Kind, kind) && 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) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) GetExcludeGroupRole() []string {
|
|
|
|
cd.mux.RLock()
|
|
|
|
defer cd.mux.RUnlock()
|
|
|
|
return cd.excludeGroupRole
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) GetExcludeUsername() []string {
|
|
|
|
cd.mux.RLock()
|
|
|
|
defer cd.mux.RUnlock()
|
|
|
|
return cd.excludeUsername
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) GetGenerateSuccessEvents() bool {
|
|
|
|
cd.mux.RLock()
|
|
|
|
defer cd.mux.RUnlock()
|
|
|
|
return cd.generateSuccessEvents
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) FilterNamespaces(namespaces []string) []string {
|
|
|
|
var results []string
|
|
|
|
for _, ns := range namespaces {
|
|
|
|
if !cd.ToFilter("", ns, "") {
|
|
|
|
results = append(results, ns)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) GetWebhooks() []WebhookConfig {
|
|
|
|
cd.mux.RLock()
|
|
|
|
defer cd.mux.RUnlock()
|
|
|
|
return cd.webhooks
|
|
|
|
}
|
|
|
|
|
2022-05-17 14:14:31 +00:00
|
|
|
func (cd *configuration) Load(cm *corev1.ConfigMap) {
|
2022-05-04 16:05:03 +00:00
|
|
|
if cm != nil {
|
2022-10-14 17:36:46 +00:00
|
|
|
cd.load(cm)
|
2022-05-04 16:05:03 +00:00
|
|
|
} else {
|
|
|
|
cd.unload()
|
|
|
|
}
|
2021-12-08 13:03:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-14 17:36:46 +00:00
|
|
|
func (cd *configuration) load(cm *corev1.ConfigMap) {
|
2022-05-04 16:05:03 +00:00
|
|
|
logger := logger.WithValues("name", cm.Name, "namespace", cm.Namespace)
|
|
|
|
if cm.Data == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cd.mux.Lock()
|
|
|
|
defer cd.mux.Unlock()
|
2022-10-14 17:36:46 +00:00
|
|
|
// reset
|
|
|
|
cd.filters = []filter{}
|
|
|
|
cd.excludeGroupRole = []string{}
|
|
|
|
cd.excludeUsername = []string{}
|
|
|
|
cd.generateSuccessEvents = false
|
|
|
|
cd.webhooks = nil
|
|
|
|
// load filters
|
|
|
|
cd.filters = parseKinds(cm.Data["resourceFilters"])
|
|
|
|
// load excludeGroupRole
|
|
|
|
cd.excludeGroupRole = append(cd.excludeGroupRole, parseRbac(cm.Data["excludeGroupRole"])...)
|
|
|
|
cd.excludeGroupRole = append(cd.excludeGroupRole, defaultExcludeGroupRole...)
|
|
|
|
// load excludeUsername
|
|
|
|
cd.excludeUsername = append(cd.excludeUsername, parseRbac(cm.Data["excludeUsername"])...)
|
|
|
|
// load generateSuccessEvents
|
|
|
|
generateSuccessEvents, ok := cm.Data["generateSuccessEvents"]
|
|
|
|
if ok {
|
|
|
|
generateSuccessEvents, err := strconv.ParseBool(generateSuccessEvents)
|
2022-05-04 16:05:03 +00:00
|
|
|
if err != nil {
|
2022-10-14 17:36:46 +00:00
|
|
|
logger.Error(err, "failed to parse generateSuccessEvents")
|
2022-05-04 16:05:03 +00:00
|
|
|
} else {
|
2022-10-14 17:36:46 +00:00
|
|
|
cd.generateSuccessEvents = generateSuccessEvents
|
2022-05-04 16:05:03 +00:00
|
|
|
}
|
2019-11-18 19:41:37 +00:00
|
|
|
}
|
2022-10-14 17:36:46 +00:00
|
|
|
// load webhooks
|
|
|
|
webhooks, ok := cm.Data["webhooks"]
|
|
|
|
if ok {
|
|
|
|
webhooks, err := parseWebhooks(webhooks)
|
2022-05-04 16:05:03 +00:00
|
|
|
if err != nil {
|
2022-10-14 17:36:46 +00:00
|
|
|
logger.Error(err, "failed to parse webhooks")
|
2022-05-04 16:05:03 +00:00
|
|
|
} else {
|
2022-10-14 17:36:46 +00:00
|
|
|
cd.webhooks = webhooks
|
2022-05-04 16:05:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cd *configuration) unload() {
|
|
|
|
cd.mux.Lock()
|
|
|
|
defer cd.mux.Unlock()
|
|
|
|
cd.filters = []filter{}
|
|
|
|
cd.excludeGroupRole = []string{}
|
|
|
|
cd.excludeUsername = []string{}
|
|
|
|
cd.generateSuccessEvents = false
|
2022-10-14 17:36:46 +00:00
|
|
|
cd.webhooks = nil
|
|
|
|
cd.excludeGroupRole = append(cd.excludeGroupRole, defaultExcludeGroupRole...)
|
2019-11-18 19:41:37 +00:00
|
|
|
}
|