diff --git a/pkg/cacheutil/redis_client.go b/pkg/cacheutil/redis_client.go index 13ffd661a04..8c3dbdc7d6f 100644 --- a/pkg/cacheutil/redis_client.go +++ b/pkg/cacheutil/redis_client.go @@ -5,7 +5,6 @@ package cacheutil import ( "context" - "crypto/tls" "fmt" "sync" "time" @@ -21,6 +20,7 @@ import ( "github.com/thanos-io/thanos/pkg/extprom" "github.com/thanos-io/thanos/pkg/gate" + thanos_tls "github.com/thanos-io/thanos/pkg/tls" ) var ( @@ -112,12 +112,26 @@ type RedisClientConfig struct { // in the client's handshake to support virtual hosting unless it is // an IP address. TLSServerName string `yaml:"tls_server_name"` + + // TLSClientCert is the certificate file used for Client Authentication. If used + // the setting TLSClientKey must also be configured corresponding key file + TLSClientCert string `yaml:"tls_client_cert"` + + // TLSClientKey is the Key file used for Client Authentication. If used + // the setting TLSClientCert must also be configured corresponding certificate + // file. + TLSClientKey string `yaml:"tls_client_key"` + + // TLSCaCert is the certificate file containing the certificates used as the + // certificate authorities for the connection. + TLSCaCert string `yaml:"tls_ca_cert"` } func (c *RedisClientConfig) validate() error { if c.Addr == "" { return errors.New("no redis addr provided") } + return nil } @@ -169,10 +183,14 @@ func NewRedisClientWithConfig(logger log.Logger, name string, config RedisClient } if config.TLSEnabled { - opts.TLSConfig = &tls.Config{ - InsecureSkipVerify: config.TLSInsecureSkipVerify, - ServerName: config.TLSServerName, + tlsConfig, err := thanos_tls.NewClientConfig(logger, config.TLSClientCert, config.TLSClientKey, + config.TLSCaCert, config.TLSServerName, config.TLSInsecureSkipVerify) + + if err != nil { + return nil, err } + + opts.TLSConfig = tlsConfig } redisClient := redis.NewClient(opts) diff --git a/pkg/cacheutil/redis_client_test.go b/pkg/cacheutil/redis_client_test.go index 1fb611c0198..5af8b24658e 100644 --- a/pkg/cacheutil/redis_client_test.go +++ b/pkg/cacheutil/redis_client_test.go @@ -136,3 +136,80 @@ func TestRedisClient(t *testing.T) { }) } } + +func TestValidateRedisConfig(t *testing.T) { + assert_ok := func(t *testing.T, _ interface{}, e error) { testutil.Ok(t, e) } + assert_not_ok := func(t *testing.T, _ interface{}, e error) { testutil.NotOk(t, e) } + + tests := []struct { + name string + config func() RedisClientConfig + assert func(*testing.T, interface{}, error) + }{ + { + name: "simpleConfig", + config: func() RedisClientConfig { + cfg := DefaultRedisClientConfig + cfg.Addr = "127.0.0.1:6789" + cfg.Username = "user" + cfg.Password = "1234" + return cfg + }, + assert: assert_ok, + }, + { + name: "tlsConfig", + config: func() RedisClientConfig { + cfg := DefaultRedisClientConfig + cfg.Addr = "127.0.0.1:6789" + cfg.Username = "user" + cfg.Password = "1234" + cfg.TLSEnabled = true + return cfg + }, + assert: assert_ok, + }, + { + name: "tlsClientCertConfig", + config: func() RedisClientConfig { + cfg := DefaultRedisClientConfig + cfg.Addr = "127.0.0.1:6789" + cfg.Username = "user" + cfg.Password = "1234" + cfg.TLSEnabled = true + cfg.TLSClientCert = "cert/client.pem" + cfg.TLSClientKey = "cert/client.key" + return cfg + }, + assert: assert_ok, + }, + { + name: "tlsInvalidClientCertConfig", + config: func() RedisClientConfig { + cfg := DefaultRedisClientConfig + cfg.Addr = "127.0.0.1:6789" + cfg.Username = "user" + cfg.Password = "1234" + cfg.TLSEnabled = true + cfg.TLSClientKey = "cert/client.key" + return cfg + }, + assert: assert_not_ok, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg := tt.config() + + logger := log.NewLogfmtLogger(os.Stderr) + reg := prometheus.NewRegistry() + val, err := NewRedisClientWithConfig(logger, tt.name, cfg, reg) + if val != nil { + defer val.Stop() + } + tt.assert(t, val, err) + }) + } + +}