Skip to content

Commit

Permalink
Add redis password and TLS basic configuration to peer management. (#201
Browse files Browse the repository at this point in the history
)
  • Loading branch information
leonardo7w authored Dec 28, 2020
1 parent 1e2de43 commit 304d6cf
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 10 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ 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
- set the `RedisHost` field in the config file
- 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)

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.
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`.

## How sampling decisions are made

Expand Down
8 changes: 8 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ type Config interface {
// management.
GetRedisHost() (string, error)

// GetRedisPassword returns the password of a Redis instance to use for peer
// management.
GetRedisPassword() (string, error)

// GetUseTLS returns true when TLS must be enabled to dial the Redis instance to
// use for peer management.
GetUseTLS() (bool, error)

// GetHoneycombAPI returns the base URL (protocol, hostname, and port) of
// the upstream Honeycomb API server
GetHoneycombAPI() (string, error)
Expand Down
18 changes: 17 additions & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestRedisEnvVar(t *testing.T) {
func TestRedisHostEnvVar(t *testing.T) {
host := "redis.magic:1337"
os.Setenv("REFINERY_REDIS_HOST", host)
defer os.Unsetenv("REFINERY_REDIS_HOST")
Expand All @@ -28,6 +28,22 @@ func TestRedisEnvVar(t *testing.T) {
}
}

func TestRedisPasswordEnvVar(t *testing.T) {
password := "admin1234"
os.Setenv("REFINERY_REDIS_PASSWORD", password)
defer os.Unsetenv("REFINERY_REDIS_PASSWORD")

c, err := NewConfig("../config.toml", "../rules.toml", func(err error) {})

if err != nil {
t.Error(err)
}

if d, _ := c.GetRedisPassword(); d != password {
t.Error("received", d, "expected", password)
}
}

func TestReload(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "")
assert.NoError(t, err)
Expand Down
18 changes: 18 additions & 0 deletions config/file_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ type PeerManagementConfig struct {
Type string `validate:"required,oneof= file redis"`
Peers []string `validate:"dive,url"`
RedisHost string
RedisPassword string
UseTLS bool
IdentifierInterfaceName string
UseIPV6Identifier bool
RedisIdentifier string
Expand All @@ -116,11 +118,13 @@ func NewConfig(config, rules string, errorCallback func(error)) (Config, error)
c := viper.New()

c.BindEnv("PeerManagement.RedisHost", "REFINERY_REDIS_HOST")
c.BindEnv("PeerManagement.RedisPassword", "REFINERY_REDIS_PASSWORD")
c.SetDefault("ListenAddr", "0.0.0.0:8080")
c.SetDefault("PeerListenAddr", "0.0.0.0:8081")
c.SetDefault("APIKeys", []string{"*"})
c.SetDefault("PeerManagement.Peers", []string{"http://127.0.0.1:8081"})
c.SetDefault("PeerManagement.Type", "file")
c.SetDefault("PeerManagement.UseTLS", false)
c.SetDefault("PeerManagement.UseIPV6Identifier", false)
c.SetDefault("HoneycombAPI", "https://api.honeycomb.io")
c.SetDefault("Logger", "logrus")
Expand Down Expand Up @@ -403,6 +407,20 @@ func (f *fileConfig) GetRedisHost() (string, error) {
return f.config.GetString("PeerManagement.RedisHost"), nil
}

func (f *fileConfig) GetRedisPassword() (string, error) {
f.mux.RLock()
defer f.mux.RUnlock()

return f.config.GetString("PeerManagement.RedisPassword"), nil
}

func (f *fileConfig) GetUseTLS() (bool, error) {
f.mux.RLock()
defer f.mux.RUnlock()

return f.config.GetBool("PeerManagement.UseTLS"), nil
}

func (f *fileConfig) GetIdentifierInterfaceName() (string, error) {
f.mux.RLock()
defer f.mux.RUnlock()
Expand Down
16 changes: 16 additions & 0 deletions config/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type MockConfig struct {
GetPeersVal []string
GetRedisHostErr error
GetRedisHostVal string
GetRedisPasswordErr error
GetRedisPasswordVal string
GetUseTLSErr error
GetUseTLSVal bool
GetSamplerTypeErr error
GetSamplerTypeVal interface{}
GetMetricsTypeErr error
Expand Down Expand Up @@ -150,6 +154,18 @@ func (m *MockConfig) GetRedisHost() (string, error) {

return m.GetRedisHostVal, m.GetRedisHostErr
}
func (m *MockConfig) GetRedisPassword() (string, error) {
m.Mux.RLock()
defer m.Mux.RUnlock()

return m.GetRedisPasswordVal, m.GetRedisPasswordErr
}
func (m *MockConfig) GetUseTLS() (bool, error) {
m.Mux.RLock()
defer m.Mux.RUnlock()

return m.GetUseTLSVal, m.GetUseTLSErr
}
func (m *MockConfig) GetMetricsType() (string, error) {
m.Mux.RLock()
defer m.Mux.RUnlock()
Expand Down
10 changes: 10 additions & 0 deletions config_complete.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ Metrics = "honeycomb"
# Not eligible for live reload.
# RedisHost = "localhost:6379"

# 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.
# Not eligible for live reload.
# RedisPassword = ""

# UseTLS enables TLS when connecting to redis for peer cluster membership management, and sets the MinVersion to 1.2.
# Not eligible for live reload.
# UseTLS = false

# IdentifierInterfaceName is optional. By default, when using RedisHost, Refinery will use
# the local hostname to identify itself to other peers in Redis. If your environment
# requires that you use IPs as identifiers (for example, if peers can't resolve eachother
Expand Down
35 changes: 29 additions & 6 deletions internal/peer/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package peer

import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
Expand Down Expand Up @@ -51,18 +52,14 @@ func newRedisPeers(c config.Config) (Peers, error) {
redisHost = "localhost:6379"
}

options := buildOptions(c)
pool := &redis.Pool{
MaxIdle: 3,
MaxActive: 30,
IdleTimeout: 5 * time.Minute,
Wait: true,
Dial: func() (redis.Conn, error) {
return redis.Dial(
"tcp", redisHost,
redis.DialReadTimeout(1*time.Second),
redis.DialConnectTimeout(1*time.Second),
redis.DialDatabase(0), // TODO enable multiple databases for multiple samproxies
)
return redis.Dial("tcp", redisHost, options...)
},
}

Expand Down Expand Up @@ -167,6 +164,32 @@ func (p *redisPeers) watchPeers() {
}
}

func buildOptions(c config.Config) []redis.DialOption {
options := []redis.DialOption{
redis.DialReadTimeout(1 * time.Second),
redis.DialConnectTimeout(1 * time.Second),
redis.DialDatabase(0), // TODO enable multiple databases for multiple samproxies
}

password, _ := c.GetRedisPassword()
if password != "" {
options = append(options, redis.DialPassword(password))
}

useTLS, _ := c.GetUseTLS()
if useTLS {
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS12,
}
options = append(options,
redis.DialTLSConfig(tlsConfig),
redis.DialTLSSkipVerify(true),
redis.DialUseTLS(true))
}

return options
}

func publicAddr(c config.Config) (string, error) {
// compute the public version of my peer listen address
listenAddr, _ := c.GetPeerListenAddr()
Expand Down

0 comments on commit 304d6cf

Please sign in to comment.