-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add certificate watcher to queue-proxy
- Loading branch information
Showing
3 changed files
with
146 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package certificate | ||
Check failure on line 1 in pkg/queue/certificate/watcher.go GitHub Actions / style / Golang / Boilerplate Check (go)
|
||
|
||
import ( | ||
"crypto/sha256" | ||
"crypto/tls" | ||
"os" | ||
"path" | ||
"sync" | ||
"time" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
const ( | ||
reloadInterval = 1 * time.Minute | ||
) | ||
|
||
// CertWatcher watches certificate and key files and reloads them if they change on disk. | ||
type CertWatcher struct { | ||
certPath string | ||
certChecksum [sha256.Size]byte | ||
keyPath string | ||
keyChecksum [sha256.Size]byte | ||
|
||
certificate *tls.Certificate | ||
|
||
logger *zap.SugaredLogger | ||
ticker *time.Ticker | ||
stop chan struct{} | ||
mux sync.RWMutex | ||
} | ||
|
||
// NewCertWatcher creates a CertWatcher and watches | ||
// the certificate and key files. It reloads the contents on file change. | ||
// Make sure to stop the CertWatcher using Stop() upon destroy. | ||
func NewCertWatcher(certPath, keyPath string, logger *zap.SugaredLogger) (*CertWatcher, error) { | ||
cw := &CertWatcher{ | ||
certPath: certPath, | ||
keyPath: keyPath, | ||
logger: logger, | ||
ticker: time.NewTicker(reloadInterval), | ||
stop: make(chan struct{}), | ||
mux: sync.RWMutex{}, | ||
} | ||
|
||
certDir := path.Dir(cw.certPath) | ||
keyDir := path.Dir(cw.keyPath) | ||
|
||
cw.logger.Info("Starting to watch the following directories for changes", | ||
zap.String("certDir", certDir), zap.String("keyDir", keyDir)) | ||
|
||
// initial load | ||
cw.loadCert() | ||
|
||
go cw.watch() | ||
|
||
return cw, nil | ||
} | ||
|
||
// Stop shuts down the CertWatcher. Use this with `defer`. | ||
func (cw *CertWatcher) Stop() { | ||
cw.logger.Info("Stopping file watcher") | ||
close(cw.stop) | ||
cw.ticker.Stop() | ||
} | ||
|
||
// GetCertificate returns the server certificate for a client-hello request. | ||
func (cw *CertWatcher) GetCertificate(_ *tls.ClientHelloInfo) (*tls.Certificate, error) { | ||
cw.mux.RLock() | ||
defer cw.mux.RUnlock() | ||
return cw.certificate, nil | ||
} | ||
|
||
func (cw *CertWatcher) watch() { | ||
for { | ||
select { | ||
case <-cw.stop: | ||
return | ||
|
||
case <-cw.ticker.C: | ||
cw.loadCert() | ||
} | ||
} | ||
} | ||
|
||
func (cw *CertWatcher) loadCert() { | ||
var err error | ||
certFile, err := os.ReadFile(cw.certPath) | ||
if err != nil { | ||
cw.logger.Error("failed to load certificate file", zap.String("certPath", cw.certPath), zap.Error(err)) | ||
return | ||
} | ||
keyFile, err := os.ReadFile(cw.keyPath) | ||
if err != nil { | ||
cw.logger.Error("failed to load key file", zap.String("keyPath", cw.keyPath), zap.Error(err)) | ||
return | ||
} | ||
|
||
certChecksum := sha256.Sum256(certFile) | ||
keyChecksum := sha256.Sum256(keyFile) | ||
|
||
if certChecksum != cw.certChecksum || keyChecksum != cw.keyChecksum { | ||
keyPair, err := tls.LoadX509KeyPair(cw.certPath, cw.keyPath) | ||
if err != nil { | ||
cw.logger.Error("failed to load and parse certificate", zap.Error(err)) | ||
return | ||
} | ||
|
||
cw.mux.Lock() | ||
defer cw.mux.Unlock() | ||
|
||
cw.certificate = &keyPair | ||
cw.certChecksum = certChecksum | ||
cw.keyChecksum = keyChecksum | ||
|
||
cw.logger.Info("Certificate and/or key have changed on disk and were reloaded.") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters