in main.go [242:323]
func initMTLSConfig(watcher *fsnotify.Watcher) error {
setupLog.Info("mTLS config", "clientSkipVerify", clientSkipVerify, "clientCertPath", clientCertPath,
"clientCertKeyPath", clientCertKeyPath, "caCertPath", caCertPath, "clientCertWatch", clientCertWatch)
// Load client cert information from files
clientCert, err := tls.LoadX509KeyPair(clientCertPath, clientCertKeyPath)
if err != nil {
setupLog.Error(err, "Error loading clientCert pair for mTLS transport", "certPath", clientCertPath, "keyPath", clientCertKeyPath)
return err
}
if watcher != nil {
// If the cert file is a symlink (which is the case when loaded from a secret), then we need to re-add the watch after the
// Right now, it will always be a symlink, so this is just future proofing when the cert gets loaded from a CSI driver
isSymlink := false
clientCertFile, _ := filepath.EvalSymlinks(clientCertPath)
if clientCertFile != clientCertPath {
isSymlink = true
}
// Watch cert files for updates
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
// If the cert was loaded from a secret, then the path will be for a symlink and an update comes in as a REMOVE event
// otherwise, look for a write to the real file
if ((isSymlink && event.Op&fsnotify.Remove == fsnotify.Remove) || (event.Op&fsnotify.Write == fsnotify.Write)) && event.Name == clientCertPath {
clientCertFile, _ := filepath.EvalSymlinks(clientCertPath)
setupLog.Info("mTLS cert file updated", "certPath", clientCertPath, "certFile", clientCertFile)
clientCert, err = tls.LoadX509KeyPair(clientCertPath, clientCertKeyPath)
if err == nil {
// update our global client certificate to the new one
clientCertificate = &clientCert
setupLog.Info("Updated mTLS Http Client after update to cert", "certPath", clientCertPath)
} else {
// will keep using the old cert, which eventually will cause failures when the old cert expires
setupLog.Error(err, "Error loading clientCert pair (after update) for mTLS transport", "certPath", clientCertPath, "keyPath", clientCertKeyPath)
}
// If the symlink we were watching was removed, re-add the watch
if event.Op&fsnotify.Remove == fsnotify.Remove {
err = watcher.Add(clientCertPath)
if err != nil {
setupLog.Error(err, "Re-add fsnotify watch for cert failed", "certPath", clientCertPath)
} else {
setupLog.Info("Re-added watch for symlink to mTLS cert file", "certPath", clientCertPath, "certFile", clientCertFile)
}
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
setupLog.Error(err, "fsnotify error")
}
}
}()
err = watcher.Add(clientCertPath)
if err != nil {
setupLog.Error(err, "Add fsnotify watch for cert failed", "certPath", clientCertPath)
return err
}
setupLog.Info("Added fsnotify watch for mTLS cert file", "certPath", clientCertPath, "certFile", clientCertFile, "isSymlink", isSymlink)
} else {
setupLog.Info("Watch for mTLS cert updates disabled", "certPath", clientCertPath)
}
clientCertificate = &clientCert
mTLSTransport, err := buildTLSTransport()
if err != nil {
return err
}
solr_api.SetMTLSHttpClient(&http.Client{Transport: mTLSTransport})
return nil
}