mirror of
https://github.com/pomerium/pomerium.git
synced 2025-05-12 00:27:35 +02:00
config: detect underlying file changes (#1775)
* wip * cleanup * add test * use uuid for temp dir, derive root CA path from filemgr for tests * fix comment * fix double close * use latest notify
This commit is contained in:
parent
c99994bed8
commit
10912add67
16 changed files with 500 additions and 99 deletions
|
@ -1,9 +1,14 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/fileutil"
|
||||
)
|
||||
|
||||
// Config holds pomerium configuration options.
|
||||
|
@ -125,3 +130,83 @@ func (src *FileOrEnvironmentSource) GetConfig() *Config {
|
|||
|
||||
return src.config
|
||||
}
|
||||
|
||||
// FileWatcherSource is a config source which triggers a change any time a file in the options changes.
|
||||
type FileWatcherSource struct {
|
||||
underlying Source
|
||||
watcher *fileutil.Watcher
|
||||
|
||||
mu sync.RWMutex
|
||||
computedConfig *Config
|
||||
version string
|
||||
|
||||
ChangeDispatcher
|
||||
}
|
||||
|
||||
// NewFileWatcherSource creates a new FileWatcherSource.
|
||||
func NewFileWatcherSource(underlying Source) *FileWatcherSource {
|
||||
src := &FileWatcherSource{
|
||||
underlying: underlying,
|
||||
watcher: fileutil.NewWatcher(),
|
||||
}
|
||||
|
||||
ch := src.watcher.Bind()
|
||||
go func() {
|
||||
for range ch {
|
||||
src.check(underlying.GetConfig())
|
||||
}
|
||||
}()
|
||||
underlying.OnConfigChange(func(cfg *Config) {
|
||||
src.check(cfg)
|
||||
})
|
||||
src.check(underlying.GetConfig())
|
||||
|
||||
return src
|
||||
}
|
||||
|
||||
// GetConfig gets the underlying config.
|
||||
func (src *FileWatcherSource) GetConfig() *Config {
|
||||
src.mu.RLock()
|
||||
defer src.mu.RUnlock()
|
||||
return src.computedConfig
|
||||
}
|
||||
|
||||
func (src *FileWatcherSource) check(cfg *Config) {
|
||||
src.mu.Lock()
|
||||
defer src.mu.Unlock()
|
||||
|
||||
src.watcher.Clear()
|
||||
|
||||
h := sha256.New()
|
||||
fs := []string{
|
||||
cfg.Options.CAFile,
|
||||
cfg.Options.CertFile,
|
||||
cfg.Options.ClientCAFile,
|
||||
cfg.Options.DataBrokerStorageCAFile,
|
||||
cfg.Options.DataBrokerStorageCertFile,
|
||||
cfg.Options.DataBrokerStorageCertKeyFile,
|
||||
cfg.Options.KeyFile,
|
||||
cfg.Options.PolicyFile,
|
||||
}
|
||||
for _, f := range fs {
|
||||
_, _ = h.Write([]byte{0})
|
||||
bs, err := ioutil.ReadFile(f)
|
||||
if err == nil {
|
||||
src.watcher.Add(f)
|
||||
_, _ = h.Write(bs)
|
||||
}
|
||||
}
|
||||
|
||||
version := hex.EncodeToString(h.Sum(nil))
|
||||
if src.version != version {
|
||||
src.version = version
|
||||
|
||||
// update the computed config
|
||||
src.computedConfig = cfg.Clone()
|
||||
src.computedConfig.Options.Certificates = nil
|
||||
_ = src.computedConfig.Options.Validate()
|
||||
|
||||
// trigger a change
|
||||
src.Trigger(src.computedConfig)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue