Skip to content

Commit

Permalink
Merge branch 'stapelberg-certs'
Browse files Browse the repository at this point in the history
Merges #3

Thanks a lot!
  • Loading branch information
mback2k committed Jul 24, 2023
2 parents 583e82e + 9b8bddb commit 54f2bb9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
6 changes: 6 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ type configAcmeLe struct {
ChallengePort int
}

type configTLS struct {
CertPath string
KeyPath string
}

type configVHost struct {
Domain string
Upstream string
Expand All @@ -64,6 +69,7 @@ type config struct {
Domain string
UseSMTPS bool
LetsEncrypt *configAcmeLe
TLS *configTLS
ReadTimeout time.Duration
WriteTimeout time.Duration
MaxMessageBytes int
Expand Down
60 changes: 60 additions & 0 deletions internal/tlsutil/tlsutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package tlsutil

import (
"crypto/tls"
"os"
"os/signal"
"sync"
"syscall"

log "github.com/sirupsen/logrus"
)

type keypairReloader struct {
certMu sync.RWMutex
cert *tls.Certificate
certPath string
keyPath string
}

func NewKeypairReloader(certPath, keyPath string) (*keypairReloader, error) {
result := &keypairReloader{
certPath: certPath,
keyPath: keyPath,
}
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return nil, err
}
result.cert = &cert
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP)
for range c {
log.Printf("Received SIGHUP, reloading TLS certificate and key from %q and %q", certPath, keyPath)
if err := result.maybeReload(); err != nil {
log.Printf("Keeping old TLS certificate because the new one could not be loaded: %v", err)
}
}
}()
return result, nil
}

func (kpr *keypairReloader) maybeReload() error {
newCert, err := tls.LoadX509KeyPair(kpr.certPath, kpr.keyPath)
if err != nil {
return err
}
kpr.certMu.Lock()
defer kpr.certMu.Unlock()
kpr.cert = &newCert
return nil
}

func (kpr *keypairReloader) GetCertificateFunc() func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
return func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
kpr.certMu.RLock()
defer kpr.certMu.RUnlock()
return kpr.cert, nil
}
}
10 changes: 10 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
package main

import (
"crypto/tls"
"runtime"

"github.com/heroku/rollrus"
"github.com/mback2k/smtp-dkim-signer/internal/tlsutil"
"github.com/rollbar/rollbar-go"
"github.com/rollbar/rollbar-go/errors"

Expand All @@ -47,6 +49,14 @@ func setupServer(cfg *config) (*smtp.Server, bool) {
if err != nil {
panic(err)
}
} else if cfg.TLS != nil && cfg.TLS.KeyPath != "" && cfg.TLS.CertPath != "" {
kpr, err := tlsutil.NewKeypairReloader(cfg.TLS.CertPath, cfg.TLS.KeyPath)
if err != nil {
panic(err)
}
server.TLSConfig = &tls.Config{
GetCertificate: kpr.GetCertificateFunc(),
}
}
return server, cfg.UseSMTPS
}
Expand Down

0 comments on commit 54f2bb9

Please sign in to comment.