diff --git a/factory/gen.go b/factory/gen.go index ff15a93..50bf94a 100644 --- a/factory/gen.go +++ b/factory/gen.go @@ -119,6 +119,12 @@ func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) { return t.generateCert(secret, cn...) } +func (t *TLS) Regenerate(secret *v1.Secret) (*v1.Secret, error) { + cns := cns(secret) + secret, _, err := t.generateCert(nil, cns...) + return secret, err +} + func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) { secret = secret.DeepCopy() if secret == nil { diff --git a/listener.go b/listener.go index 4328935..096145c 100644 --- a/listener.go +++ b/listener.go @@ -27,6 +27,7 @@ type TLSFactory interface { 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 + Regenerate(secret *v1.Secret) (*v1.Secret, error) } type SetFactory interface { @@ -74,11 +75,18 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c setter.SetFactory(dynamicListener.factory) } + if config.RegenerateCerts != nil && config.RegenerateCerts() { + if err := dynamicListener.regenerateCerts(); err != nil { + return nil, nil, err + } + } + if config.ExpirationDaysCheck == 0 { config.ExpirationDaysCheck = 30 } tlsListener := tls.NewListener(dynamicListener.WrapExpiration(config.ExpirationDaysCheck), dynamicListener.tlsConfig) + return tlsListener, dynamicListener.cacheHandler(), nil } @@ -129,6 +137,7 @@ type Config struct { MaxSANs int ExpirationDaysCheck int CloseConnOnCertChange bool + RegenerateCerts func() bool FilterCN func(...string) []string } @@ -180,6 +189,30 @@ func (l *listener) WrapExpiration(days int) net.Listener { } } +// regenerateCerts regenerates the used certificates and +// updates the secret. +func (l *listener) regenerateCerts() error { + l.Lock() + defer l.Unlock() + + secret, err := l.storage.Get() + if err != nil { + return err + } + + newSecret, err := l.factory.Regenerate(secret) + if err != nil { + return err + } + if err := l.storage.Update(newSecret); err != nil { + return err + } + // clear version to force cert reload + l.version = "" + + return nil +} + func (l *listener) checkExpiration(days int) error { l.Lock() defer l.Unlock()