From b09b9f719b7ed52a3990522c7edc150a2a952312 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Wed, 16 Sep 2020 00:55:21 +0300 Subject: [PATCH] kubeadm: relax the validation of kubeconfig server URLs For external CA users that have prepared the kubeconfig files for components, they might wish to provide a custom API server URL. When performing validation on these kubeconfig files, instead of erroring out on such custom URLs, show a klog Warning. This allows flexibility around topology setup, where users wish to make the kubeconfigs point to the ControlPlaneEndpoint instead of the LocalAPIEndpoint. Fix validation in ValidateKubeconfigsForExternalCA expecting all kubeconfig files to use the CPE. The kube-scheduler and kube-controller-manager now use LAE. --- .../app/phases/kubeconfig/kubeconfig.go | 43 +++++++++++++------ .../app/phases/kubeconfig/kubeconfig_test.go | 11 ++--- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go index 785376b3a9a..51bd42eec2b 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go @@ -221,9 +221,10 @@ func validateKubeConfig(outDir, filename string, config *clientcmdapi.Config) er if !bytes.Equal(caCurrent, caExpected) { return errors.Errorf("a kubeconfig file %q exists already but has got the wrong CA cert", kubeConfigFilePath) } - // If the current API Server location on disk doesn't match the expected API server, error out because we have a file, but it's stale + // If the current API Server location on disk doesn't match the expected API server, show a warning if currentConfig.Clusters[currentCluster].Server != config.Clusters[expectedCluster].Server { - return errors.Errorf("a kubeconfig file %q exists already but has got the wrong API Server URL", kubeConfigFilePath) + klog.Warningf("a kubeconfig file %q exists already but has an unexpected API Server URL: expected: %s, got: %s", + kubeConfigFilePath, config.Clusters[expectedCluster].Server, currentConfig.Clusters[currentCluster].Server) } return nil @@ -331,13 +332,6 @@ func writeKubeConfigFromSpec(out io.Writer, spec *kubeConfigSpec, clustername st // ValidateKubeconfigsForExternalCA check if the kubeconfig file exist and has the expected CA and server URL using kubeadmapi.InitConfiguration. func ValidateKubeconfigsForExternalCA(outDir string, cfg *kubeadmapi.InitConfiguration) error { - kubeConfigFileNames := []string{ - kubeadmconstants.AdminKubeConfigFileName, - kubeadmconstants.KubeletKubeConfigFileName, - kubeadmconstants.ControllerManagerKubeConfigFileName, - kubeadmconstants.SchedulerKubeConfigFileName, - } - // Creates a kubeconfig file with the target CA and server URL // to be used as a input for validating user provided kubeconfig files caCert, err := pkiutil.TryLoadCertFromDisk(cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName) @@ -345,19 +339,42 @@ func ValidateKubeconfigsForExternalCA(outDir string, cfg *kubeadmapi.InitConfigu return errors.Wrapf(err, "the CA file couldn't be loaded") } + // validate user provided kubeconfig files for the scheduler and controller-manager + localAPIEndpoint, err := kubeadmutil.GetLocalAPIEndpoint(&cfg.LocalAPIEndpoint) + if err != nil { + return err + } + + validationConfigLocal := kubeconfigutil.CreateBasic(localAPIEndpoint, "dummy", "dummy", pkiutil.EncodeCertPEM(caCert)) + kubeConfigFileNamesLocal := []string{ + kubeadmconstants.ControllerManagerKubeConfigFileName, + kubeadmconstants.SchedulerKubeConfigFileName, + } + + for _, kubeConfigFileName := range kubeConfigFileNamesLocal { + if err = validateKubeConfig(outDir, kubeConfigFileName, validationConfigLocal); err != nil { + return errors.Wrapf(err, "the %s file does not exists or it is not valid", kubeConfigFileName) + } + } + + // validate user provided kubeconfig files for the kubelet and admin controlPlaneEndpoint, err := kubeadmutil.GetControlPlaneEndpoint(cfg.ControlPlaneEndpoint, &cfg.LocalAPIEndpoint) if err != nil { return err } - validationConfig := kubeconfigutil.CreateBasic(controlPlaneEndpoint, "dummy", "dummy", pkiutil.EncodeCertPEM(caCert)) + validationConfigCPE := kubeconfigutil.CreateBasic(controlPlaneEndpoint, "dummy", "dummy", pkiutil.EncodeCertPEM(caCert)) + kubeConfigFileNamesCPE := []string{ + kubeadmconstants.AdminKubeConfigFileName, + kubeadmconstants.KubeletKubeConfigFileName, + } - // validate user provided kubeconfig files - for _, kubeConfigFileName := range kubeConfigFileNames { - if err = validateKubeConfig(outDir, kubeConfigFileName, validationConfig); err != nil { + for _, kubeConfigFileName := range kubeConfigFileNamesCPE { + if err = validateKubeConfig(outDir, kubeConfigFileName, validationConfigCPE); err != nil { return errors.Wrapf(err, "the %s file does not exists or it is not valid", kubeConfigFileName) } } + return nil } diff --git a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go index ede3bf5ada3..df5d47b64e1 100644 --- a/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go +++ b/cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go @@ -261,11 +261,10 @@ func TestCreateKubeConfigFileIfNotExists(t *testing.T) { kubeConfig: configWithAnotherClusterCa, expectedError: true, }, - { // if KubeConfig is not equal to the existingKubeConfig - refers to the another cluster (a cluster with another address) -, raise error + { // if KubeConfig is not equal to the existingKubeConfig - tollerate custom server addresses name: "KubeConfig referst to the cluster with another address", existingKubeConfig: config, kubeConfig: configWithAnotherClusterAddress, - expectedError: true, }, } @@ -505,10 +504,9 @@ func TestValidateKubeConfig(t *testing.T) { kubeConfig: config, expectedError: true, }, - "kubeconfig exist and has invalid server url": { + "kubeconfig exist and has a different server url": { existingKubeConfig: configWithAnotherServerURL, kubeConfig: config, - expectedError: true, }, "kubeconfig exist and is valid": { existingKubeConfig: config, @@ -608,15 +606,14 @@ func TestValidateKubeconfigsForExternalCA(t *testing.T) { initConfig: initConfig, expectedError: true, }, - "some files have invalid Server Url": { + "some files have a different Server URL": { filesToWrite: map[string]*clientcmdapi.Config{ kubeadmconstants.AdminKubeConfigFileName: config, kubeadmconstants.KubeletKubeConfigFileName: config, kubeadmconstants.ControllerManagerKubeConfigFileName: config, kubeadmconstants.SchedulerKubeConfigFileName: configWithAnotherServerURL, }, - initConfig: initConfig, - expectedError: true, + initConfig: initConfig, }, "all files are valid": { filesToWrite: map[string]*clientcmdapi.Config{