From 39459f42fc9133eb36d23dc335e02199a7e68e71 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sat, 14 Dec 2019 01:19:03 +0100 Subject: [PATCH] Add fields to load sensitive values from file (#7) --- internal/app/job.go | 15 ++++++++++++--- internal/config/config.go | 5 +++-- internal/config/config.test.yml | 5 +++++ internal/config/config_test.go | 4 ++++ internal/model/mail.go | 2 ++ internal/model/regopts.go | 10 ++++++---- internal/notif/mail/client.go | 15 +++++++++++++-- pkg/docker/tags.go | 2 +- {internal => pkg}/utl/utl.go | 15 +++++++++++++++ 9 files changed, 61 insertions(+), 12 deletions(-) rename {internal => pkg}/utl/utl.go (75%) diff --git a/internal/app/job.go b/internal/app/job.go index d89a6165..fc23d75c 100644 --- a/internal/app/job.go +++ b/internal/app/job.go @@ -5,9 +5,9 @@ import ( "time" "github.com/crazy-max/diun/internal/model" - "github.com/crazy-max/diun/internal/utl" "github.com/crazy-max/diun/pkg/docker" "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/utl" "github.com/rs/zerolog/log" ) @@ -23,11 +23,20 @@ func (di *Diun) createJob(job model.Job) { sublog.Warn().Err(err).Msg("Registry options") } + regUser, err := utl.GetSecret(regOpts.Username, regOpts.UsernameFile) + if err != nil { + log.Warn().Err(err).Msgf("Cannot retrieve username secret for regopts %s", job.Image.RegOptsID) + } + regPassword, err := utl.GetSecret(regOpts.Password, regOpts.PasswordFile) + if err != nil { + log.Warn().Err(err).Msgf("Cannot retrieve password secret for regopts %s", job.Image.RegOptsID) + } + job.Registry, err = docker.NewRegistryClient(docker.RegistryOptions{ Os: job.Image.Os, Arch: job.Image.Arch, - Username: regOpts.Username, - Password: regOpts.Password, + Username: regUser, + Password: regPassword, Timeout: time.Duration(regOpts.Timeout) * time.Second, InsecureTLS: regOpts.InsecureTLS, }) diff --git a/internal/config/config.go b/internal/config/config.go index 0fcc430a..5e6690e8 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,7 @@ import ( "regexp" "github.com/crazy-max/diun/internal/model" - "github.com/crazy-max/diun/internal/utl" + "github.com/crazy-max/diun/pkg/utl" "github.com/imdario/mergo" "github.com/rs/zerolog/log" "gopkg.in/yaml.v2" @@ -63,7 +63,8 @@ func Load(flags model.Flags, version string) (*Config, error) { }, }, Providers: model.Providers{ - Image: []model.PrdImage{}, + Docker: []model.PrdDocker{}, + Image: []model.PrdImage{}, }, } diff --git a/internal/config/config.test.yml b/internal/config/config.test.yml index fd291f27..6b77ea79 100644 --- a/internal/config/config.test.yml +++ b/internal/config/config.test.yml @@ -13,7 +13,9 @@ notif: ssl: false insecure_skip_verify: false username: + username_file: password: + password_file: from: to: webhook: @@ -31,6 +33,9 @@ regopts: bintrayoptions: username: foo password: bar + sensitive: + username_file: /run/secrets/username + password_file: /run/secrets/password providers: docker: diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 1936b86f..f36fc371 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -78,6 +78,10 @@ func TestLoad(t *testing.T) { Username: "foo", Password: "bar", }, + "sensitive": { + UsernameFile: "/run/secrets/username", + PasswordFile: "/run/secrets/password", + }, }, Providers: model.Providers{ Docker: []model.PrdDocker{ diff --git a/internal/model/mail.go b/internal/model/mail.go index 5244b81b..0b15d4d3 100644 --- a/internal/model/mail.go +++ b/internal/model/mail.go @@ -8,7 +8,9 @@ type Mail struct { SSL bool `yaml:"ssl,omitempty"` InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty"` Username string `yaml:"username,omitempty"` + UsernameFile string `yaml:"username_file,omitempty"` Password string `yaml:"password,omitempty"` + PasswordFile string `yaml:"password_file,omitempty"` From string `yaml:"from,omitempty"` To string `yaml:"to,omitempty"` } diff --git a/internal/model/regopts.go b/internal/model/regopts.go index be921c4e..7b4dc112 100644 --- a/internal/model/regopts.go +++ b/internal/model/regopts.go @@ -2,8 +2,10 @@ package model // RegOpts holds registry options configuration type RegOpts struct { - Username string `yaml:"username,omitempty" json:",omitempty"` - Password string `yaml:"password,omitempty" json:",omitempty"` - InsecureTLS bool `yaml:"insecure_tls,omitempty" json:",omitempty"` - Timeout int `yaml:"timeout,omitempty" json:",omitempty"` + Username string `yaml:"username,omitempty" json:",omitempty"` + UsernameFile string `yaml:"username_file,omitempty" json:",omitempty"` + Password string `yaml:"password,omitempty" json:",omitempty"` + PasswordFile string `yaml:"password_file,omitempty" json:",omitempty"` + InsecureTLS bool `yaml:"insecure_tls,omitempty" json:",omitempty"` + Timeout int `yaml:"timeout,omitempty" json:",omitempty"` } diff --git a/internal/notif/mail/client.go b/internal/notif/mail/client.go index 1d8512ac..ddd6aa50 100644 --- a/internal/notif/mail/client.go +++ b/internal/notif/mail/client.go @@ -9,8 +9,10 @@ import ( "github.com/crazy-max/diun/internal/model" "github.com/crazy-max/diun/internal/notif/notifier" + "github.com/crazy-max/diun/pkg/utl" "github.com/go-gomail/gomail" "github.com/matcornic/hermes/v2" + "github.com/rs/zerolog/log" ) // Client represents an active mail notification object @@ -105,11 +107,20 @@ Need help, or have questions? Go to https://github.com/crazy-max/diun and leave } } + username, err := utl.GetSecret(c.cfg.Username, c.cfg.UsernameFile) + if err != nil { + log.Warn().Err(err).Msg("Cannot retrieve username secret for mail notifier") + } + password, err := utl.GetSecret(c.cfg.Password, c.cfg.PasswordFile) + if err != nil { + log.Warn().Err(err).Msg("Cannot retrieve password secret for mail notifier") + } + dialer := &gomail.Dialer{ Host: c.cfg.Host, Port: c.cfg.Port, - Username: c.cfg.Username, - Password: c.cfg.Password, + Username: username, + Password: password, SSL: c.cfg.SSL, TLSConfig: tlsConfig, } diff --git a/pkg/docker/tags.go b/pkg/docker/tags.go index 3f19f1d5..a1453431 100644 --- a/pkg/docker/tags.go +++ b/pkg/docker/tags.go @@ -2,8 +2,8 @@ package docker import ( "github.com/containers/image/docker" - "github.com/crazy-max/diun/internal/utl" "github.com/crazy-max/diun/pkg/docker/registry" + "github.com/crazy-max/diun/pkg/utl" ) type Tags struct { diff --git a/internal/utl/utl.go b/pkg/utl/utl.go similarity index 75% rename from internal/utl/utl.go rename to pkg/utl/utl.go index 9f1baa02..3f2b6081 100644 --- a/internal/utl/utl.go +++ b/pkg/utl/utl.go @@ -1,6 +1,7 @@ package utl import ( + "io/ioutil" "os" "regexp" ) @@ -51,3 +52,17 @@ func GetEnv(key, fallback string) string { } return fallback } + +// GetSecret retrieves secret's value from plaintext or filename if defined +func GetSecret(plaintext, filename string) (string, error) { + if plaintext != "" { + return plaintext, nil + } else if filename != "" { + b, err := ioutil.ReadFile(filename) + if err != nil { + return "", err + } + return string(b), nil + } + return "", nil +}