kubeadm: validate local etcd certficates during expiration checks

In case stacked etcd is used, the code that does expiration checks
does not validate if the etcd CA is "external" (missing key)
and if the etcd CA signed certificates are valid.

Add a new function UsingExternalEtcdCA() similar to existing functions
for the cluster CA and front-proxy CA, that performs the checks for
missing etcd CA key and certificate validity.

This function only runs for stacked etcd, since if etcd is external
kubeadm does not track any certs signed by that etcd CA.

This fixes a bug where the etcd CA will be reported as local even
if the etcd/ca.key is missing during "certs check-expiration".
This commit is contained in:
Lubomir I. Ivanov 2021-12-08 20:37:58 +02:00
parent 2daa3415ec
commit 6603cf6357
2 changed files with 37 additions and 1 deletions

View File

@ -381,6 +381,38 @@ func UsingExternalFrontProxyCA(cfg *kubeadmapi.ClusterConfiguration) (bool, erro
return true, nil
}
// UsingExternalEtcdCA determines whether the user is relying on an external etcd CA. We currently implicitly determine this is the case
// when the etcd CA Cert is present but the etcd CA Key is not.
// In case we are using an external etcd CA, the function validates the certificates signed by etcd CA that should be provided by the user.
func UsingExternalEtcdCA(cfg *kubeadmapi.ClusterConfiguration) (bool, error) {
if err := validateCACert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName, "", "etcd CA"}); err != nil {
return false, err
}
path := filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdCAKeyName)
if _, err := os.Stat(path); !os.IsNotExist(err) {
return false, nil
}
if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName, kubeadmconstants.APIServerEtcdClientCertAndKeyBaseName, "apiserver etcd client"}); err != nil {
return true, err
}
if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName, kubeadmconstants.EtcdServerCertAndKeyBaseName, "etcd server"}); err != nil {
return true, err
}
if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName, kubeadmconstants.EtcdPeerCertAndKeyBaseName, "etcd peer"}); err != nil {
return true, err
}
if err := validateSignedCert(certKeyLocation{cfg.CertificatesDir, kubeadmconstants.EtcdCACertAndKeyBaseName, kubeadmconstants.EtcdHealthcheckClientCertAndKeyBaseName, "etcd health-check client"}); err != nil {
return true, err
}
return true, nil
}
// validateCACert tries to load a x509 certificate from pkiDir and validates that it is a CA
func validateCACert(l certKeyLocation) error {
// Check CA Cert

View File

@ -374,7 +374,11 @@ func (rm *Manager) IsExternallyManaged(caBaseName string) (bool, error) {
}
return externallyManaged, nil
case kubeadmconstants.EtcdCACertAndKeyBaseName:
return false, nil
externallyManaged, err := certsphase.UsingExternalEtcdCA(rm.cfg)
if err != nil {
return false, errors.Wrapf(err, "Error checking external CA condition for %s certificate authority", caBaseName)
}
return externallyManaged, nil
default:
return false, errors.Errorf("unknown certificate authority %s", caBaseName)
}