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.
This commit is contained in:
Lubomir I. Ivanov 2019-12-30 00:51:37 +02:00
parent 886cf062a4
commit 453ac809c1
2 changed files with 20 additions and 1 deletions

View File

@ -235,8 +235,14 @@ func validateKubeConfig(outDir, filename string, config *clientcmdapi.Config) er
return errors.Errorf("failed to find the given CurrentContext Cluster in Clusters of the kubeconfig file %s", kubeConfigFilePath)
}
// Make sure the compared CAs are whitespace-trimmed. The function clientcmd.LoadFromFile() just decodes
// the base64 CA and places it raw in the v1.Config object. In case the user has extra whitespace
// in the CA they used to create a kubeconfig this comparison to a generated v1.Config will otherwise fail.
caCurrent := bytes.TrimSpace(currentConfig.Clusters[currentCluster].CertificateAuthorityData)
caExpected := bytes.TrimSpace(config.Clusters[expectedCluster].CertificateAuthorityData)
// 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
if !bytes.Equal(currentConfig.Clusters[currentCluster].CertificateAuthorityData, config.Clusters[expectedCluster].CertificateAuthorityData) {
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

View File

@ -469,6 +469,14 @@ func TestValidateKubeConfig(t *testing.T) {
configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1")
configWithAnotherServerURL := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://4.3.2.1:4321", "test-cluster", "myOrg1")
// create a valid config but with whitespace around the CA PEM.
// validateKubeConfig() should tollerate that.
configWhitespace := config.DeepCopy()
configWhitespaceCtx := configWhitespace.Contexts[configWhitespace.CurrentContext]
configWhitespaceCA := string(configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData)
configWhitespaceCA = "\n" + configWhitespaceCA + "\n"
configWhitespace.Clusters[configWhitespaceCtx.Cluster].CertificateAuthorityData = []byte(configWhitespaceCA)
tests := map[string]struct {
existingKubeConfig *clientcmdapi.Config
kubeConfig *clientcmdapi.Config
@ -493,6 +501,11 @@ func TestValidateKubeConfig(t *testing.T) {
kubeConfig: config,
expectedError: false,
},
"kubeconfig exist and is valid even if its CA contains whitespace": {
existingKubeConfig: configWhitespace,
kubeConfig: config,
expectedError: false,
},
}
for name, test := range tests {