Skip to content

Commit 453ac80

Browse files
committed
kubeadm: tolerate whitespace when validating user CA PEMs
The function validateKubeConfig() can end up comparing a user generated kubeconfig to a kubeconfig generated by kubeadm. If a user kubeconfig has a CA that is base64 encoded with whitespace, if said kubeconfig is loaded using clientcmd.LoadFromFile() the CertificateAuthorityData bytes will be decoded from base64 and placed in the v1.Config raw. On the other hand a kubeconfig generated by kubeadm will have the ca.crt parsed to a Certificate object with whitespace ignored in the PEM input. Make sure that validateKubeConfig() tolerates whitespace differences when comparing CertificateAuthorityData.
1 parent 886cf06 commit 453ac80

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

cmd/kubeadm/app/phases/kubeconfig/kubeconfig.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,14 @@ func validateKubeConfig(outDir, filename string, config *clientcmdapi.Config) er
235235
return errors.Errorf("failed to find the given CurrentContext Cluster in Clusters of the kubeconfig file %s", kubeConfigFilePath)
236236
}
237237

238+
// Make sure the compared CAs are whitespace-trimmed. The function clientcmd.LoadFromFile() just decodes
239+
// the base64 CA and places it raw in the v1.Config object. In case the user has extra whitespace
240+
// in the CA they used to create a kubeconfig this comparison to a generated v1.Config will otherwise fail.
241+
caCurrent := bytes.TrimSpace(currentConfig.Clusters[currentCluster].CertificateAuthorityData)
242+
caExpected := bytes.TrimSpace(config.Clusters[expectedCluster].CertificateAuthorityData)
243+
238244
// If the current CA cert on disk doesn't match the expected CA cert, error out because we have a file, but it's stale
239-
if !bytes.Equal(currentConfig.Clusters[currentCluster].CertificateAuthorityData, config.Clusters[expectedCluster].CertificateAuthorityData) {
245+
if !bytes.Equal(caCurrent, caExpected) {
240246
return errors.Errorf("a kubeconfig file %q exists already but has got the wrong CA cert", kubeConfigFilePath)
241247
}
242248
// 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

cmd/kubeadm/app/phases/kubeconfig/kubeconfig_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,14 @@ func TestValidateKubeConfig(t *testing.T) {
469469
configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
470470
configWithAnotherServerURL := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://4.3.2.1:4321", "test-cluster", "myOrg1")
471471

472+
// create a valid config but with whitespace around the CA PEM.
473+
// validateKubeConfig() should tollerate that.
474+
configWhitespace := config.DeepCopy()
475+
configWhitespaceCtx := configWhitespace.Contexts[configWhitespace.CurrentContext]
476+
configWhitespaceCA := string(configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData)
477+
configWhitespaceCA = "\n" + configWhitespaceCA + "\n"
478+
configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData = []byte(configWhitespaceCA)
479+
472480
tests := map[string]struct {
473481
existingKubeConfig *clientcmdapi.Config
474482
kubeConfig *clientcmdapi.Config
@@ -493,6 +501,11 @@ func TestValidateKubeConfig(t *testing.T) {
493501
kubeConfig: config,
494502
expectedError: false,
495503
},
504+
"kubeconfig exist and is valid even if its CA contains whitespace": {
505+
existingKubeConfig: configWhitespace,
506+
kubeConfig: config,
507+
expectedError: false,
508+
},
496509
}
497510

498511
for name, test := range tests {

0 commit comments

Comments
 (0)