k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go (about) 1 /* 2 Copyright 2017 The Kubernetes 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 kubeconfig 18 19 import ( 20 "fmt" 21 "os" 22 23 "github.com/pkg/errors" 24 25 clientset "k8s.io/client-go/kubernetes" 26 "k8s.io/client-go/tools/clientcmd" 27 clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 28 ) 29 30 // CreateBasic creates a basic, general KubeConfig object that then can be extended 31 func CreateBasic(serverURL, clusterName, userName string, caCert []byte) *clientcmdapi.Config { 32 // Use the cluster and the username as the context name 33 contextName := fmt.Sprintf("%s@%s", userName, clusterName) 34 35 return &clientcmdapi.Config{ 36 Clusters: map[string]*clientcmdapi.Cluster{ 37 clusterName: { 38 Server: serverURL, 39 CertificateAuthorityData: caCert, 40 }, 41 }, 42 Contexts: map[string]*clientcmdapi.Context{ 43 contextName: { 44 Cluster: clusterName, 45 AuthInfo: userName, 46 }, 47 }, 48 AuthInfos: map[string]*clientcmdapi.AuthInfo{}, 49 CurrentContext: contextName, 50 } 51 } 52 53 // CreateWithCerts creates a KubeConfig object with access to the API server with client certificates 54 func CreateWithCerts(serverURL, clusterName, userName string, caCert []byte, clientKey []byte, clientCert []byte) *clientcmdapi.Config { 55 config := CreateBasic(serverURL, clusterName, userName, caCert) 56 config.AuthInfos[userName] = &clientcmdapi.AuthInfo{ 57 ClientKeyData: clientKey, 58 ClientCertificateData: clientCert, 59 } 60 return config 61 } 62 63 // CreateWithToken creates a KubeConfig object with access to the API server with a token 64 func CreateWithToken(serverURL, clusterName, userName string, caCert []byte, token string) *clientcmdapi.Config { 65 config := CreateBasic(serverURL, clusterName, userName, caCert) 66 config.AuthInfos[userName] = &clientcmdapi.AuthInfo{ 67 Token: token, 68 } 69 return config 70 } 71 72 // ClientSetFromFile returns a ready-to-use client from a kubeconfig file 73 func ClientSetFromFile(path string) (clientset.Interface, error) { 74 config, err := clientcmd.LoadFromFile(path) 75 if err != nil { 76 return nil, errors.Wrap(err, "failed to load admin kubeconfig") 77 } 78 return ToClientSet(config) 79 } 80 81 // ToClientSet converts a KubeConfig object to a client 82 func ToClientSet(config *clientcmdapi.Config) (clientset.Interface, error) { 83 overrides := clientcmd.ConfigOverrides{Timeout: "10s"} 84 clientConfig, err := clientcmd.NewDefaultClientConfig(*config, &overrides).ClientConfig() 85 if err != nil { 86 return nil, errors.Wrap(err, "failed to create API client configuration from kubeconfig") 87 } 88 89 client, err := clientset.NewForConfig(clientConfig) 90 if err != nil { 91 return nil, errors.Wrap(err, "failed to create API client") 92 } 93 return client, nil 94 } 95 96 // WriteToDisk writes a KubeConfig object down to disk with mode 0600 97 func WriteToDisk(filename string, kubeconfig *clientcmdapi.Config) error { 98 err := clientcmd.WriteToFile(*kubeconfig, filename) 99 if err != nil { 100 return err 101 } 102 103 return nil 104 } 105 106 // GetClusterFromKubeConfig returns the default Cluster of the specified KubeConfig 107 func GetClusterFromKubeConfig(config *clientcmdapi.Config) (string, *clientcmdapi.Cluster) { 108 // If there is an unnamed cluster object, use it 109 if config.Clusters[""] != nil { 110 return "", config.Clusters[""] 111 } 112 113 currentContext := config.Contexts[config.CurrentContext] 114 if currentContext != nil { 115 return currentContext.Cluster, config.Clusters[currentContext.Cluster] 116 } 117 return "", nil 118 } 119 120 // HasAuthenticationCredentials returns true if the current user has valid authentication credentials for 121 // token authentication, basic authentication or X509 authentication 122 func HasAuthenticationCredentials(config *clientcmdapi.Config) bool { 123 authInfo := getCurrentAuthInfo(config) 124 if authInfo == nil { 125 return false 126 } 127 128 // token authentication 129 if len(authInfo.Token) != 0 || len(authInfo.TokenFile) != 0 { 130 return true 131 } 132 133 // basic authentication 134 if len(authInfo.Username) != 0 && len(authInfo.Password) != 0 { 135 return true 136 } 137 138 // X509 authentication 139 if (len(authInfo.ClientCertificate) != 0 || len(authInfo.ClientCertificateData) != 0) && 140 (len(authInfo.ClientKey) != 0 || len(authInfo.ClientKeyData) != 0) { 141 return true 142 } 143 144 // exec authentication 145 if authInfo.Exec != nil && len(authInfo.Exec.Command) != 0 { 146 return true 147 } 148 149 // authprovider authentication 150 if authInfo.AuthProvider != nil && len(authInfo.AuthProvider.Name) != 0 { 151 return true 152 } 153 154 return false 155 } 156 157 // EnsureAuthenticationInfoAreEmbedded check if some authentication info are provided as external key/certificate 158 // files, and eventually embeds such files into the kubeconfig file 159 func EnsureAuthenticationInfoAreEmbedded(config *clientcmdapi.Config) error { 160 authInfo := getCurrentAuthInfo(config) 161 if authInfo == nil { 162 return errors.New("invalid kubeconfig file. AuthInfo is not defined for the current user") 163 } 164 165 if len(authInfo.ClientCertificateData) == 0 && len(authInfo.ClientCertificate) != 0 { 166 clientCert, err := os.ReadFile(authInfo.ClientCertificate) 167 if err != nil { 168 return errors.Wrap(err, "error while reading client cert file defined in kubeconfig") 169 } 170 authInfo.ClientCertificateData = clientCert 171 authInfo.ClientCertificate = "" 172 } 173 if len(authInfo.ClientKeyData) == 0 && len(authInfo.ClientKey) != 0 { 174 clientKey, err := os.ReadFile(authInfo.ClientKey) 175 if err != nil { 176 return errors.Wrap(err, "error while reading client key file defined in kubeconfig") 177 } 178 authInfo.ClientKeyData = clientKey 179 authInfo.ClientKey = "" 180 } 181 if len(authInfo.Token) == 0 && len(authInfo.TokenFile) != 0 { 182 tokenBytes, err := os.ReadFile(authInfo.TokenFile) 183 if err != nil { 184 return errors.Wrap(err, "error while reading token file defined in kubeconfig") 185 } 186 authInfo.Token = string(tokenBytes) 187 authInfo.TokenFile = "" 188 } 189 190 return nil 191 } 192 193 // EnsureCertificateAuthorityIsEmbedded check if the certificate authority is provided as an external 194 // file and eventually embeds it into the kubeconfig 195 func EnsureCertificateAuthorityIsEmbedded(cluster *clientcmdapi.Cluster) error { 196 if cluster == nil { 197 return errors.New("received nil value for Cluster") 198 } 199 200 if len(cluster.CertificateAuthorityData) == 0 && len(cluster.CertificateAuthority) != 0 { 201 ca, err := os.ReadFile(cluster.CertificateAuthority) 202 if err != nil { 203 return errors.Wrap(err, "error while reading certificate authority file defined in kubeconfig") 204 } 205 cluster.CertificateAuthorityData = ca 206 cluster.CertificateAuthority = "" 207 } 208 209 return nil 210 } 211 212 // getCurrentAuthInfo returns current authInfo, if defined 213 func getCurrentAuthInfo(config *clientcmdapi.Config) *clientcmdapi.AuthInfo { 214 if config == nil || config.CurrentContext == "" || 215 len(config.Contexts) == 0 || config.Contexts[config.CurrentContext] == nil { 216 return nil 217 } 218 user := config.Contexts[config.CurrentContext].AuthInfo 219 220 if user == "" || len(config.AuthInfos) == 0 || config.AuthInfos[user] == nil { 221 return nil 222 } 223 224 return config.AuthInfos[user] 225 }