mirror of
https://github.com/k0sproject/k0s.git
synced 2026-10-28 11:04:40 +08:00
Renew etcd certificates generated by custom etcd CA
k0s renews certs issued by a custom cluster CA, and it should do the same for certs issued by a custom etcd CA. Fixes #7795 Signed-off-by: Dmitrii Shishliannikov <dshishliannikov@mirantis.com>
This commit is contained in:
1 parent
3cd439fbb2
commit
2b9f3a214b
2 files changed
+50
-8
No files matched your search
@@ -17,28 +17,43 @@ type CustomCASuite struct {
|
||||
common.BootlooseSuite
|
||||
}
|
||||
|
||||
func (s *CustomCASuite) initCA(ssh *common.SSHConnection, dir, cn string) string {
|
||||
err := ssh.Exec(s.Context(), "sh -e", common.SSHStreams{
|
||||
//nolint:dupword // this is a script
|
||||
In: strings.NewReader(strings.NewReplacer("{dir}", dir, "{cn}", cn).Replace(`
|
||||
mkdir -p {dir}
|
||||
command -v openssl || apk add openssl
|
||||
openssl genrsa -out {dir}/ca.key 4096
|
||||
openssl req -x509 -new -nodes -key {dir}/ca.key -sha256 -days 365 -out {dir}/ca.crt -subj "/CN={cn}"
|
||||
`)),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cert, err := ssh.ExecWithOutput(s.Context(), fmt.Sprintf("cat %s/ca.crt", dir))
|
||||
s.Require().NoError(err)
|
||||
|
||||
return cert
|
||||
}
|
||||
|
||||
func (s *CustomCASuite) TestK0sGetsUp() {
|
||||
// Create an custom certificate to prove that k0s manage to work with it
|
||||
ssh, err := s.SSH(s.Context(), s.ControllerNode(0))
|
||||
s.Require().NoError(err)
|
||||
defer ssh.Disconnect()
|
||||
|
||||
caCert := s.initCA(ssh, "/var/lib/k0s/pki", "Test CA")
|
||||
etcdCACert := s.initCA(ssh, "/var/lib/k0s/pki/etcd", "Test Etcd CA")
|
||||
|
||||
err = ssh.Exec(s.Context(), "sh -e", common.SSHStreams{
|
||||
//nolint:dupword // this is a script
|
||||
In: strings.NewReader(fmt.Sprintf(`
|
||||
K0S_PATH=%q
|
||||
IP_ADDRESS=%q
|
||||
mkdir -p /var/lib/k0s/pki /var/lib/k0s/manifests/test
|
||||
apk add openssl
|
||||
openssl genrsa -out /var/lib/k0s/pki/ca.key 4096
|
||||
openssl req -x509 -new -nodes -key /var/lib/k0s/pki/ca.key -sha256 -days 365 -out /var/lib/k0s/pki/ca.crt -subj "/CN=Test CA"
|
||||
mkdir -p /var/lib/k0s/manifests/test
|
||||
"$K0S_PATH" token pre-shared --cert /var/lib/k0s/pki/ca.crt --url https://"$IP_ADDRESS":6443/ --out /var/lib/k0s/manifests/test
|
||||
`, s.K0sFullPath, s.GetControllerIPAddress(0))),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
cert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/ca.crt")
|
||||
s.Require().NoError(err)
|
||||
token, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/manifests/test/token_* && rm /var/lib/k0s/manifests/test/token_*")
|
||||
s.Require().NoError(err)
|
||||
|
||||
@@ -56,11 +71,19 @@ func (s *CustomCASuite) TestK0sGetsUp() {
|
||||
|
||||
newCert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/ca.crt")
|
||||
s.Require().NoError(err)
|
||||
s.Equal(cert, newCert)
|
||||
s.Equal(caCert, newCert)
|
||||
|
||||
newEtcdCert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/etcd/ca.crt")
|
||||
s.Require().NoError(err)
|
||||
s.Equal(etcdCACert, newEtcdCert)
|
||||
|
||||
// Validate that k0s renews certificates with custom CA
|
||||
k0sAPICert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/k0s-api.crt")
|
||||
s.Require().NoError(err, "Failed to obtain k0s-api certificate")
|
||||
|
||||
etcdServerCert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/etcd/server.crt")
|
||||
s.Require().NoError(err, "Failed to obtain etcd server certificate")
|
||||
|
||||
s.Require().NoError(s.StopController(s.ControllerNode(0)))
|
||||
s.Require().NoError(s.StartController(s.ControllerNode(0)))
|
||||
|
||||
@@ -69,6 +92,9 @@ func (s *CustomCASuite) TestK0sGetsUp() {
|
||||
s.Require().NoError(err, "Failed to obtain new k0s certificate")
|
||||
s.Require().NotEqual(k0sAPICert, newK0sAPICert, "k0s-api certificate was not renewed")
|
||||
|
||||
newEtcdServerCert, err := ssh.ExecWithOutput(s.Context(), "cat /var/lib/k0s/pki/etcd/server.crt")
|
||||
s.Require().NoError(err, "Failed to obtain new etcd server certificate")
|
||||
s.Require().NotEqual(etcdServerCert, newEtcdServerCert, "etcd server certificate was not renewed")
|
||||
}
|
||||
|
||||
func TestCustomCASuite(t *testing.T) {
|
||||
|
||||
@@ -223,6 +223,16 @@ func (m *Manager) isManagedByK0s(cert *certinfo.Certificate) (bool, error) {
|
||||
return false, fmt.Errorf("unable to parse ca certificate: %w", err)
|
||||
}
|
||||
|
||||
etcdCA, err := certinfo.ParseCertificateFile(filepath.Join(m.K0sVars.EtcdCertDir, "ca.crt"))
|
||||
if err != nil {
|
||||
// etcd CA is created separately from the cluster CA
|
||||
// and may not available right away on the first start,
|
||||
// this is expected and should not result in an error
|
||||
logrus.Warnf("unable to parse etcd ca certificate: %v ", err)
|
||||
// fall back to the default etcd CA
|
||||
etcdCA = &certinfo.Certificate{Subject: certinfo.Name{CommonName: "etcd-ca"}}
|
||||
}
|
||||
|
||||
switch cert.Issuer.CommonName {
|
||||
case "kubernetes-ca":
|
||||
return true, nil
|
||||
@@ -236,6 +246,12 @@ func (m *Manager) isManagedByK0s(cert *certinfo.Certificate) (bool, error) {
|
||||
}
|
||||
logrus.Warnf("certificate issued by %q, but no ca.key found, not renewing the certificate %q", ca.Subject.CommonName, cert.Subject.CommonName)
|
||||
return false, nil
|
||||
case etcdCA.Subject.CommonName:
|
||||
if file.Exists(filepath.Join(m.K0sVars.EtcdCertDir, "ca.key")) {
|
||||
return true, nil
|
||||
}
|
||||
logrus.Warnf("certificate issued by %q, but no ca.key found, not renewing the certificate %q", etcdCA.Subject.CommonName, cert.Subject.CommonName)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
||||
Reference in new issue
Block a user