2019-08-21 01:07:32 -07:00
|
|
|
package webhookconfig
|
2019-03-21 15:57:30 +02:00
|
|
|
|
2019-03-19 21:32:31 +02:00
|
|
|
import (
|
2021-06-14 13:01:40 -07:00
|
|
|
"encoding/json"
|
2020-03-17 11:05:20 -07:00
|
|
|
"fmt"
|
2020-11-26 16:07:06 -08:00
|
|
|
"strings"
|
2019-11-18 11:41:37 -08:00
|
|
|
"sync"
|
2019-08-27 16:44:10 -07:00
|
|
|
"time"
|
2019-03-19 21:32:31 +02:00
|
|
|
|
2020-03-17 11:05:20 -07:00
|
|
|
"github.com/go-logr/logr"
|
2021-10-05 00:15:09 -07:00
|
|
|
kyvernoclient "github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
|
|
|
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1"
|
2020-10-07 11:12:31 -07:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
|
|
|
client "github.com/kyverno/kyverno/pkg/dclient"
|
2021-02-05 09:58:10 -08:00
|
|
|
"github.com/kyverno/kyverno/pkg/resourcecache"
|
2021-03-16 11:31:04 -07:00
|
|
|
"github.com/kyverno/kyverno/pkg/tls"
|
2022-01-05 15:47:42 +08:00
|
|
|
"github.com/kyverno/kyverno/pkg/utils"
|
2021-06-14 13:01:40 -07:00
|
|
|
"github.com/pkg/errors"
|
2021-10-05 00:15:09 -07:00
|
|
|
admregapi "k8s.io/api/admissionregistration/v1"
|
2021-03-30 16:46:01 -04:00
|
|
|
corev1 "k8s.io/api/core/v1"
|
2019-08-14 11:51:01 -07:00
|
|
|
errorsapi "k8s.io/apimachinery/pkg/api/errors"
|
2021-02-05 09:58:10 -08:00
|
|
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2021-03-16 11:31:04 -07:00
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
2021-03-30 16:46:01 -04:00
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
2019-03-21 18:14:26 +02:00
|
|
|
rest "k8s.io/client-go/rest"
|
2019-03-19 21:32:31 +02:00
|
|
|
)
|
|
|
|
|
2019-11-15 14:01:40 -08:00
|
|
|
const (
|
2020-11-26 16:07:06 -08:00
|
|
|
kindMutating string = "MutatingWebhookConfiguration"
|
|
|
|
kindValidating string = "ValidatingWebhookConfiguration"
|
2019-11-15 14:01:40 -08:00
|
|
|
)
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
// Register manages webhook registration. There are five webhooks:
|
|
|
|
// 1. Policy Validation
|
|
|
|
// 2. Policy Mutation
|
|
|
|
// 3. Resource Validation
|
|
|
|
// 4. Resource Mutation
|
|
|
|
// 5. Webhook Status Mutation
|
|
|
|
type Register struct {
|
2021-10-05 00:15:09 -07:00
|
|
|
client *client.Client
|
|
|
|
clientConfig *rest.Config
|
|
|
|
resCache resourcecache.ResourceCache
|
|
|
|
serverIP string // when running outside a cluster
|
|
|
|
timeoutSeconds int32
|
|
|
|
log logr.Logger
|
|
|
|
debug bool
|
|
|
|
autoUpdateWebhooks bool
|
|
|
|
|
|
|
|
UpdateWebhookChan chan bool
|
|
|
|
createDefaultWebhook chan string
|
|
|
|
|
|
|
|
// manage implements methods to manage webhook configurations
|
|
|
|
manage
|
2019-03-25 10:11:50 +02:00
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
// NewRegister creates new Register instance
|
|
|
|
func NewRegister(
|
2019-11-15 14:01:40 -08:00
|
|
|
clientConfig *rest.Config,
|
|
|
|
client *client.Client,
|
2021-10-05 00:15:09 -07:00
|
|
|
kyvernoClient *kyvernoclient.Clientset,
|
2021-02-05 09:58:10 -08:00
|
|
|
resCache resourcecache.ResourceCache,
|
2021-10-05 00:15:09 -07:00
|
|
|
pInformer kyvernoinformer.ClusterPolicyInformer,
|
|
|
|
npInformer kyvernoinformer.PolicyInformer,
|
2019-11-15 14:01:40 -08:00
|
|
|
serverIP string,
|
2020-03-17 11:05:20 -07:00
|
|
|
webhookTimeout int32,
|
2021-04-22 01:05:13 +05:30
|
|
|
debug bool,
|
2021-10-05 00:15:09 -07:00
|
|
|
autoUpdateWebhooks bool,
|
|
|
|
stopCh <-chan struct{},
|
2020-11-26 16:07:06 -08:00
|
|
|
log logr.Logger) *Register {
|
2021-10-05 00:15:09 -07:00
|
|
|
register := &Register{
|
|
|
|
clientConfig: clientConfig,
|
|
|
|
client: client,
|
|
|
|
resCache: resCache,
|
|
|
|
serverIP: serverIP,
|
|
|
|
timeoutSeconds: webhookTimeout,
|
|
|
|
log: log.WithName("Register"),
|
|
|
|
debug: debug,
|
|
|
|
autoUpdateWebhooks: autoUpdateWebhooks,
|
|
|
|
UpdateWebhookChan: make(chan bool),
|
|
|
|
createDefaultWebhook: make(chan string),
|
2019-11-15 14:01:40 -08:00
|
|
|
}
|
2021-10-05 00:15:09 -07:00
|
|
|
|
2021-11-09 12:09:19 +08:00
|
|
|
register.manage = newWebhookConfigManager(client, kyvernoClient, pInformer, npInformer, resCache, serverIP, register.autoUpdateWebhooks, register.createDefaultWebhook, stopCh, log.WithName("WebhookConfigManager"))
|
2021-10-05 00:15:09 -07:00
|
|
|
|
|
|
|
return register
|
2019-03-25 15:44:53 +02:00
|
|
|
}
|
2019-03-25 10:11:50 +02:00
|
|
|
|
2020-12-08 15:04:24 -08:00
|
|
|
// Register clean up the old webhooks and re-creates admission webhooks configs on cluster
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) Register() error {
|
|
|
|
logger := wrc.log
|
2019-06-10 18:10:51 -07:00
|
|
|
if wrc.serverIP != "" {
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("Registering webhook", "url", fmt.Sprintf("https://%s", wrc.serverIP))
|
2019-06-10 18:10:51 -07:00
|
|
|
}
|
2021-04-22 01:05:13 +05:30
|
|
|
if !wrc.debug {
|
|
|
|
if err := wrc.checkEndpoint(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-03-30 16:46:01 -04:00
|
|
|
}
|
2020-12-08 15:04:24 -08:00
|
|
|
wrc.removeWebhookConfigurations()
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
caData := wrc.readCaData()
|
|
|
|
if caData == nil {
|
|
|
|
return errors.New("Unable to extract CA data from configuration")
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
errors := make([]string, 0)
|
2021-03-16 11:31:04 -07:00
|
|
|
if err := wrc.createVerifyMutatingWebhookConfiguration(caData); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
errors = append(errors, err.Error())
|
2019-11-25 18:22:05 -08:00
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
if err := wrc.createPolicyValidatingWebhookConfiguration(caData); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
errors = append(errors, err.Error())
|
2019-05-14 18:10:25 +03:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
if err := wrc.createPolicyMutatingWebhookConfiguration(caData); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
errors = append(errors, err.Error())
|
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
if err := wrc.createResourceValidatingWebhookConfiguration(caData); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
errors = append(errors, err.Error())
|
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
if err := wrc.createResourceMutatingWebhookConfiguration(caData); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
errors = append(errors, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(errors) > 0 {
|
|
|
|
return fmt.Errorf("%s", strings.Join(errors, ","))
|
|
|
|
}
|
|
|
|
|
2021-10-07 13:50:30 -07:00
|
|
|
go wrc.manage.start()
|
2020-11-26 16:07:06 -08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-02-05 09:58:10 -08:00
|
|
|
// Check returns an error if any of the webhooks are not configured
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) Check() error {
|
2021-02-05 09:58:10 -08:00
|
|
|
mutatingCache, _ := wrc.resCache.GetGVRCache(kindMutating)
|
|
|
|
validatingCache, _ := wrc.resCache.GetGVRCache(kindValidating)
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2021-02-05 09:58:10 -08:00
|
|
|
if _, err := mutatingCache.Lister().Get(wrc.getVerifyWebhookMutatingWebhookName()); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
if _, err := mutatingCache.Lister().Get(getResourceMutatingWebhookConfigName(wrc.serverIP)); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
if _, err := validatingCache.Lister().Get(getResourceValidatingWebhookConfigName(wrc.serverIP)); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
if _, err := mutatingCache.Lister().Get(getPolicyMutatingWebhookConfigurationName(wrc.serverIP)); err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
if _, err := validatingCache.Lister().Get(getPolicyValidatingWebhookConfigurationName(wrc.serverIP)); err != nil {
|
2019-03-25 15:44:53 +02:00
|
|
|
return err
|
2019-03-19 21:32:31 +02:00
|
|
|
}
|
2019-10-30 13:39:19 -07:00
|
|
|
|
2019-08-07 18:01:28 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
// Remove removes all webhook configurations
|
|
|
|
func (wrc *Register) Remove(cleanUp chan<- struct{}) {
|
2021-03-16 11:31:04 -07:00
|
|
|
defer close(cleanUp)
|
|
|
|
if !wrc.cleanupKyvernoResource() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-08-27 16:44:10 -07:00
|
|
|
wrc.removeWebhookConfigurations()
|
2021-03-16 11:31:04 -07:00
|
|
|
wrc.removeSecrets()
|
2021-10-07 04:42:07 +05:30
|
|
|
err := wrc.client.DeleteResource("coordination.k8s.io/v1", "Lease", config.KyvernoNamespace, "kyvernopre-lock", false)
|
|
|
|
if err != nil && errorsapi.IsNotFound(err) {
|
|
|
|
wrc.log.WithName("cleanup").Error(err, "failed to clean up Lease lock")
|
|
|
|
}
|
|
|
|
|
2019-08-27 16:44:10 -07:00
|
|
|
}
|
|
|
|
|
2021-06-14 13:01:40 -07:00
|
|
|
// UpdateWebhookConfigurations updates resource webhook configurations dynamically
|
2022-01-07 16:22:34 +05:30
|
|
|
// based on the UPDATEs of Kyverno ConfigMap defined in INIT_CONFIG env
|
2021-06-14 13:01:40 -07:00
|
|
|
//
|
2021-10-05 00:15:09 -07:00
|
|
|
// it currently updates namespaceSelector only, can be extend to update other fields
|
2021-10-29 16:06:03 +01:00
|
|
|
// +deprecated
|
2021-06-14 13:01:40 -07:00
|
|
|
func (wrc *Register) UpdateWebhookConfigurations(configHandler config.Interface) {
|
|
|
|
logger := wrc.log.WithName("UpdateWebhookConfigurations")
|
|
|
|
for {
|
|
|
|
<-wrc.UpdateWebhookChan
|
|
|
|
logger.Info("received the signal to update webhook configurations")
|
|
|
|
|
|
|
|
var nsSelector map[string]interface{}
|
|
|
|
webhookCfgs := configHandler.GetWebhooks()
|
|
|
|
if webhookCfgs != nil {
|
|
|
|
selector := webhookCfgs[0].NamespaceSelector
|
|
|
|
selectorBytes, err := json.Marshal(*selector)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to serialize namespaceSelector")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = json.Unmarshal(selectorBytes, &nsSelector); err != nil {
|
|
|
|
logger.Error(err, "failed to convert namespaceSelector to the map")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := wrc.updateResourceMutatingWebhookConfiguration(nsSelector); err != nil {
|
2021-10-05 00:15:09 -07:00
|
|
|
logger.Error(err, "unable to update mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
|
2021-06-16 23:29:07 -07:00
|
|
|
go func() { wrc.UpdateWebhookChan <- true }()
|
2021-06-14 13:01:40 -07:00
|
|
|
} else {
|
2021-10-05 00:15:09 -07:00
|
|
|
logger.Info("successfully updated mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
|
2021-06-14 13:01:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := wrc.updateResourceValidatingWebhookConfiguration(nsSelector); err != nil {
|
2021-10-05 00:15:09 -07:00
|
|
|
logger.Error(err, "unable to update validatingWebhookConfigurations", "name", getResourceValidatingWebhookConfigName(wrc.serverIP))
|
2021-06-16 23:29:07 -07:00
|
|
|
go func() { wrc.UpdateWebhookChan <- true }()
|
2021-06-14 13:01:40 -07:00
|
|
|
} else {
|
2021-10-05 00:15:09 -07:00
|
|
|
logger.Info("successfully updated validatingWebhookConfigurations", "name", getResourceValidatingWebhookConfigName(wrc.serverIP))
|
2021-06-14 13:01:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) ValidateWebhookConfigurations(namespace, name string) error {
|
|
|
|
logger := wrc.log.WithName("ValidateWebhookConfigurations")
|
|
|
|
|
|
|
|
cm, err := wrc.client.GetResource("", "ConfigMap", namespace, name)
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "unable to fetch ConfigMap", "namespace", namespace, "name", name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
webhooks, ok, err := unstructured.NestedString(cm.UnstructuredContent(), "data", "webhooks")
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to fetch tag 'webhooks' from the ConfigMap")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
logger.V(4).Info("webhook configurations not defined")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
webhookCfgs := make([]config.WebhookConfig, 0, 10)
|
|
|
|
return json.Unmarshal([]byte(webhooks), &webhookCfgs)
|
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
// cleanupKyvernoResource returns true if Kyverno deployment is terminating
|
|
|
|
func (wrc *Register) cleanupKyvernoResource() bool {
|
|
|
|
logger := wrc.log.WithName("cleanupKyvernoResource")
|
|
|
|
deploy, err := wrc.client.GetResource("", "Deployment", deployNamespace, deployName)
|
|
|
|
if err != nil {
|
2022-01-06 14:41:16 +05:30
|
|
|
logger.Error(err, "failed to get deployment, not cleaning up kyverno resources")
|
|
|
|
return false
|
2021-03-16 11:31:04 -07:00
|
|
|
}
|
|
|
|
if deploy.GetDeletionTimestamp() != nil {
|
2021-03-25 12:28:03 -07:00
|
|
|
logger.Info("Kyverno is terminating, cleanup Kyverno resources")
|
2021-03-16 11:31:04 -07:00
|
|
|
return true
|
|
|
|
}
|
2019-05-14 18:10:25 +03:00
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
replicas, _, err := unstructured.NestedInt64(deploy.UnstructuredContent(), "spec", "replicas")
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "unable to fetch spec.replicas of Kyverno deployment")
|
2019-03-19 21:32:31 +02:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
if replicas == 0 {
|
2021-03-25 12:28:03 -07:00
|
|
|
logger.Info("Kyverno is scaled to zero, cleanup Kyverno resources")
|
2021-03-16 11:31:04 -07:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.Info("updating Kyverno Pod, won't clean up Kyverno resources")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) createResourceMutatingWebhookConfiguration(caData []byte) error {
|
|
|
|
var config *admregapi.MutatingWebhookConfiguration
|
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
if wrc.serverIP != "" {
|
2021-06-14 13:01:40 -07:00
|
|
|
config = wrc.constructDefaultDebugMutatingWebhookConfig(caData)
|
2019-08-27 14:52:56 -07:00
|
|
|
} else {
|
2021-06-14 13:01:40 -07:00
|
|
|
config = wrc.constructDefaultMutatingWebhookConfig(caData)
|
2019-07-02 18:42:07 -07:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
|
|
|
logger := wrc.log.WithValues("kind", kindMutating, "name", config.Name)
|
|
|
|
|
|
|
|
_, err := wrc.client.CreateResource("", kindMutating, "", *config, false)
|
2019-09-04 13:43:12 -07:00
|
|
|
if errorsapi.IsAlreadyExists(err) {
|
2020-05-18 21:16:48 -07:00
|
|
|
logger.V(6).Info("resource mutating webhook configuration already exists", "name", config.Name)
|
2019-09-04 13:43:12 -07:00
|
|
|
return nil
|
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2019-09-04 13:43:12 -07:00
|
|
|
if err != nil {
|
2020-03-17 11:05:20 -07:00
|
|
|
logger.Error(err, "failed to create resource mutating webhook configuration", "name", config.Name)
|
2019-07-02 18:42:07 -07:00
|
|
|
return err
|
|
|
|
}
|
2020-11-03 16:07:02 -08:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("created webhook")
|
2019-03-25 15:44:53 +02:00
|
|
|
return nil
|
2019-03-25 10:11:50 +02:00
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
func (wrc *Register) createResourceValidatingWebhookConfiguration(caData []byte) error {
|
2020-01-11 18:33:11 +05:30
|
|
|
var config *admregapi.ValidatingWebhookConfiguration
|
|
|
|
|
|
|
|
if wrc.serverIP != "" {
|
2021-06-14 13:01:40 -07:00
|
|
|
config = wrc.constructDefaultDebugValidatingWebhookConfig(caData)
|
2020-01-11 18:33:11 +05:30
|
|
|
} else {
|
2021-06-14 13:01:40 -07:00
|
|
|
config = wrc.constructDefaultValidatingWebhookConfig(caData)
|
2020-01-11 18:33:11 +05:30
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger := wrc.log.WithValues("kind", kindValidating, "name", config.Name)
|
|
|
|
|
|
|
|
_, err := wrc.client.CreateResource("", kindValidating, "", *config, false)
|
2020-01-11 18:33:11 +05:30
|
|
|
if errorsapi.IsAlreadyExists(err) {
|
2020-05-18 21:16:48 -07:00
|
|
|
logger.V(6).Info("resource validating webhook configuration already exists", "name", config.Name)
|
2020-01-11 18:33:11 +05:30
|
|
|
return nil
|
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2020-01-11 18:33:11 +05:30
|
|
|
if err != nil {
|
2020-03-17 11:05:20 -07:00
|
|
|
logger.Error(err, "failed to create resource")
|
2020-01-11 18:33:11 +05:30
|
|
|
return err
|
|
|
|
}
|
2020-11-03 16:07:02 -08:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("created webhook")
|
2020-01-11 18:33:11 +05:30
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
//registerPolicyValidatingWebhookConfiguration create a Validating webhook configuration for Policy CRD
|
2021-03-16 11:31:04 -07:00
|
|
|
func (wrc *Register) createPolicyValidatingWebhookConfiguration(caData []byte) error {
|
2019-08-27 14:52:56 -07:00
|
|
|
var config *admregapi.ValidatingWebhookConfiguration
|
2019-06-10 18:10:51 -07:00
|
|
|
|
2019-08-08 13:09:40 -07:00
|
|
|
if wrc.serverIP != "" {
|
2021-10-05 00:15:09 -07:00
|
|
|
config = wrc.constructDebugPolicyValidatingWebhookConfig(caData)
|
2019-08-27 14:52:56 -07:00
|
|
|
} else {
|
2021-10-05 00:15:09 -07:00
|
|
|
config = wrc.constructPolicyValidatingWebhookConfig(caData)
|
2019-08-08 13:09:40 -07:00
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
if _, err := wrc.client.CreateResource("", kindValidating, "", *config, false); err != nil {
|
|
|
|
if errorsapi.IsAlreadyExists(err) {
|
|
|
|
wrc.log.V(6).Info("webhook already exists", "kind", kindValidating, "name", config.Name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
return err
|
2019-08-07 18:01:28 -07:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
|
|
|
wrc.log.Info("created webhook", "kind", kindValidating, "name", config.Name)
|
2019-08-27 14:52:56 -07:00
|
|
|
return nil
|
2019-03-19 21:32:31 +02:00
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
func (wrc *Register) createPolicyMutatingWebhookConfiguration(caData []byte) error {
|
2019-08-27 14:52:56 -07:00
|
|
|
var config *admregapi.MutatingWebhookConfiguration
|
2020-11-26 16:07:06 -08:00
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
if wrc.serverIP != "" {
|
2021-10-05 00:15:09 -07:00
|
|
|
config = wrc.constructDebugPolicyMutatingWebhookConfig(caData)
|
2019-08-27 14:52:56 -07:00
|
|
|
} else {
|
2021-10-05 00:15:09 -07:00
|
|
|
config = wrc.constructPolicyMutatingWebhookConfig(caData)
|
2019-03-25 15:44:53 +02:00
|
|
|
}
|
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
// create mutating webhook configuration resource
|
2020-11-26 16:07:06 -08:00
|
|
|
if _, err := wrc.client.CreateResource("", kindMutating, "", *config, false); err != nil {
|
|
|
|
if errorsapi.IsAlreadyExists(err) {
|
|
|
|
wrc.log.V(6).Info("webhook already exists", "kind", kindMutating, "name", config.Name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-27 14:52:56 -07:00
|
|
|
return err
|
2019-06-10 18:10:51 -07:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
|
|
|
wrc.log.Info("created webhook", "kind", kindMutating, "name", config.Name)
|
2019-08-27 14:52:56 -07:00
|
|
|
return nil
|
2019-05-14 18:10:25 +03:00
|
|
|
}
|
|
|
|
|
2021-03-16 11:31:04 -07:00
|
|
|
func (wrc *Register) createVerifyMutatingWebhookConfiguration(caData []byte) error {
|
2019-10-30 13:39:19 -07:00
|
|
|
var config *admregapi.MutatingWebhookConfiguration
|
|
|
|
|
|
|
|
if wrc.serverIP != "" {
|
|
|
|
config = wrc.constructDebugVerifyMutatingWebhookConfig(caData)
|
|
|
|
} else {
|
|
|
|
config = wrc.constructVerifyMutatingWebhookConfig(caData)
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
if _, err := wrc.client.CreateResource("", kindMutating, "", *config, false); err != nil {
|
|
|
|
if errorsapi.IsAlreadyExists(err) {
|
|
|
|
wrc.log.V(6).Info("webhook already exists", "kind", kindMutating, "name", config.Name)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-30 13:39:19 -07:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
wrc.log.Info("created webhook", "kind", kindMutating, "name", config.Name)
|
2019-10-30 13:39:19 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) removeWebhookConfigurations() {
|
2019-08-27 16:44:10 -07:00
|
|
|
startTime := time.Now()
|
2021-06-08 12:37:19 -07:00
|
|
|
wrc.log.V(3).Info("deleting all webhook configurations")
|
2019-08-27 16:44:10 -07:00
|
|
|
defer func() {
|
2020-11-26 16:07:06 -08:00
|
|
|
wrc.log.V(4).Info("removed webhook configurations", "processingTime", time.Since(startTime).String())
|
2019-08-27 16:44:10 -07:00
|
|
|
}()
|
2019-11-18 11:41:37 -08:00
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
2020-01-11 18:33:11 +05:30
|
|
|
wg.Add(5)
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2019-11-18 11:41:37 -08:00
|
|
|
go wrc.removeResourceMutatingWebhookConfiguration(&wg)
|
2020-01-11 18:33:11 +05:30
|
|
|
go wrc.removeResourceValidatingWebhookConfiguration(&wg)
|
2019-11-18 11:41:37 -08:00
|
|
|
go wrc.removePolicyMutatingWebhookConfiguration(&wg)
|
|
|
|
go wrc.removePolicyValidatingWebhookConfiguration(&wg)
|
2019-11-25 13:07:36 -08:00
|
|
|
go wrc.removeVerifyWebhookMutatingWebhookConfig(&wg)
|
2019-11-18 11:41:37 -08:00
|
|
|
|
|
|
|
wg.Wait()
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) removePolicyMutatingWebhookConfiguration(wg *sync.WaitGroup) {
|
2020-01-11 18:33:11 +05:30
|
|
|
defer wg.Done()
|
2019-08-27 14:52:56 -07:00
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
mutatingConfig := getPolicyMutatingWebhookConfigurationName(wrc.serverIP)
|
2020-11-26 16:07:06 -08:00
|
|
|
|
|
|
|
logger := wrc.log.WithValues("kind", kindMutating, "name", mutatingConfig)
|
2021-04-12 20:29:51 -07:00
|
|
|
|
|
|
|
if mutateCache, ok := wrc.resCache.GetGVRCache("MutatingWebhookConfiguration"); ok {
|
|
|
|
if _, err := mutateCache.Lister().Get(mutatingConfig); err != nil && errorsapi.IsNotFound(err) {
|
|
|
|
logger.V(4).Info("webhook not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
err := wrc.client.DeleteResource("", kindMutating, "", mutatingConfig, false)
|
|
|
|
if errorsapi.IsNotFound(err) {
|
|
|
|
logger.V(5).Info("policy mutating webhook configuration not found")
|
|
|
|
return
|
2020-12-04 10:04:46 -08:00
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logger.Error(err, "failed to delete policy mutating webhook configuration")
|
|
|
|
return
|
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("webhook configuration deleted")
|
|
|
|
}
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
func getPolicyMutatingWebhookConfigurationName(serverIP string) string {
|
2019-11-18 11:41:37 -08:00
|
|
|
var mutatingConfig string
|
2021-10-05 00:15:09 -07:00
|
|
|
if serverIP != "" {
|
2019-11-18 11:41:37 -08:00
|
|
|
mutatingConfig = config.PolicyMutatingWebhookConfigurationDebugName
|
|
|
|
} else {
|
|
|
|
mutatingConfig = config.PolicyMutatingWebhookConfigurationName
|
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
return mutatingConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) removePolicyValidatingWebhookConfiguration(wg *sync.WaitGroup) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
validatingConfig := getPolicyValidatingWebhookConfigurationName(wrc.serverIP)
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger := wrc.log.WithValues("kind", kindValidating, "name", validatingConfig)
|
2021-04-12 20:29:51 -07:00
|
|
|
if mutateCache, ok := wrc.resCache.GetGVRCache("ValidatingWebhookConfiguration"); ok {
|
|
|
|
if _, err := mutateCache.Lister().Get(validatingConfig); err != nil && errorsapi.IsNotFound(err) {
|
|
|
|
logger.V(4).Info("webhook not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.V(4).Info("removing validating webhook configuration")
|
|
|
|
err := wrc.client.DeleteResource("", kindValidating, "", validatingConfig, false)
|
2019-11-18 11:41:37 -08:00
|
|
|
if errorsapi.IsNotFound(err) {
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.V(5).Info("policy validating webhook configuration not found")
|
2020-05-17 14:37:05 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Error(err, "failed to delete policy validating webhook configuration")
|
2020-05-17 14:37:05 -07:00
|
|
|
return
|
2019-11-18 11:41:37 -08:00
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("webhook configuration deleted")
|
2019-11-18 11:41:37 -08:00
|
|
|
}
|
2019-06-10 18:10:51 -07:00
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
func getPolicyValidatingWebhookConfigurationName(serverIP string) string {
|
2019-11-18 11:41:37 -08:00
|
|
|
var validatingConfig string
|
2021-10-05 00:15:09 -07:00
|
|
|
if serverIP != "" {
|
2019-11-18 11:41:37 -08:00
|
|
|
validatingConfig = config.PolicyValidatingWebhookConfigurationDebugName
|
|
|
|
} else {
|
|
|
|
validatingConfig = config.PolicyValidatingWebhookConfigurationName
|
|
|
|
}
|
2020-11-26 16:07:06 -08:00
|
|
|
return validatingConfig
|
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) constructVerifyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration {
|
|
|
|
return &admregapi.MutatingWebhookConfiguration{
|
|
|
|
ObjectMeta: v1.ObjectMeta{
|
|
|
|
Name: config.VerifyMutatingWebhookConfigurationName,
|
2021-08-14 05:37:40 +05:30
|
|
|
OwnerReferences: []v1.OwnerReference{
|
|
|
|
wrc.constructOwner(),
|
|
|
|
},
|
2020-11-26 16:07:06 -08:00
|
|
|
},
|
|
|
|
Webhooks: []admregapi.MutatingWebhook{
|
|
|
|
generateMutatingWebhook(
|
|
|
|
config.VerifyMutatingWebhookName,
|
|
|
|
config.VerifyMutatingWebhookServicePath,
|
|
|
|
caData,
|
|
|
|
true,
|
|
|
|
wrc.timeoutSeconds,
|
2021-10-05 00:15:09 -07:00
|
|
|
admregapi.Rule{
|
|
|
|
Resources: []string{"deployments/*"},
|
|
|
|
APIGroups: []string{"apps"},
|
|
|
|
APIVersions: []string{"v1"},
|
|
|
|
},
|
2020-11-26 16:07:06 -08:00
|
|
|
[]admregapi.OperationType{admregapi.Update},
|
2021-10-05 00:15:09 -07:00
|
|
|
admregapi.Ignore,
|
2020-11-26 16:07:06 -08:00
|
|
|
),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) constructDebugVerifyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration {
|
|
|
|
logger := wrc.log
|
|
|
|
url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.VerifyMutatingWebhookServicePath)
|
|
|
|
logger.V(4).Info("Debug VerifyMutatingWebhookConfig is registered with url", "url", url)
|
|
|
|
return &admregapi.MutatingWebhookConfiguration{
|
|
|
|
ObjectMeta: v1.ObjectMeta{
|
|
|
|
Name: config.VerifyMutatingWebhookConfigurationDebugName,
|
|
|
|
},
|
|
|
|
Webhooks: []admregapi.MutatingWebhook{
|
|
|
|
generateDebugMutatingWebhook(
|
|
|
|
config.VerifyMutatingWebhookName,
|
|
|
|
url,
|
|
|
|
caData,
|
|
|
|
true,
|
|
|
|
wrc.timeoutSeconds,
|
2021-10-05 00:15:09 -07:00
|
|
|
admregapi.Rule{
|
|
|
|
Resources: []string{"deployments/*"},
|
|
|
|
APIGroups: []string{"apps"},
|
|
|
|
APIVersions: []string{"v1"},
|
|
|
|
},
|
2020-11-26 16:07:06 -08:00
|
|
|
[]admregapi.OperationType{admregapi.Update},
|
2021-10-05 00:15:09 -07:00
|
|
|
admregapi.Ignore,
|
2020-11-26 16:07:06 -08:00
|
|
|
),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) removeVerifyWebhookMutatingWebhookConfig(wg *sync.WaitGroup) {
|
|
|
|
defer wg.Done()
|
|
|
|
|
|
|
|
var err error
|
|
|
|
mutatingConfig := wrc.getVerifyWebhookMutatingWebhookName()
|
|
|
|
logger := wrc.log.WithValues("kind", kindMutating, "name", mutatingConfig)
|
2021-04-12 20:29:51 -07:00
|
|
|
|
|
|
|
if mutateCache, ok := wrc.resCache.GetGVRCache("MutatingWebhookConfiguration"); ok {
|
|
|
|
if _, err := mutateCache.Lister().Get(mutatingConfig); err != nil && errorsapi.IsNotFound(err) {
|
|
|
|
logger.V(4).Info("webhook not found")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
err = wrc.client.DeleteResource("", kindMutating, "", mutatingConfig, false)
|
2019-11-18 11:41:37 -08:00
|
|
|
if errorsapi.IsNotFound(err) {
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.V(5).Info("verify webhook configuration not found")
|
2020-05-17 14:37:05 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Error(err, "failed to delete verify webhook configuration")
|
2020-05-17 14:37:05 -07:00
|
|
|
return
|
2019-11-18 11:41:37 -08:00
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
logger.Info("webhook configuration deleted")
|
2019-05-14 18:10:25 +03:00
|
|
|
}
|
2020-05-18 17:00:52 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) getVerifyWebhookMutatingWebhookName() string {
|
|
|
|
var mutatingConfig string
|
|
|
|
if wrc.serverIP != "" {
|
|
|
|
mutatingConfig = config.VerifyMutatingWebhookConfigurationDebugName
|
|
|
|
} else {
|
|
|
|
mutatingConfig = config.VerifyMutatingWebhookConfigurationName
|
|
|
|
}
|
|
|
|
return mutatingConfig
|
|
|
|
}
|
|
|
|
|
2020-05-18 17:00:52 -07:00
|
|
|
// GetWebhookTimeOut returns the value of webhook timeout
|
2020-11-26 16:07:06 -08:00
|
|
|
func (wrc *Register) GetWebhookTimeOut() time.Duration {
|
2020-05-18 17:00:52 -07:00
|
|
|
return time.Duration(wrc.timeoutSeconds)
|
|
|
|
}
|
2021-03-16 11:31:04 -07:00
|
|
|
|
|
|
|
// removeSecrets removes Kyverno managed secrets
|
|
|
|
func (wrc *Register) removeSecrets() {
|
|
|
|
selector := &v1.LabelSelector{
|
|
|
|
MatchLabels: map[string]string{
|
|
|
|
tls.ManagedByLabel: "kyverno",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
secretList, err := wrc.client.ListResource("", "Secret", config.KyvernoNamespace, selector)
|
2021-04-12 20:29:51 -07:00
|
|
|
if err != nil {
|
2021-03-16 11:31:04 -07:00
|
|
|
wrc.log.Error(err, "failed to clean up Kyverno managed secrets")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, secret := range secretList.Items {
|
|
|
|
if err := wrc.client.DeleteResource("", "Secret", secret.GetNamespace(), secret.GetName(), false); err != nil {
|
2021-06-08 12:37:19 -07:00
|
|
|
if !errorsapi.IsNotFound(err) {
|
|
|
|
wrc.log.Error(err, "failed to delete secret", "ns", secret.GetNamespace(), "name", secret.GetName())
|
|
|
|
}
|
2021-03-16 11:31:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-03-30 16:46:01 -04:00
|
|
|
|
|
|
|
func (wrc *Register) checkEndpoint() error {
|
|
|
|
obj, err := wrc.client.GetResource("", "Endpoints", config.KyvernoNamespace, config.KyvernoServiceName)
|
|
|
|
if err != nil {
|
2021-04-12 20:29:51 -07:00
|
|
|
return fmt.Errorf("failed to get endpoint %s/%s: %v", config.KyvernoNamespace, config.KyvernoServiceName, err)
|
2021-03-30 16:46:01 -04:00
|
|
|
}
|
|
|
|
var endpoint corev1.Endpoints
|
|
|
|
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), &endpoint)
|
|
|
|
if err != nil {
|
2021-04-12 20:29:51 -07:00
|
|
|
return fmt.Errorf("failed to convert endpoint %s/%s from unstructured: %v", config.KyvernoNamespace, config.KyvernoServiceName, err)
|
2021-03-30 16:46:01 -04:00
|
|
|
}
|
2021-04-12 20:29:51 -07:00
|
|
|
|
|
|
|
pods, err := wrc.client.ListResource("", "Pod", config.KyvernoNamespace, &v1.LabelSelector{MatchLabels: map[string]string{"app.kubernetes.io/name": "kyverno"}})
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to list Kyverno Pod: %v", err)
|
|
|
|
}
|
|
|
|
|
2022-01-05 15:47:42 +08:00
|
|
|
ips, errs := getHealthyPodsIP(pods.Items)
|
|
|
|
if len(errs) != 0 {
|
|
|
|
return fmt.Errorf("error getting pod's IP: %v", errs)
|
2021-04-12 20:29:51 -07:00
|
|
|
}
|
|
|
|
|
2022-01-05 15:47:42 +08:00
|
|
|
if len(ips) == 0 {
|
2021-10-05 00:15:09 -07:00
|
|
|
return fmt.Errorf("pod is not assigned to any node yet")
|
2021-04-12 20:29:51 -07:00
|
|
|
}
|
|
|
|
|
2021-03-30 16:46:01 -04:00
|
|
|
for _, subset := range endpoint.Subsets {
|
|
|
|
if len(subset.Addresses) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2021-04-12 20:29:51 -07:00
|
|
|
|
|
|
|
for _, addr := range subset.Addresses {
|
2022-01-05 15:47:42 +08:00
|
|
|
if utils.ContainsString(ips, addr.IP) {
|
2021-04-12 20:29:51 -07:00
|
|
|
wrc.log.Info("Endpoint ready", "ns", config.KyvernoNamespace, "name", config.KyvernoServiceName)
|
|
|
|
return nil
|
|
|
|
}
|
2021-03-30 16:46:01 -04:00
|
|
|
}
|
|
|
|
}
|
2021-04-12 20:29:51 -07:00
|
|
|
|
|
|
|
// clean up old webhook configurations, if any
|
|
|
|
wrc.removeWebhookConfigurations()
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
err = fmt.Errorf("endpoint not ready")
|
2021-03-31 13:24:36 -07:00
|
|
|
wrc.log.V(3).Info(err.Error(), "ns", config.KyvernoNamespace, "name", config.KyvernoServiceName)
|
2021-03-30 16:46:01 -04:00
|
|
|
return err
|
|
|
|
}
|
2021-06-14 13:01:40 -07:00
|
|
|
|
2022-01-05 15:47:42 +08:00
|
|
|
func getHealthyPodsIP(pods []unstructured.Unstructured) (ips []string, errs []error) {
|
|
|
|
for _, pod := range pods {
|
|
|
|
phase, _, err := unstructured.NestedString(pod.UnstructuredContent(), "status", "phase")
|
|
|
|
if err != nil {
|
|
|
|
errs = append(errs, fmt.Errorf("failed to get pod %s status: %v", pod.GetName(), err))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if phase != "Running" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
ip, _, err := unstructured.NestedString(pod.UnstructuredContent(), "status", "podIP")
|
|
|
|
if err != nil {
|
|
|
|
errs = append(errs, fmt.Errorf("failed to extract pod %s IP: %v", pod.GetName(), err))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
ips = append(ips, ip)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-06-14 13:01:40 -07:00
|
|
|
func (wrc *Register) updateResourceValidatingWebhookConfiguration(nsSelector map[string]interface{}) error {
|
|
|
|
validatingCache, _ := wrc.resCache.GetGVRCache(kindValidating)
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
resourceValidating, err := validatingCache.Lister().Get(getResourceValidatingWebhookConfigName(wrc.serverIP))
|
2021-06-14 13:01:40 -07:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to get validatingWebhookConfigurations")
|
|
|
|
}
|
|
|
|
|
|
|
|
webhooksUntyped, _, err := unstructured.NestedSlice(resourceValidating.UnstructuredContent(), "webhooks")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to load validatingWebhookConfigurations.webhooks")
|
|
|
|
}
|
|
|
|
|
|
|
|
var webhooks map[string]interface{}
|
|
|
|
var ok bool
|
|
|
|
if webhooksUntyped != nil {
|
|
|
|
webhooks, ok = webhooksUntyped[0].(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err = unstructured.SetNestedMap(webhooks, nsSelector, "namespaceSelector"); err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to set validatingWebhookConfigurations.webhooks[0].namespaceSelector")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = unstructured.SetNestedSlice(resourceValidating.UnstructuredContent(), []interface{}{webhooks}, "webhooks"); err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to set validatingWebhookConfigurations.webhooks")
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := wrc.client.UpdateResource(resourceValidating.GetAPIVersion(), resourceValidating.GetKind(), "", resourceValidating, false); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (wrc *Register) updateResourceMutatingWebhookConfiguration(nsSelector map[string]interface{}) error {
|
|
|
|
mutatingCache, _ := wrc.resCache.GetGVRCache(kindMutating)
|
|
|
|
|
2021-10-05 00:15:09 -07:00
|
|
|
resourceMutating, err := mutatingCache.Lister().Get(getResourceMutatingWebhookConfigName(wrc.serverIP))
|
2021-06-14 13:01:40 -07:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to get mutatingWebhookConfigurations")
|
|
|
|
}
|
|
|
|
|
|
|
|
webhooksUntyped, _, err := unstructured.NestedSlice(resourceMutating.UnstructuredContent(), "webhooks")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to load mutatingWebhookConfigurations.webhooks")
|
|
|
|
}
|
|
|
|
|
|
|
|
var webhooks map[string]interface{}
|
|
|
|
var ok bool
|
|
|
|
if webhooksUntyped != nil {
|
|
|
|
webhooks, ok = webhooksUntyped[0].(map[string]interface{})
|
|
|
|
if !ok {
|
|
|
|
return errors.Wrapf(err, "type mismatched, expected map[string]interface{}, got %T", webhooksUntyped[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err = unstructured.SetNestedMap(webhooks, nsSelector, "namespaceSelector"); err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to set mutatingWebhookConfigurations.webhooks[0].namespaceSelector")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = unstructured.SetNestedSlice(resourceMutating.UnstructuredContent(), []interface{}{webhooks}, "webhooks"); err != nil {
|
|
|
|
return errors.Wrapf(err, "unable to set mutatingWebhookConfigurations.webhooks")
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := wrc.client.UpdateResource(resourceMutating.GetAPIVersion(), resourceMutating.GetKind(), "", resourceMutating, false); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|