From 05b77fe99f5c57bad36a74c2e1986f678ac44a01 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Wed, 23 Sep 2020 03:27:50 +0300 Subject: [PATCH] kubeadm: warn but do not error out on missing CA keys on CP join - Modify validateCACertAndKey() to print warnings for missing keys instead of erroring out. - Update unit tests. This allows doing a CP node join in a case where the user has: - copied shared certificates to the new CP node, but not copied ca.key files, treating the cluster CAs as external - signed other required certificates in advance --- cmd/kubeadm/app/phases/certs/certs.go | 5 +++-- cmd/kubeadm/app/phases/certs/certs_test.go | 24 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cmd/kubeadm/app/phases/certs/certs.go b/cmd/kubeadm/app/phases/certs/certs.go index 094f4303375..fb3f372e1cf 100644 --- a/cmd/kubeadm/app/phases/certs/certs.go +++ b/cmd/kubeadm/app/phases/certs/certs.go @@ -286,6 +286,7 @@ type certKeyLocation struct { // SharedCertificateExists verifies if the shared certificates - the certificates that must be // equal across control-plane nodes: ca.key, ca.crt, sa.key, sa.pub + etcd/ca.key, etcd/ca.crt if local/stacked etcd +// Missing keys are non-fatal and produce warnings. func SharedCertificateExists(cfg *kubeadmapi.ClusterConfiguration) (bool, error) { if err := validateCACertAndKey(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.CACertAndKeyBaseName, "", "CA"}); err != nil { @@ -373,7 +374,7 @@ func validateCACert(l certKeyLocation) error { } // validateCACertAndKey tries to load a x509 certificate and private key from pkiDir, -// and validates that the cert is a CA +// and validates that the cert is a CA. Failure to load the key produces a warning. func validateCACertAndKey(l certKeyLocation) error { if err := validateCACert(l); err != nil { return err @@ -381,7 +382,7 @@ func validateCACertAndKey(l certKeyLocation) error { _, err := pkiutil.TryLoadKeyFromDisk(l.pkiDir, l.caBaseName) if err != nil { - return errors.Wrapf(err, "failure loading key for %s", l.uxName) + klog.Warningf("assuming external key for %s: %v", l.uxName, err) } return nil } diff --git a/cmd/kubeadm/app/phases/certs/certs_test.go b/cmd/kubeadm/app/phases/certs/certs_test.go index c1c43e3e9b8..e0e9436a4e4 100644 --- a/cmd/kubeadm/app/phases/certs/certs_test.go +++ b/cmd/kubeadm/app/phases/certs/certs_test.go @@ -401,6 +401,19 @@ func TestSharedCertificateExists(t *testing.T) { }, expectedError: true, }, + { + name: "missing ca.key", + files: certstestutil.PKIFiles{ + "ca.crt": caCert, + "front-proxy-ca.crt": caCert, + "front-proxy-ca.key": caKey, + "sa.pub": publicKey, + "sa.key": key, + "etcd/ca.crt": caCert, + "etcd/ca.key": caKey, + }, + expectedError: false, + }, { name: "missing sa.key", files: certstestutil.PKIFiles{ @@ -642,7 +655,7 @@ func TestValidateMethods(t *testing.T) { name: "validateCACertAndKey (key missing)", validateFunc: validateCACertAndKey, loc: certKeyLocation{caBaseName: "ca", baseName: "", uxName: "CA"}, - expectedSuccess: false, + expectedSuccess: true, }, { name: "validateSignedCert", @@ -666,6 +679,15 @@ func TestValidateMethods(t *testing.T) { loc: certKeyLocation{baseName: "sa", uxName: "service account"}, expectedSuccess: true, }, + { + name: "validatePrivatePublicKey (missing key)", + files: certstestutil.PKIFiles{ + "sa.pub": key.Public(), + }, + validateFunc: validatePrivatePublicKey, + loc: certKeyLocation{baseName: "sa", uxName: "service account"}, + expectedSuccess: false, + }, } for _, test := range tests {