88 lines
1.4 KiB
Go
88 lines
1.4 KiB
Go
package tls
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
const (
|
|
defaultCertFile = "/var/secrets/mail/tls.crt"
|
|
defaultKeyFile = "/var/secrets/mail/tls.key"
|
|
)
|
|
|
|
type CertManager struct {
|
|
cert *tls.Certificate
|
|
|
|
Log *zap.Logger
|
|
|
|
certFile string
|
|
keyFile string
|
|
}
|
|
|
|
func NewCertManager(certFile, keyFile string) (*CertManager, error) {
|
|
if certFile == "" {
|
|
certFile = defaultCertFile
|
|
}
|
|
|
|
if keyFile == "" {
|
|
keyFile = defaultKeyFile
|
|
}
|
|
|
|
cm := &CertManager{
|
|
certFile: certFile,
|
|
keyFile: keyFile,
|
|
}
|
|
|
|
return cm, nil
|
|
}
|
|
|
|
func (cm *CertManager) Get(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
|
if cm.cert == nil {
|
|
return nil, errors.New("no certificate")
|
|
}
|
|
|
|
return cm.cert, nil
|
|
}
|
|
|
|
func (cm *CertManager) Load() error {
|
|
cert, err := tls.LoadX509KeyPair(cm.certFile, cm.keyFile)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to load certificate")
|
|
}
|
|
|
|
cm.cert = &cert
|
|
|
|
return nil
|
|
}
|
|
|
|
func (cm *CertManager) Ready() bool {
|
|
return cm.cert != nil
|
|
}
|
|
|
|
func (cm *CertManager) Watch(ctx context.Context, log *zap.Logger) error {
|
|
cm.Log = log
|
|
|
|
if err := cm.Load(); err != nil {
|
|
log.Error("failed to load initial certificate", zap.Error(err))
|
|
|
|
return err
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case <-time.After(time.Hour):
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
}
|
|
|
|
if err := cm.Load(); err != nil {
|
|
log.Error("failed to reload new certificate", zap.Error(err))
|
|
|
|
continue
|
|
}
|
|
}
|
|
}
|