github.com/verrazzano/verrazzano@v1.7.0/application-operator/internal/operatorinit/run_webhook.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package operatorinit
     5  
     6  import (
     7  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
     8  	"github.com/verrazzano/verrazzano/application-operator/controllers/webhooks"
     9  	"github.com/verrazzano/verrazzano/application-operator/internal/certificates"
    10  	"github.com/verrazzano/verrazzano/pkg/k8sutil"
    11  	"go.uber.org/zap"
    12  	istioversionedclient "istio.io/client-go/pkg/clientset/versioned"
    13  	"k8s.io/apimachinery/pkg/runtime"
    14  	"k8s.io/client-go/dynamic"
    15  	"k8s.io/client-go/kubernetes"
    16  	ctrl "sigs.k8s.io/controller-runtime"
    17  	"sigs.k8s.io/controller-runtime/pkg/webhook"
    18  )
    19  
    20  const (
    21  	failedToUpdate = "Failed to update %s: %v"
    22  )
    23  
    24  // WebhookInit Webhook init container entry point
    25  func WebhookInit(certDir string, log *zap.SugaredLogger) error {
    26  	log.Debug("Creating certificates used by webhooks")
    27  
    28  	conf, err := k8sutil.GetConfigFromController()
    29  	if err != nil {
    30  		log.Errorf("Failed to get config: %v", err)
    31  		return err
    32  	}
    33  
    34  	kubeClient, err := kubernetes.NewForConfig(conf)
    35  	if err != nil {
    36  		log.Errorf("Failed to get kubernetes client: %v", err)
    37  		return err
    38  	}
    39  
    40  	// Create the webhook certificates and secrets
    41  	if err := certificates.CreateWebhookCertificates(log, kubeClient, certDir); err != nil {
    42  		log.Errorf("Failed to create webhook certificates and secrets: %v", err)
    43  		return err
    44  	}
    45  	return nil
    46  }
    47  
    48  func StartWebhookServer(metricsAddr string, log *zap.SugaredLogger, enableLeaderElection bool, certDir string, scheme *runtime.Scheme) error {
    49  	config, err := k8sutil.GetConfigFromController()
    50  	if err != nil {
    51  		log.Errorf("Failed to get kubeconfig: %v", err)
    52  		return err
    53  	}
    54  
    55  	mgr, err := ctrl.NewManager(config, ctrl.Options{
    56  		Scheme:             scheme,
    57  		MetricsBindAddress: metricsAddr,
    58  		Port:               9443,
    59  		LeaderElection:     enableLeaderElection,
    60  		LeaderElectionID:   "5df248b4.verrazzano.io",
    61  	})
    62  	if err != nil {
    63  		log.Errorf("Failed to start manager: %v", err)
    64  		return err
    65  	}
    66  
    67  	kubeClient, err := kubernetes.NewForConfig(config)
    68  	if err != nil {
    69  		log.Errorf("Failed to get clientset", err)
    70  		return err
    71  	}
    72  
    73  	log.Debug("Setting up certificates for webhook")
    74  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.IngressTraitValidatingWebhookName)
    75  	if err != nil {
    76  		log.Errorf(failedToUpdate, certificates.IngressTraitValidatingWebhookName, err)
    77  		return err
    78  	}
    79  
    80  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.MultiClusterSecretName)
    81  	if err != nil {
    82  		log.Errorf(failedToUpdate, certificates.MultiClusterSecretName, err)
    83  		return err
    84  	}
    85  
    86  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.MultiClusterComponentName)
    87  	if err != nil {
    88  		log.Errorf(failedToUpdate, certificates.MultiClusterComponentName, err)
    89  		return err
    90  	}
    91  
    92  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.MultiClusterConfigMapName)
    93  	if err != nil {
    94  		log.Errorf(failedToUpdate, certificates.MultiClusterConfigMapName, err)
    95  		return err
    96  	}
    97  
    98  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.MultiClusterApplicationConfigurationName)
    99  	if err != nil {
   100  		log.Errorf(failedToUpdate, certificates.MultiClusterApplicationConfigurationName, err)
   101  		return err
   102  	}
   103  
   104  	err = updateValidatingWebhookConfiguration(kubeClient, certificates.VerrazzanoProjectValidatingWebhookName)
   105  	if err != nil {
   106  		log.Errorf(failedToUpdate, certificates.VerrazzanoProjectValidatingWebhookName, err)
   107  		return err
   108  	}
   109  
   110  	err = updateMutatingWebhookConfiguration(kubeClient, certificates.IstioMutatingWebhookName)
   111  	if err != nil {
   112  		log.Errorf(failedToUpdate, certificates.IstioMutatingWebhookName, err)
   113  		return err
   114  	}
   115  
   116  	err = updateMutatingWebhookConfiguration(kubeClient, certificates.AppConfigMutatingWebhookName)
   117  	if err != nil {
   118  		log.Errorf(failedToUpdate, certificates.AppConfigMutatingWebhookName, err)
   119  		return err
   120  	}
   121  
   122  	err = updateMutatingWebhookConfiguration(kubeClient, certificates.MetricsBindingWebhookName)
   123  	if err != nil {
   124  		log.Errorf(failedToUpdate, certificates.MetricsBindingWebhookName, err)
   125  		return err
   126  	}
   127  
   128  	if err = (&vzapi.IngressTrait{}).SetupWebhookWithManager(mgr); err != nil {
   129  		log.Errorf("Failed to create IngressTrait webhook: %v", err)
   130  		return err
   131  	}
   132  
   133  	// VerrazzanoProject validating webhook
   134  	mgr.GetWebhookServer().Register(
   135  		"/validate-clusters-verrazzano-io-v1alpha1-verrazzanoproject",
   136  		&webhook.Admission{Handler: &webhooks.VerrazzanoProjectValidator{}})
   137  
   138  	dynamicClient, err := dynamic.NewForConfig(config)
   139  	if err != nil {
   140  		log.Errorf("Failed to create Kubernetes dynamic client: %v", err)
   141  		return err
   142  	}
   143  
   144  	istioClientSet, err := istioversionedclient.NewForConfig(config)
   145  	if err != nil {
   146  		log.Errorf("Failed to create istio client: %v", err)
   147  		return err
   148  	}
   149  
   150  	// Register a webhook that listens on pods that are running in a istio enabled namespace.
   151  	mgr.GetWebhookServer().Register(
   152  		webhooks.IstioDefaulterPath,
   153  		&webhook.Admission{
   154  			Handler: &webhooks.IstioWebhook{
   155  				Client:        mgr.GetClient(),
   156  				KubeClient:    kubeClient,
   157  				DynamicClient: dynamicClient,
   158  				IstioClient:   istioClientSet,
   159  			},
   160  		},
   161  	)
   162  
   163  	// Register the metrics binding mutating webhooks for plain old kubernetes objects workloads
   164  	// The webhooks handle legacy metrics template annotations on these workloads - newer
   165  	// workloads should rely on user-created monitor resources.
   166  	mgr.GetWebhookServer().Register(
   167  		webhooks.MetricsBindingGeneratorWorkloadPath,
   168  		&webhook.Admission{
   169  			Handler: &webhooks.WorkloadWebhook{
   170  				Client:     mgr.GetClient(),
   171  				KubeClient: kubeClient,
   172  			},
   173  		},
   174  	)
   175  	mgr.GetWebhookServer().Register(
   176  		webhooks.MetricsBindingLabelerPodPath,
   177  		&webhook.Admission{
   178  			Handler: &webhooks.LabelerPodWebhook{
   179  				Client:        mgr.GetClient(),
   180  				DynamicClient: dynamicClient,
   181  			},
   182  		},
   183  	)
   184  
   185  	mgr.GetWebhookServer().CertDir = certDir
   186  	appconfigWebhook := &webhooks.AppConfigWebhook{
   187  		Client:      mgr.GetClient(),
   188  		KubeClient:  kubeClient,
   189  		IstioClient: istioClientSet,
   190  		Defaulters: []webhooks.AppConfigDefaulter{
   191  			&webhooks.MetricsTraitDefaulter{
   192  				Client: mgr.GetClient(),
   193  			},
   194  		},
   195  	}
   196  	mgr.GetWebhookServer().Register(webhooks.AppConfigDefaulterPath, &webhook.Admission{Handler: appconfigWebhook})
   197  
   198  	// MultiClusterApplicationConfiguration validating webhook
   199  	mgr.GetWebhookServer().Register(
   200  		"/validate-clusters-verrazzano-io-v1alpha1-multiclusterapplicationconfiguration",
   201  		&webhook.Admission{Handler: &webhooks.MultiClusterApplicationConfigurationValidator{}})
   202  
   203  	// MultiClusterComponent validating webhook
   204  	mgr.GetWebhookServer().Register(
   205  		"/validate-clusters-verrazzano-io-v1alpha1-multiclustercomponent",
   206  		&webhook.Admission{Handler: &webhooks.MultiClusterComponentValidator{}})
   207  
   208  	// MultiClusterConfigMap validating webhook
   209  	mgr.GetWebhookServer().Register(
   210  		"/validate-clusters-verrazzano-io-v1alpha1-multiclusterconfigmap",
   211  		&webhook.Admission{Handler: &webhooks.MultiClusterConfigmapValidator{}})
   212  
   213  	// MultiClusterSecret validating webhook
   214  	mgr.GetWebhookServer().Register(
   215  		"/validate-clusters-verrazzano-io-v1alpha1-multiclustersecret",
   216  		&webhook.Admission{Handler: &webhooks.MultiClusterSecretValidator{}})
   217  
   218  	// +kubebuilder:scaffold:builder
   219  
   220  	log.Info("Starting manager")
   221  	if err = mgr.Start(ctrl.SetupSignalHandler()); err != nil {
   222  		log.Errorf("Failed to run manager: %v", err)
   223  		return err
   224  	}
   225  	return err
   226  }