volcano.sh/volcano@v1.9.0/cmd/webhook-manager/app/util.go (about) 1 /* 2 Copyright 2019 The Volcano Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package app 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/tls" 23 "crypto/x509" 24 "fmt" 25 "strings" 26 "time" 27 28 v1 "k8s.io/api/admissionregistration/v1" 29 apierrors "k8s.io/apimachinery/pkg/api/errors" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/apimachinery/pkg/util/wait" 32 "k8s.io/client-go/kubernetes" 33 "k8s.io/client-go/rest" 34 "k8s.io/klog/v2" 35 36 "volcano.sh/apis/pkg/client/clientset/versioned" 37 "volcano.sh/volcano/cmd/webhook-manager/app/options" 38 "volcano.sh/volcano/pkg/webhooks/router" 39 ) 40 41 const volcanoAdmissionPrefix = "volcano-admission-service" 42 43 func addCaCertForWebhook(kubeClient *kubernetes.Clientset, service *router.AdmissionService, caBundle []byte) error { 44 if service.MutatingConfig != nil { 45 // update MutatingWebhookConfigurations 46 var mutatingWebhookName = volcanoAdmissionPrefix + strings.ReplaceAll(service.Path, "/", "-") 47 var mutatingWebhook *v1.MutatingWebhookConfiguration 48 webhookChanged := false 49 if err := wait.Poll(time.Second, 5*time.Minute, func() (done bool, err error) { 50 mutatingWebhook, err = kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), mutatingWebhookName, metav1.GetOptions{}) 51 if err != nil { 52 if apierrors.IsNotFound(err) { 53 klog.Errorln(err) 54 return false, nil 55 } 56 return false, fmt.Errorf("failed to get mutating webhook %v", err) 57 } 58 return true, nil 59 }); err != nil { 60 return fmt.Errorf("failed to get mutating webhook %v", err) 61 } 62 63 for index := 0; index < len(mutatingWebhook.Webhooks); index++ { 64 if mutatingWebhook.Webhooks[index].ClientConfig.CABundle == nil || 65 !bytes.Equal(mutatingWebhook.Webhooks[index].ClientConfig.CABundle, caBundle) { 66 mutatingWebhook.Webhooks[index].ClientConfig.CABundle = caBundle 67 webhookChanged = true 68 } 69 } 70 if webhookChanged { 71 if _, err := kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(context.TODO(), mutatingWebhook, metav1.UpdateOptions{}); err != nil { 72 return fmt.Errorf("failed to update mutating admission webhooks %v %v", mutatingWebhookName, err) 73 } 74 } 75 } 76 77 if service.ValidatingConfig != nil { 78 // update ValidatingWebhookConfigurations 79 var validatingWebhookName = volcanoAdmissionPrefix + strings.ReplaceAll(service.Path, "/", "-") 80 var validatingWebhook *v1.ValidatingWebhookConfiguration 81 webhookChanged := false 82 if err := wait.Poll(time.Second, 5*time.Minute, func() (done bool, err error) { 83 validatingWebhook, err = kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), validatingWebhookName, metav1.GetOptions{}) 84 if err != nil { 85 if apierrors.IsNotFound(err) { 86 klog.Errorln(err) 87 return false, nil 88 } 89 return false, fmt.Errorf("failed to get validating webhook %v", err) 90 } 91 return true, nil 92 }); err != nil { 93 return fmt.Errorf("failed to get validating webhook %v", err) 94 } 95 96 for index := 0; index < len(validatingWebhook.Webhooks); index++ { 97 if validatingWebhook.Webhooks[index].ClientConfig.CABundle == nil || 98 !bytes.Equal(validatingWebhook.Webhooks[index].ClientConfig.CABundle, caBundle) { 99 validatingWebhook.Webhooks[index].ClientConfig.CABundle = caBundle 100 webhookChanged = true 101 } 102 } 103 if webhookChanged { 104 if _, err := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(context.TODO(), validatingWebhook, metav1.UpdateOptions{}); err != nil { 105 return fmt.Errorf("failed to update validating admission webhooks %v %v", validatingWebhookName, err) 106 } 107 } 108 } 109 110 return nil 111 } 112 113 // getKubeClient Get a clientset with restConfig. 114 func getKubeClient(restConfig *rest.Config) *kubernetes.Clientset { 115 clientset, err := kubernetes.NewForConfig(restConfig) 116 if err != nil { 117 klog.Fatal(err) 118 } 119 return clientset 120 } 121 122 // GetVolcanoClient get a clientset for volcano. 123 func getVolcanoClient(restConfig *rest.Config) *versioned.Clientset { 124 clientset, err := versioned.NewForConfig(restConfig) 125 if err != nil { 126 klog.Fatal(err) 127 } 128 return clientset 129 } 130 131 // configTLS is a helper function that generate tls certificates from directly defined tls config or kubeconfig 132 // These are passed in as command line for cluster certification. If tls config is passed in, we use the directly 133 // defined tls config, else use that defined in kubeconfig. 134 func configTLS(config *options.Config, restConfig *rest.Config) *tls.Config { 135 if len(config.CertData) != 0 && len(config.KeyData) != 0 { 136 certPool := x509.NewCertPool() 137 certPool.AppendCertsFromPEM(config.CaCertData) 138 139 sCert, err := tls.X509KeyPair(config.CertData, config.KeyData) 140 if err != nil { 141 klog.Fatal(err) 142 } 143 144 return &tls.Config{ 145 Certificates: []tls.Certificate{sCert}, 146 RootCAs: certPool, 147 MinVersion: tls.VersionTLS12, 148 ClientAuth: tls.VerifyClientCertIfGiven, 149 CipherSuites: []uint16{ 150 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 151 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 152 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 153 }, 154 } 155 } 156 157 if len(restConfig.CertData) != 0 && len(restConfig.KeyData) != 0 { 158 sCert, err := tls.X509KeyPair(restConfig.CertData, restConfig.KeyData) 159 if err != nil { 160 klog.Fatal(err) 161 } 162 163 return &tls.Config{ 164 Certificates: []tls.Certificate{sCert}, 165 } 166 } 167 168 klog.Fatal("tls: failed to find any tls config data") 169 return &tls.Config{} 170 }