Skip to content

Commit

Permalink
kubeadm: avoid requiring a CA key during kubeconfig expiration checks
Browse files Browse the repository at this point in the history
When the "kubeadm certs check-expiration" command is used and
if the ca.key is not present, regular on disk certificate reads
pass fine, but fail for kubeconfig files. The reason for the
failure is that reading of kubeconfig files currently
requires reading both the CA key and cert from disk. Reading the CA
is done to ensure that the CA cert in the kubeconfig is not out of date
during renewal.

Instead of requiring both a CA key and cert to be read, only read
the CA cert from disk, as only the cert is needed for kubeconfig files.

This fixes printing the cert expiration table even if the ca.key
is missing on a host (i.e. the CA is considered external).
  • Loading branch information
neolit123 committed Dec 9, 2021
1 parent c6ca334 commit d431931
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 6 deletions.
15 changes: 9 additions & 6 deletions cmd/kubeadm/app/phases/certs/renewal/readwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ import (
"os"
"path/filepath"

certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
"github.com/pkg/errors"

"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
certutil "k8s.io/client-go/util/cert"
"k8s.io/client-go/util/keyutil"

"github.com/pkg/errors"
pkiutil "k8s.io/kubernetes/cmd/kubeadm/app/util/pkiutil"
)

// certificateReadWriter defines the behavior of a component that
Expand Down Expand Up @@ -141,11 +140,15 @@ func (rw *kubeConfigReadWriter) Read() (*x509.Certificate, error) {
// For local CA renewal, the local CA on disk could have changed, thus a reload is needed.
// For CSR renewal we assume the same CA on disk is mounted for usage with KCM's
// '--cluster-signing-cert-file' flag.
caCert, _, err := certsphase.LoadCertificateAuthority(rw.certificateDir, rw.baseName)
certificatePath, _ := pkiutil.PathsForCertAndKey(rw.certificateDir, rw.baseName)
caCerts, err := certutil.CertsFromFile(certificatePath)
if err != nil {
return nil, err
return nil, errors.Wrapf(err, "failed to load existing certificate %s", rw.baseName)
}
if len(caCerts) != 1 {
return nil, errors.Errorf("wanted exactly one certificate, got %d", len(caCerts))
}
rw.caCert = caCert
rw.caCert = caCerts[0]

// get current context
if _, ok := kubeConfig.Contexts[kubeConfig.CurrentContext]; !ok {
Expand Down
5 changes: 5 additions & 0 deletions cmd/kubeadm/app/phases/certs/renewal/readwriter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ func TestKubeconfigReadWriter(t *testing.T) {
t.Fatalf("couldn't write new embedded certificate: %v", err)
}

// Make sure that CA key is not present during Read() as it is not needed.
// This covers testing when the CA is external and not present on the host.
_, caKeyPath := pkiutil.PathsForCertAndKey(dirPKI, caName)
os.Remove(caKeyPath)

// Reads back the new certificate embedded in a kubeconfig writer
readCert, err = kubeconfigReadWriter.Read()
if err != nil {
Expand Down

0 comments on commit d431931

Please sign in to comment.