From 21cd660a1f570dce08bc314241d1acd68fe8e74c Mon Sep 17 00:00:00 2001 From: SataQiu Date: Sat, 19 Nov 2022 16:32:37 +0800 Subject: [PATCH] kubeadm: respect user provided kubeconfig during discovery process --- cmd/kubeadm/app/cmd/join.go | 2 +- cmd/kubeadm/app/cmd/util/join.go | 2 +- cmd/kubeadm/app/discovery/discovery.go | 6 ++-- cmd/kubeadm/app/discovery/file/file.go | 30 ++++++++----------- cmd/kubeadm/app/discovery/https/https.go | 4 +-- cmd/kubeadm/app/util/kubeconfig/kubeconfig.go | 12 ++++---- 6 files changed, 27 insertions(+), 29 deletions(-) diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 3f374ff9ee4..af8f06f8832 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -589,7 +589,7 @@ func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfigurati } // Create the final KubeConfig file with the cluster name discovered after fetching the cluster configuration - clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg) + _, clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg) tlsBootstrapCfg.Clusters = map[string]*clientcmdapi.Cluster{ initConfiguration.ClusterName: clusterinfo, } diff --git a/cmd/kubeadm/app/cmd/util/join.go b/cmd/kubeadm/app/cmd/util/join.go index 639f5420945..95f0e7d4aae 100644 --- a/cmd/kubeadm/app/cmd/util/join.go +++ b/cmd/kubeadm/app/cmd/util/join.go @@ -59,7 +59,7 @@ func getJoinCommand(kubeConfigFile, token, key string, controlPlane, skipTokenPr } // load the default cluster config - clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config) + _, clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config) if clusterConfig == nil { return "", errors.New("failed to get default cluster config") } diff --git a/cmd/kubeadm/app/discovery/discovery.go b/cmd/kubeadm/app/discovery/discovery.go index 26af504fae0..574163d4dac 100644 --- a/cmd/kubeadm/app/discovery/discovery.go +++ b/cmd/kubeadm/app/discovery/discovery.go @@ -51,7 +51,7 @@ func For(cfg *kubeadmapi.JoinConfiguration) (*clientcmdapi.Config, error) { if len(cfg.Discovery.TLSBootstrapToken) != 0 { klog.V(1).Info("[discovery] Using provided TLSBootstrapToken as authentication credentials for the join process") - clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(config) + _, clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(config) return kubeconfigutil.CreateWithToken( clusterinfo.Server, kubeadmapiv1.DefaultClusterName, @@ -76,9 +76,9 @@ func DiscoverValidatedKubeConfig(cfg *kubeadmapi.JoinConfiguration) (*clientcmda case cfg.Discovery.File != nil: kubeConfigPath := cfg.Discovery.File.KubeConfigPath if isHTTPSURL(kubeConfigPath) { - return https.RetrieveValidatedConfigInfo(kubeConfigPath, kubeadmapiv1.DefaultClusterName, cfg.Discovery.Timeout.Duration) + return https.RetrieveValidatedConfigInfo(kubeConfigPath, cfg.Discovery.Timeout.Duration) } - return file.RetrieveValidatedConfigInfo(kubeConfigPath, kubeadmapiv1.DefaultClusterName, cfg.Discovery.Timeout.Duration) + return file.RetrieveValidatedConfigInfo(kubeConfigPath, cfg.Discovery.Timeout.Duration) case cfg.Discovery.BootstrapToken != nil: return token.RetrieveValidatedConfigInfo(&cfg.Discovery) default: diff --git a/cmd/kubeadm/app/discovery/file/file.go b/cmd/kubeadm/app/discovery/file/file.go index 11673f69722..6a9627bb8b4 100644 --- a/cmd/kubeadm/app/discovery/file/file.go +++ b/cmd/kubeadm/app/discovery/file/file.go @@ -38,22 +38,22 @@ import ( // RetrieveValidatedConfigInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func RetrieveValidatedConfigInfo(filepath, clustername string, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { +func RetrieveValidatedConfigInfo(filepath string, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { config, err := clientcmd.LoadFromFile(filepath) if err != nil { return nil, err } - return ValidateConfigInfo(config, clustername, discoveryTimeout) + return ValidateConfigInfo(config, discoveryTimeout) } // ValidateConfigInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert/client certificates and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func ValidateConfigInfo(config *clientcmdapi.Config, clustername string, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { +func ValidateConfigInfo(config *clientcmdapi.Config, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { if len(config.Clusters) < 1 { return nil, errors.New("the provided kubeconfig file must have at least one Cluster defined") } - currentCluster := kubeconfigutil.GetClusterFromKubeConfig(config) + currentClusterName, currentCluster := kubeconfigutil.GetClusterFromKubeConfig(config) if currentCluster == nil { return nil, errors.New("the provided kubeconfig file must have a unnamed Cluster or a CurrentContext that specifies a non-nil Cluster") } @@ -78,15 +78,6 @@ func ValidateConfigInfo(config *clientcmdapi.Config, clustername string, discove } else { // If the discovery file config does not contains authentication credentials klog.V(1).Info("[discovery] Discovery file does not contains authentication credentials, using unauthenticated request for validating TLS connection") - - // Create a new kubeconfig object from the discovery file config, with only the server and the CA cert. - // NB. We do this in order to not pick up other possible misconfigurations in the clusterinfo file - config = kubeconfigutil.CreateBasic( - currentCluster.Server, - clustername, - "", // no user provided - currentCluster.CertificateAuthorityData, - ) } // Try to read the cluster-info config map; this step was required by the original design in order @@ -131,11 +122,16 @@ func ValidateConfigInfo(config *clientcmdapi.Config, clustername string, discove return config, nil } - refreshedCluster := kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig) - currentCluster.Server = refreshedCluster.Server - currentCluster.CertificateAuthorityData = refreshedCluster.CertificateAuthorityData + _, refreshedCluster := kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig) + if currentCluster.Server != refreshedCluster.Server { + klog.Warningf("[discovery] the API Server endpoint %q in use is different from the endpoint %q which defined in the %s ConfigMap", currentCluster.Server, refreshedCluster.Server, bootstrapapi.ConfigMapClusterInfo) + } + + if len(currentCluster.CertificateAuthorityData) == 0 && len(refreshedCluster.CertificateAuthorityData) > 0 { + config.Clusters[currentClusterName].CertificateAuthorityData = refreshedCluster.CertificateAuthorityData + klog.V(1).Infof("[discovery] Synced CertificateAuthorityData from the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) + } - klog.V(1).Infof("[discovery] Synced Server and CertificateAuthorityData from the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) return config, nil } diff --git a/cmd/kubeadm/app/discovery/https/https.go b/cmd/kubeadm/app/discovery/https/https.go index 6ff6814de20..18f0a0df211 100644 --- a/cmd/kubeadm/app/discovery/https/https.go +++ b/cmd/kubeadm/app/discovery/https/https.go @@ -31,7 +31,7 @@ import ( // RetrieveValidatedConfigInfo connects to the API Server and makes sure it can talk // securely to the API Server using the provided CA cert and // optionally refreshes the cluster-info information from the cluster-info ConfigMap -func RetrieveValidatedConfigInfo(httpsURL, clustername string, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { +func RetrieveValidatedConfigInfo(httpsURL string, discoveryTimeout time.Duration) (*clientcmdapi.Config, error) { client := &http.Client{Transport: netutil.SetOldTransportDefaults(&http.Transport{})} response, err := client.Get(httpsURL) if err != nil { @@ -48,5 +48,5 @@ func RetrieveValidatedConfigInfo(httpsURL, clustername string, discoveryTimeout if err != nil { return nil, err } - return file.ValidateConfigInfo(config, clustername, discoveryTimeout) + return file.ValidateConfigInfo(config, discoveryTimeout) } diff --git a/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go b/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go index 3494960f640..332b22279d8 100644 --- a/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go +++ b/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go @@ -104,15 +104,17 @@ func WriteToDisk(filename string, kubeconfig *clientcmdapi.Config) error { } // GetClusterFromKubeConfig returns the default Cluster of the specified KubeConfig -func GetClusterFromKubeConfig(config *clientcmdapi.Config) *clientcmdapi.Cluster { +func GetClusterFromKubeConfig(config *clientcmdapi.Config) (string, *clientcmdapi.Cluster) { // If there is an unnamed cluster object, use it if config.Clusters[""] != nil { - return config.Clusters[""] + return "", config.Clusters[""] } - if config.Contexts[config.CurrentContext] != nil { - return config.Clusters[config.Contexts[config.CurrentContext].Cluster] + + currentContext := config.Contexts[config.CurrentContext] + if currentContext != nil { + return currentContext.Cluster, config.Clusters[currentContext.Cluster] } - return nil + return "", nil } // HasAuthenticationCredentials returns true if the current user has valid authentication credentials for