From f2395863ed5b87b35e39d8fab4f741cb215c9ab7 Mon Sep 17 00:00:00 2001 From: Emma OBrien Date: Wed, 9 Feb 2022 13:03:50 -0800 Subject: [PATCH] added username in config for redis auth --- README.md | 4 ++-- config/config.go | 4 ++++ config/config_test.go | 17 +++++++++++++++++ config/file_config.go | 9 +++++++++ config/mock.go | 8 ++++++++ config_complete.toml | 6 ++++++ internal/peer/redis.go | 7 ++++++- 7 files changed, 52 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7385f2a82f..74db7a164d 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ To enable the redis-based config: When launched in redis-config mode, Refinery needs a redis host to use for managing the list of peers in the Refinery cluster. This hostname and port can be specified in one of two ways: -- set the `REFINERY_REDIS_HOST` environment variable (and optionally the `REFINERY_REDIS_PASSWORD` environment variable) -- set the `RedisHost` field in the config file (and optionally the `RedisPassword` field in the config file) +- set the `REFINERY_REDIS_HOST` environment variable (and optionally the `REFINERY_REDIS_USERNAME` and `REFINERY_REDIS_PASSWORD` environment variables) +- set the `RedisHost` field in the config file (and optionally the `RedisUsername` and `RedisPassword` fields in the config file) The Redis host should be a hostname and a port, for example `redis.mydomain.com:6379`. The example config file has `localhost:6379` which obviously will not work with more than one host. When TLS is required to connect to the Redis instance, set the `UseTLS` config to `true`. diff --git a/config/config.go b/config/config.go index b364375ee5..989ae9f815 100644 --- a/config/config.go +++ b/config/config.go @@ -45,6 +45,10 @@ type Config interface { // management. GetRedisHost() (string, error) + // GetRedisUsername returns the username of a Redis instance to use for peer + // management. + GetRedisUsername() (string, error) + // GetRedisPassword returns the password of a Redis instance to use for peer // management. GetRedisPassword() (string, error) diff --git a/config/config_test.go b/config/config_test.go index 7e440fdffd..7e3940bd02 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -46,6 +46,23 @@ func TestRedisHostEnvVar(t *testing.T) { } } +func TestRedisUsernameEnvVar(t *testing.T) { + const username = "admin" + const envVarName = "REFINERY_REDIS_USERNAME" + os.Setenv(envVarName, username) + defer os.Unsetenv(envVarName) + + c, err := NewConfig("../config.toml", "../rules.toml", func(err error) {}) + + if err != nil { + t.Error(err) + } + + if d, _ := c.GetRedisUsername(); d != username { + t.Error("received", d, "expected", username) + } +} + func TestRedisPasswordEnvVar(t *testing.T) { const password = "admin1234" const envVarName = "REFINERY_REDIS_PASSWORD" diff --git a/config/file_config.go b/config/file_config.go index a7a7ec1eb6..cc8952ad20 100644 --- a/config/file_config.go +++ b/config/file_config.go @@ -82,6 +82,7 @@ type PeerManagementConfig struct { Type string `validate:"required,oneof= file redis"` Peers []string `validate:"dive,url"` RedisHost string + RedisUsername string RedisPassword string UseTLS bool UseTLSInsecure bool @@ -96,6 +97,7 @@ func NewConfig(config, rules string, errorCallback func(error)) (Config, error) c.BindEnv("GRPCListenAddr", "REFINERY_GRPC_LISTEN_ADDRESS") c.BindEnv("PeerManagement.RedisHost", "REFINERY_REDIS_HOST") + c.BindEnv("PeerManagement.RedisUsername", "REFINERY_REDIS_USERNAME") c.BindEnv("PeerManagement.RedisPassword", "REFINERY_REDIS_PASSWORD") c.BindEnv("HoneycombLogger.LoggerAPIKey", "REFINERY_HONEYCOMB_API_KEY") c.BindEnv("HoneycombMetrics.MetricsAPIKey", "REFINERY_HONEYCOMB_API_KEY") @@ -414,6 +416,13 @@ func (f *fileConfig) GetRedisHost() (string, error) { return f.config.GetString("PeerManagement.RedisHost"), nil } +func (f *fileConfig) GetRedisUsername() (string, error) { + f.mux.RLock() + defer f.mux.RUnlock() + + return f.config.GetString("PeerManagement.RedisUsername"), nil +} + func (f *fileConfig) GetRedisPassword() (string, error) { f.mux.RLock() defer f.mux.RUnlock() diff --git a/config/mock.go b/config/mock.go index a4025c1042..35a70a5846 100644 --- a/config/mock.go +++ b/config/mock.go @@ -38,6 +38,8 @@ type MockConfig struct { GetPeersVal []string GetRedisHostErr error GetRedisHostVal string + GetRedisUsernameErr error + GetRedisUsernameVal string GetRedisPasswordErr error GetRedisPasswordVal string GetUseTLSErr error @@ -173,6 +175,12 @@ func (m *MockConfig) GetRedisHost() (string, error) { return m.GetRedisHostVal, m.GetRedisHostErr } +func (m *MockConfig) GetRedisUsername() (string, error) { + m.Mux.RLock() + defer m.Mux.RUnlock() + + return m.GetRedisUsernameVal, m.GetRedisUsernameErr +} func (m *MockConfig) GetRedisPassword() (string, error) { m.Mux.RLock() defer m.Mux.RUnlock() diff --git a/config_complete.toml b/config_complete.toml index 87fe76e793..f8de3b3674 100644 --- a/config_complete.toml +++ b/config_complete.toml @@ -152,6 +152,12 @@ Metrics = "honeycomb" # Not eligible for live reload. # RedisHost = "localhost:6379" +# RedisUsername is the username used to connect to redis for peer cluster membership management. +# If the environment variable 'REFINERY_REDIS_USERNAME' is set it takes +# precedence and this value is ignored. +# Not eligible for live reload. +# RedisUsername = "" + # RedisPassword is the password used to connect to redis for peer cluster membership management. # If the environment variable 'REFINERY_REDIS_PASSWORD' is set it takes # precedence and this value is ignored. diff --git a/internal/peer/redis.go b/internal/peer/redis.go index 71c8a9a876..4507e17843 100644 --- a/internal/peer/redis.go +++ b/internal/peer/redis.go @@ -65,7 +65,7 @@ func newRedisPeers(c config.Config) (Peers, error) { // a 1 second delay between attempts to allow the redis process to init var ( conn redis.Conn - err error + err error ) for timeout := time.After(10 * time.Second); ; { select { @@ -190,6 +190,11 @@ func buildOptions(c config.Config) []redis.DialOption { redis.DialDatabase(0), // TODO enable multiple databases for multiple samproxies } + username, _ := c.GetRedisUsername() + if username != "" { + options = append(options, redis.DialUsername(username)) + } + password, _ := c.GetRedisPassword() if password != "" { options = append(options, redis.DialPassword(password))