From e7be7d73e5a4e42bce2e7e939d7cbceabadc66f8 Mon Sep 17 00:00:00 2001 From: kaiyou <dev@kaiyou.fr> Date: Sun, 17 Dec 2023 20:53:52 +0100 Subject: [PATCH] General rewrite of the certificates code to support renewing certificates --- services/certs.go | 15 +++++++-- services/meta.go | 83 ++++++++++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/services/certs.go b/services/certs.go index 5902790..19425b0 100644 --- a/services/certs.go +++ b/services/certs.go @@ -105,10 +105,16 @@ var pkiManager = &Unit{ }, Wake: func(u *Unit, c *Cluster) error { for name, certs := range c.state.Certificates { - if certs.TLS.Cert == nil || certs.API.Cert == nil { + if certs == nil || certs.TLS == nil || certs.API == nil { + continue + } + if certs.TLS.Cert == nil && certs.TLS.CSR != nil { c.pki.TLS.Sign(certs.TLS, pekahi.NewServerTemplate([]string{name}, certs.TLS.CSR.IPAddresses)) + u.Manager.Logger.Info("signed node tls cert", "node", name) + } + if certs.API.Cert == nil && certs.API.CSR != nil { c.pki.API.Sign(certs.API, pekahi.NewClientTemplate("system:node:"+name, "system:nodes")) - u.Manager.Logger.Info("signed node cert", "node", name) + u.Manager.Logger.Info("signed node api cert", "node", name) } } return nil @@ -223,6 +229,9 @@ var pkiNode = &Unit{ return nil }, Ready: func(u *Unit, c *Cluster) bool { - return c.certs.TLS.Cert != nil && c.certs.API.Cert != nil + return (c.certs.TLS.Cert != nil && + c.certs.API.Cert != nil && + c.certs.TLS.Key.PublicKey.Equal(c.certs.TLS.Cert.PublicKey)) && + c.certs.API.Key.PublicKey.Equal(c.certs.API.Cert.PublicKey) }, } diff --git a/services/meta.go b/services/meta.go index 3f98dba..7566de0 100644 --- a/services/meta.go +++ b/services/meta.go @@ -1,6 +1,7 @@ package services import ( + "bytes" "encoding/json" "net/netip" @@ -79,47 +80,61 @@ func (s *HeptoState) String() string { func (s *HeptoState) Merge(b []byte) (bool, error) { remote := new(HeptoState) err := json.Unmarshal(b, remote) + // If state cannot decode or no pki is shared in state, bail if err != nil { return false, err } - if s.PKI == nil || remote.PKI == nil { - return false, nil + // Track changes + changed := false + if s.PKI != nil && remote.PKI != nil { + // Grab CA Certificates + updateCA := func(local, remote *pekahi.Certificate) { + if local == nil || remote == nil { + return + } + if local.Cert == nil && remote.Cert != nil { + local.Cert = remote.Cert + local.Save() + changed = true + } + } + updateCA(s.PKI.TLS, remote.PKI.TLS) + updateCA(s.PKI.API, remote.PKI.API) + updateCA(s.PKI.Kubelet, remote.PKI.Kubelet) + updateCA(s.PKI.Proxy, remote.PKI.Proxy) } - change := false - change = mergeCert(s.PKI.TLS, remote.PKI.TLS) || change - change = mergeCert(s.PKI.Kubelet, remote.PKI.Kubelet) || change - change = mergeCert(s.PKI.API, remote.PKI.API) || change - change = mergeCert(s.PKI.Proxy, remote.PKI.Proxy) || change for name, remoteCerts := range remote.Certificates { + if remoteCerts == nil { + continue + } certs, ok := s.Certificates[name] - if ok { - change = mergeCert(certs.TLS, remoteCerts.TLS) || change - change = mergeCert(certs.API, remoteCerts.API) || change - } else { + if !ok || certs == nil { s.Certificates[name] = remoteCerts - change = true + changed = true + continue } + // Grab a node CSR or our certificates if available + updateCSROrCert := func(local, remote *pekahi.Certificate) { + if local == nil || remote == nil { + return + } + // If this is not our own data, remote is providing a CSR we do not know about yet, save it + if local.Key == nil && remote.CSR != nil && (local.CSR == nil || !bytes.Equal(local.CSR.Raw, remote.CSR.Raw)) { + local.Cert = remote.Cert + local.CSR = remote.CSR + local.Save() + changed = true + } + // If remote is providing a cert that matches our key and CSR, save it + if local.Key != nil && local.CSR != nil && local.Cert == nil && remote.Cert != nil && local.Key.PublicKey.Equal(remote.Cert.PublicKey) { + local.Cert = remote.Cert + local.Save() + changed = true + } + } + updateCSROrCert(certs.API, remoteCerts.API) + updateCSROrCert(certs.TLS, remoteCerts.TLS) } - return change, nil -} - -// Merge a single node or master certificate -func mergeCert(local *pekahi.Certificate, remote *pekahi.Certificate) bool { - change := false - // Do not merge nothing - if remote == nil { - return change - } - // Import CSR to master for signing - if local.CSR == nil && remote.CSR != nil { - local.CSR = remote.CSR - change = true - } - // Import and save cert back to node - if local.Cert == nil && remote.Cert != nil { - local.Cert = remote.Cert - local.Save() - change = true - } - return change + // Grab signed ceritificates for the kubelet of current node + return changed, nil } -- GitLab