Watch for symlinked certs in container envs (#6282)

Fixes #6278
master
Harshavardhana 6 years ago committed by kannappanr
parent eab947cf42
commit 1103ad2d08
  1. 57
      pkg/certs/certs.go

@ -18,8 +18,10 @@ package certs
import ( import (
"crypto/tls" "crypto/tls"
"os"
"path/filepath" "path/filepath"
"sync" "sync"
"time"
"github.com/rjeczalik/notify" "github.com/rjeczalik/notify"
) )
@ -46,6 +48,14 @@ type LoadX509KeyPairFunc func(certFile, keyFile string) (tls.Certificate, error)
// New initializes a new certs monitor. // New initializes a new certs monitor.
func New(certFile, keyFile string, loadCert LoadX509KeyPairFunc) (*Certs, error) { func New(certFile, keyFile string, loadCert LoadX509KeyPairFunc) (*Certs, error) {
certFileIsLink, err := checkSymlink(certFile)
if err != nil {
return nil, err
}
keyFileIsLink, err := checkSymlink(keyFile)
if err != nil {
return nil, err
}
c := &Certs{ c := &Certs{
certFile: certFile, certFile: certFile,
keyFile: keyFile, keyFile: keyFile,
@ -55,13 +65,56 @@ func New(certFile, keyFile string, loadCert LoadX509KeyPairFunc) (*Certs, error)
e: make(chan notify.EventInfo, 1), e: make(chan notify.EventInfo, 1),
} }
if err := c.watch(); err != nil { if certFileIsLink && keyFileIsLink {
return nil, err if err := c.watchSymlinks(); err != nil {
return nil, err
}
} else {
if err := c.watch(); err != nil {
return nil, err
}
} }
return c, nil return c, nil
} }
func checkSymlink(file string) (bool, error) {
st, err := os.Lstat(file)
if err != nil {
return false, err
}
return st.Mode()&os.ModeSymlink == os.ModeSymlink, nil
}
// watchSymlinks reloads symlinked files since fsnotify cannot watch
// on symbolic links.
func (c *Certs) watchSymlinks() (err error) {
c.Lock()
c.cert, err = c.loadCert(c.certFile, c.keyFile)
c.Unlock()
if err != nil {
return err
}
go func() {
for {
select {
case <-c.e:
// Once stopped exits this routine.
return
case <-time.After(24 * time.Hour):
cert, cerr := c.loadCert(c.certFile, c.keyFile)
if cerr != nil {
continue
}
c.Lock()
c.cert = cert
c.Unlock()
}
}
}()
return nil
}
// watch starts watching for changes to the certificate // watch starts watching for changes to the certificate
// and key files. On any change the certificate and key // and key files. On any change the certificate and key
// are reloaded. If there is an issue the loading will fail // are reloaded. If there is an issue the loading will fail

Loading…
Cancel
Save