Allow forcing cert reissuance (#28)

Refreshing the cert should force renewal as opposed to returning
early if the SANs aren't changing. This is currently breaking refresh
of expired certs as per:
https://github.com/rancher/k3s/issues/1621#issuecomment-669464318

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
This commit is contained in:
Brad Davidson
2020-08-10 17:06:11 -07:00
committed by Brad Davidson
parent 479ab335d6
commit 53f6b38760
7 changed files with 117 additions and 60 deletions

View File

@@ -11,6 +11,7 @@ import (
"sync"
"time"
"github.com/rancher/dynamiclistener/cert"
"github.com/rancher/dynamiclistener/factory"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
@@ -22,7 +23,7 @@ type TLSStorage interface {
}
type TLSFactory interface {
Refresh(secret *v1.Secret) (*v1.Secret, error)
Renew(secret *v1.Secret) (*v1.Secret, error)
AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error)
Merge(target *v1.Secret, additional *v1.Secret) (*v1.Secret, bool, error)
Filter(cn ...string) []string
@@ -152,13 +153,18 @@ type listener struct {
func (l *listener) WrapExpiration(days int) net.Listener {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(5 * time.Minute)
time.Sleep(30 * time.Second)
for {
wait := 6 * time.Hour
if err := l.checkExpiration(days); err != nil {
logrus.Errorf("failed to check and refresh dynamic cert: %v", err)
wait = 5 + time.Minute
logrus.Errorf("failed to check and renew dynamic cert: %v", err)
// Don't go into short retry loop if we're using a static (user-provided) cert.
// We will still check and print an error every six hours until the user updates the secret with
// a cert that is not about to expire. Hopefully this will prompt them to take action.
if err != cert.ErrStaticCert {
wait = 5 * time.Minute
}
}
select {
case <-ctx.Done():
@@ -191,22 +197,26 @@ func (l *listener) checkExpiration(days int) error {
return err
}
cert, err := tls.X509KeyPair(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
keyPair, err := tls.X509KeyPair(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
if err != nil {
return err
}
certParsed, err := x509.ParseCertificate(cert.Certificate[0])
certParsed, err := x509.ParseCertificate(keyPair.Certificate[0])
if err != nil {
return err
}
if time.Now().UTC().Add(time.Hour * 24 * time.Duration(days)).After(certParsed.NotAfter) {
secret, err := l.factory.Refresh(secret)
if cert.IsCertExpired(certParsed, days) {
secret, err := l.factory.Renew(secret)
if err != nil {
return err
}
return l.storage.Update(secret)
if err := l.storage.Update(secret); err != nil {
return err
}
// clear version to force cert reload
l.version = ""
}
return nil
@@ -304,7 +314,7 @@ func (l *listener) updateCert(cn ...string) error {
return err
}
if !factory.NeedsUpdate(l.maxSANs, secret, cn...) {
if !factory.IsStatic(secret) && !factory.NeedsUpdate(l.maxSANs, secret, cn...) {
return nil
}
@@ -324,13 +334,6 @@ func (l *listener) updateCert(cn ...string) error {
}
// clear version to force cert reload
l.version = ""
if l.conns != nil {
l.connLock.Lock()
for _, conn := range l.conns {
_ = conn.close()
}
l.connLock.Unlock()
}
}
return nil
@@ -366,6 +369,15 @@ func (l *listener) loadCert() (*tls.Certificate, error) {
return nil, err
}
// cert has changed, close closeWrapper wrapped connections
if l.conns != nil {
l.connLock.Lock()
for _, conn := range l.conns {
_ = conn.close()
}
l.connLock.Unlock()
}
l.cert = &cert
l.version = secret.ResourceVersion
return l.cert, nil