Merge df0a78475f into 65037b086c
This commit is contained in:
commit
e1fdae644e
|
|
@ -156,6 +156,8 @@ func NewFlagSet() *pflag.FlagSet {
|
|||
flagSet.String("redis-sentinel-password", "", "Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password`")
|
||||
flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjunction with --redis-use-sentinel")
|
||||
flagSet.String("redis-ca-path", "", "Redis custom CA path")
|
||||
flagSet.String("redis-client-cert-path", "", "Path to PEM-encoded client certificate for mutual TLS when connecting to Redis")
|
||||
flagSet.String("redis-client-key-path", "", "Path to PEM-encoded client private key for mutual TLS when connecting to Redis")
|
||||
flagSet.Bool("redis-insecure-skip-tls-verify", false, "Use insecure TLS connection to redis")
|
||||
flagSet.StringSlice("redis-sentinel-connection-urls", []string{}, "List of Redis sentinel connection URLs (eg redis://[USER[:PASSWORD]@]HOST[:PORT]). Used in conjunction with --redis-use-sentinel")
|
||||
flagSet.Bool("redis-use-cluster", false, "Connect to redis cluster. Must set --redis-cluster-connection-urls to use this feature")
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ type RedisStoreOptions struct {
|
|||
UseCluster bool `flag:"redis-use-cluster" cfg:"redis_use_cluster"`
|
||||
ClusterConnectionURLs []string `flag:"redis-cluster-connection-urls" cfg:"redis_cluster_connection_urls"`
|
||||
CAPath string `flag:"redis-ca-path" cfg:"redis_ca_path"`
|
||||
ClientCertPath string `flag:"redis-client-cert-path" cfg:"redis_client_cert_path"`
|
||||
ClientKeyPath string `flag:"redis-client-key-path" cfg:"redis_client_key_path"`
|
||||
InsecureSkipTLSVerify bool `flag:"redis-insecure-skip-tls-verify" cfg:"redis_insecure_skip_tls_verify"`
|
||||
IdleTimeout int `flag:"redis-connection-idle-timeout" cfg:"redis_connection_idle_timeout"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,21 @@ func setupTLSConfig(opts options.RedisStoreOptions, opt *redis.Options) error {
|
|||
|
||||
opt.TLSConfig.RootCAs = rootCAs
|
||||
}
|
||||
|
||||
if opts.ClientCertPath != "" || opts.ClientKeyPath != "" {
|
||||
if opts.ClientCertPath == "" || opts.ClientKeyPath == "" {
|
||||
return fmt.Errorf("redis client TLS: client certificate path and client private key path must both be set")
|
||||
}
|
||||
clientCert, err := tls.LoadX509KeyPair(opts.ClientCertPath, opts.ClientKeyPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load redis client certificate/key pair: %w", err)
|
||||
}
|
||||
if opt.TLSConfig == nil {
|
||||
/* #nosec */
|
||||
opt.TLSConfig = &tls.Config{}
|
||||
}
|
||||
opt.TLSConfig.Certificates = []tls.Certificate{clientCert}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -321,4 +321,23 @@ var _ = Describe("Redis SessionStore Tests", func() {
|
|||
Expect(opts).To(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Redis TLS client credentials", func() {
|
||||
It("returns an error when only client certificate path is set", func() {
|
||||
_, err := buildStandaloneClient(options.RedisStoreOptions{
|
||||
ConnectionURL: "redis://localhost:6379",
|
||||
ClientCertPath: "/some/path/cert.pem",
|
||||
})
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("must both be set"))
|
||||
})
|
||||
It("returns an error when only client private key path is set", func() {
|
||||
_, err := buildStandaloneClient(options.RedisStoreOptions{
|
||||
ConnectionURL: "redis://localhost:6379",
|
||||
ClientKeyPath: "/some/path/key.pem",
|
||||
})
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("must both be set"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -147,6 +147,62 @@ var _ = Describe("Redis SessionStore Tests", func() {
|
|||
)
|
||||
})
|
||||
|
||||
Context("with mutual TLS (client certificate)", func() {
|
||||
BeforeEach(func() {
|
||||
mr.Close()
|
||||
// Require a client certificate on the wire; RequireAndVerifyClientCert would
|
||||
// reject the test suite cert (ExtKeyUsageServerAuth only, no clientAuth EKU).
|
||||
var err error
|
||||
mr, err = miniredis.RunTLS(&tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ClientAuth: tls.RequireAnyClientCert,
|
||||
})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
Context("with standalone", func() {
|
||||
tests.RunSessionStoreTests(
|
||||
func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
|
||||
opts.Type = options.RedisSessionStoreType
|
||||
opts.Redis.ConnectionURL = redissProtocol + mr.Addr()
|
||||
opts.Redis.CAPath = caPath
|
||||
opts.Redis.ClientCertPath = caPath
|
||||
opts.Redis.ClientKeyPath = keyPath
|
||||
|
||||
var err error
|
||||
ss, err = NewRedisSessionStore(opts, cookieOpts)
|
||||
return ss, err
|
||||
},
|
||||
func(d time.Duration) error {
|
||||
mr.FastForward(d)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
Context("with cluster", func() {
|
||||
tests.RunSessionStoreTests(
|
||||
func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
|
||||
clusterAddr := redissProtocol + mr.Addr()
|
||||
opts.Type = options.RedisSessionStoreType
|
||||
opts.Redis.ClusterConnectionURLs = []string{clusterAddr}
|
||||
opts.Redis.UseCluster = true
|
||||
opts.Redis.CAPath = caPath
|
||||
opts.Redis.ClientCertPath = caPath
|
||||
opts.Redis.ClientKeyPath = keyPath
|
||||
|
||||
var err error
|
||||
ss, err = NewRedisSessionStore(opts, cookieOpts)
|
||||
return ss, err
|
||||
},
|
||||
func(d time.Duration) error {
|
||||
mr.FastForward(d)
|
||||
return nil
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Context("with insecure TLS connection", func() {
|
||||
tests.RunSessionStoreTests(
|
||||
func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ func (l *wrappedRedisLogger) Printf(_ context.Context, format string, v ...inter
|
|||
}
|
||||
|
||||
var (
|
||||
cert tls.Certificate
|
||||
caPath string
|
||||
cert tls.Certificate
|
||||
caPath string
|
||||
keyPath string
|
||||
)
|
||||
|
||||
func TestRedis(t *testing.T) {
|
||||
|
|
@ -61,8 +62,16 @@ var _ = BeforeSuite(func() {
|
|||
_, err = certFile.Write(certData)
|
||||
defer certFile.Close()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
keyFile, err := os.CreateTemp("", "key.*.pem")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
keyPath = keyFile.Name()
|
||||
_, err = keyFile.Write(keyOut.Bytes())
|
||||
defer keyFile.Close()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
|
||||
var _ = AfterSuite(func() {
|
||||
Expect(os.Remove(caPath)).ToNot(HaveOccurred())
|
||||
Expect(os.Remove(keyPath)).ToNot(HaveOccurred())
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue