Skip to content

Commit 7622f1a

Browse files
committed
Regenerate apiserver.crt when APIEndpoint.AlternativeNames has something new
Signed-off-by: Artiom Diomin <artiom@kubermatic.com>
1 parent af7d964 commit 7622f1a

5 files changed

Lines changed: 56 additions & 16 deletions

File tree

pkg/certificate/ca.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ import (
2929
)
3030

3131
const (
32-
KubernetesCACertPath = "/etc/kubernetes/pki/ca.crt"
33-
KubernetesCAKeyPath = "/etc/kubernetes/pki/ca.key"
32+
KubernetesAPIServerPath = "/etc/kubernetes/pki/apiserver.crt"
33+
KubernetesCACertPath = "/etc/kubernetes/pki/ca.crt"
34+
KubernetesCAKeyPath = "/etc/kubernetes/pki/ca.key"
3435
)
3536

36-
func kubernetesPKIFiles() []string {
37+
func kubernetesPKICAFiles() []string {
3738
return []string{
3839
KubernetesCACertPath,
3940
KubernetesCAKeyPath,
@@ -49,7 +50,7 @@ func kubernetesPKIFiles() []string {
4950
func DownloadKubePKI(s *state.State, _ *kubeoneapi.HostConfig, _ executor.Interface) error {
5051
sshfs := s.Runner.NewFS()
5152

52-
for _, fname := range kubernetesPKIFiles() {
53+
for _, fname := range kubernetesPKICAFiles() {
5354
buf, err := fs.ReadFile(sshfs, fname)
5455
if err != nil {
5556
return err
@@ -74,13 +75,13 @@ func DownloadKubePKI(s *state.State, _ *kubeoneapi.HostConfig, _ executor.Interf
7475
func UploadKubePKI(s *state.State, _ *kubeoneapi.HostConfig, _ executor.Interface) error {
7576
sshfs := s.Runner.NewFS()
7677

77-
for _, fname := range kubernetesPKIFiles() {
78+
for _, fname := range kubernetesPKICAFiles() {
7879
buf, found := s.Configuration.KubernetesPKI[fname]
7980
if !found {
80-
return fmt.Errorf("file %q found found in PKI", fname)
81+
return fmt.Errorf("file %q not found in PKI", fname)
8182
}
8283

83-
if err := sshfs.MkdirAll(path.Dir(fname), 0700); err != nil {
84+
if err := sshfs.MkdirAll(path.Dir(fname), 0o700); err != nil {
8485
return err
8586
}
8687

@@ -95,7 +96,7 @@ func UploadKubePKI(s *state.State, _ *kubeoneapi.HostConfig, _ executor.Interfac
9596
return err
9697
}
9798

98-
if err = fw.Chmod(0600); err != nil {
99+
if err = fw.Chmod(0o600); err != nil {
99100
return err
100101
}
101102

pkg/certificate/certificate.go

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ import (
2121
"crypto/ecdsa"
2222
"crypto/rsa"
2323
"crypto/x509"
24+
"encoding/pem"
2425
"fmt"
26+
"io/fs"
2527
"os"
28+
"slices"
2629
"strings"
2730
"time"
2831

@@ -93,7 +96,7 @@ func CAKeyPair(config *configupload.Configuration) (crypto.Signer, *x509.Certifi
9396

9497
func NewSignedKubernetesServiceTLSCert(name, namespace, domain string, caKey crypto.Signer, caCert *x509.Certificate) (map[string]string, error) {
9598
serviceCommonName := strings.Join([]string{name, namespace, "svc"}, ".")
96-
serviceFQDNCommonName := strings.Join([]string{serviceCommonName, domain, ""}, ".")
99+
serviceFQDNCommonName := strings.Join([]string{serviceCommonName, domain}, ".")
97100

98101
altdnsNames := []string{
99102
serviceFQDNCommonName,
@@ -140,7 +143,43 @@ func RenewAll(st *state.State) error {
140143
logger := ctx.Logger.WithField("node", node.PublicAddress)
141144
logger.Infoln("Renew certificates...")
142145

143-
_, _, err := ctx.Runner.RunRaw("sudo kubeadm certs renew all")
146+
sshfs := ctx.Runner.NewFS()
147+
apiserverCertFile, err := fs.ReadFile(sshfs, KubernetesAPIServerPath)
148+
if err != nil {
149+
return fail.SSH(err, "reading Kubernetes API server certificate")
150+
}
151+
152+
apiserverPEM, _ := pem.Decode(apiserverCertFile)
153+
if apiserverPEM == nil {
154+
return fail.Runtime(fmt.Errorf("PEM block is empty"), "decoding Kubernetes API server certificate PEM")
155+
}
156+
157+
apiserverCert, err := x509.ParseCertificate(apiserverPEM.Bytes)
158+
if err != nil {
159+
return fail.Runtime(err, "parsing Kubernetes API server certificate")
160+
}
161+
162+
needToRecreateAPIServerCerts := false
163+
for _, san := range ctx.Cluster.APIEndpoint.AlternativeNames {
164+
if !slices.Contains(apiserverCert.DNSNames, san) {
165+
needToRecreateAPIServerCerts = true
166+
}
167+
}
168+
169+
var certsCmd strings.Builder
170+
if needToRecreateAPIServerCerts {
171+
fmt.Fprintf(&certsCmd, "sudo rm %q\n", KubernetesAPIServerPath)
172+
kubeadmInitAllCertsCmd, serr := scripts.KubeadmCertsAll(ctx.WorkDir, node.ID, ctx.KubeadmVerboseFlag())
173+
if serr != nil {
174+
return serr
175+
}
176+
certsCmd.WriteString(kubeadmInitAllCertsCmd)
177+
certsCmd.WriteString("\n")
178+
}
179+
180+
certsCmd.WriteString("sudo kubeadm certs renew all")
181+
182+
_, _, err = ctx.Runner.RunRaw(certsCmd.String())
144183
if err != nil {
145184
return fail.SSH(err, "renewing certificates")
146185
}

pkg/scripts/kubeadm.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ var (
3939
sudo find /etc/kubernetes/pki/ -name *.crt -exec chmod 600 {} \;
4040
`)
4141

42-
kubeadmCertScriptTemplate = heredoc.Doc(`
42+
kubeadmCertsAllScriptTemplate = heredoc.Doc(`
4343
sudo kubeadm {{ .VERBOSE }} init phase certs all \
4444
--config={{ .WORK_DIR }}/cfg/control_plane_full_{{ .NODE_ID }}.yaml
4545
sudo find /etc/kubernetes/pki/ -name *.crt -exec chmod 600 {} \;
@@ -97,14 +97,14 @@ func KubeadmJoinWorker(workdir string, nodeID int, verboseFlag string) (string,
9797
return result, fail.Runtime(err, "rendering kubeadmWorkerJoinScriptTemplate script")
9898
}
9999

100-
func KubeadmCert(workdir string, nodeID int, verboseFlag string) (string, error) {
101-
result, err := Render(kubeadmCertScriptTemplate, Data{
100+
func KubeadmCertsAll(workdir string, nodeID int, verboseFlag string) (string, error) {
101+
result, err := Render(kubeadmCertsAllScriptTemplate, Data{
102102
"WORK_DIR": workdir,
103103
"NODE_ID": nodeID,
104104
"VERBOSE": verboseFlag,
105105
})
106106

107-
return result, fail.Runtime(err, "rendering kubeadmCertScriptTemplate script")
107+
return result, fail.Runtime(err, "rendering kubeadmCertsAllScriptTemplate script")
108108
}
109109

110110
func KubeadmInit(workdir string, nodeID int, verboseFlag, token, tokenTTL string, skipPhases string) (string, error) {

pkg/scripts/kubeadm_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func TestKubeadmCert(t *testing.T) {
146146
for _, tt := range tests {
147147
t.Run(tt.name, func(t *testing.T) {
148148
t.Parallel()
149-
got, err := KubeadmCert(tt.args.workdir, tt.args.nodeID, tt.args.verboseFlag)
149+
got, err := KubeadmCertsAll(tt.args.workdir, tt.args.nodeID, tt.args.verboseFlag)
150150
if !errors.Is(err, tt.err) {
151151
t.Errorf("KubeadmCert() error = %v, wantErr %v", err, tt.err)
152152

pkg/tasks/controlplane.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func joinControlPlaneNodeInternal(s *state.State, node *kubeoneapi.HostConfig, c
5555

5656
func kubeadmCertsExecutor(s *state.State, node *kubeoneapi.HostConfig, _ executor.Interface) error {
5757
s.Logger.Infoln("Ensuring Certificates...")
58-
cmd, err := scripts.KubeadmCert(s.WorkDir, node.ID, s.KubeadmVerboseFlag())
58+
cmd, err := scripts.KubeadmCertsAll(s.WorkDir, node.ID, s.KubeadmVerboseFlag())
5959
if err != nil {
6060
return err
6161
}

0 commit comments

Comments
 (0)