mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-06-02 23:27:22 +02:00
Add ability to configure username for Redis cluster connections (#2381)
* Initial attempt. * Add CHANGELOG entry. * Drop commented-out Sentinel test. --------- Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
This commit is contained in:
parent
4c2bf5a2fe
commit
f3dbca600f
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
## Changes since v7.5.1
|
## Changes since v7.5.1
|
||||||
|
|
||||||
|
- [#2381](https://github.com/oauth2-proxy/oauth2-proxy/pull/2381) Allow username authentication to Redis cluster (@rossigee)
|
||||||
- [#2345](https://github.com/oauth2-proxy/oauth2-proxy/pull/2345) Log error details when failed loading CSRF cookie (@charvadzo)
|
- [#2345](https://github.com/oauth2-proxy/oauth2-proxy/pull/2345) Log error details when failed loading CSRF cookie (@charvadzo)
|
||||||
- [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll)
|
- [#2128](https://github.com/oauth2-proxy/oauth2-proxy/pull/2128) Update dependencies (@vllvll)
|
||||||
- [#2269](https://github.com/oauth2-proxy/oauth2-proxy/pull/2269) Added Azure China (and other air gaped cloud) support (@mblaschke)
|
- [#2269](https://github.com/oauth2-proxy/oauth2-proxy/pull/2269) Added Azure China (and other air gaped cloud) support (@mblaschke)
|
||||||
|
@ -144,16 +144,17 @@ func NewFlagSet() *pflag.FlagSet {
|
|||||||
flagSet.String("ready-path", "/ready", "the ready endpoint that can be used for deep health checks")
|
flagSet.String("ready-path", "/ready", "the ready endpoint that can be used for deep health checks")
|
||||||
flagSet.String("session-store-type", "cookie", "the session storage provider to use")
|
flagSet.String("session-store-type", "cookie", "the session storage provider to use")
|
||||||
flagSet.Bool("session-cookie-minimal", false, "strip OAuth tokens from cookie session stores if they aren't needed (cookie session store only)")
|
flagSet.Bool("session-cookie-minimal", false, "strip OAuth tokens from cookie session stores if they aren't needed (cookie session store only)")
|
||||||
flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage (eg: redis://HOST[:PORT])")
|
flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage (eg: redis://[USER[:PASSWORD]@]HOST[:PORT])")
|
||||||
|
flagSet.String("redis-username", "", "Redis username. Applicable for Redis configurations where ACL has been configured. Will override any username set in `--redis-connection-url`")
|
||||||
flagSet.String("redis-password", "", "Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url`")
|
flagSet.String("redis-password", "", "Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url`")
|
||||||
flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-connection-urls to use this feature")
|
flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-connection-urls to use this feature")
|
||||||
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-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-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-ca-path", "", "Redis custom CA path")
|
||||||
flagSet.Bool("redis-insecure-skip-tls-verify", false, "Use insecure TLS connection 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://HOST[:PORT]). Used in conjunction with --redis-use-sentinel")
|
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")
|
flagSet.Bool("redis-use-cluster", false, "Connect to redis cluster. Must set --redis-cluster-connection-urls to use this feature")
|
||||||
flagSet.StringSlice("redis-cluster-connection-urls", []string{}, "List of Redis cluster connection URLs (eg redis://HOST[:PORT]). Used in conjunction with --redis-use-cluster")
|
flagSet.StringSlice("redis-cluster-connection-urls", []string{}, "List of Redis cluster connection URLs (eg redis://[USER[:PASSWORD]@]HOST[:PORT]). Used in conjunction with --redis-use-cluster")
|
||||||
flagSet.Int("redis-connection-idle-timeout", 0, "Redis connection idle timeout seconds, if Redis timeout option is non-zero, the --redis-connection-idle-timeout must be less then Redis timeout option")
|
flagSet.Int("redis-connection-idle-timeout", 0, "Redis connection idle timeout seconds, if Redis timeout option is non-zero, the --redis-connection-idle-timeout must be less then Redis timeout option")
|
||||||
flagSet.String("signature-key", "", "GAP-Signature request signature key (algorithm:secretkey)")
|
flagSet.String("signature-key", "", "GAP-Signature request signature key (algorithm:secretkey)")
|
||||||
flagSet.Bool("gcp-healthchecks", false, "Enable GCP/GKE healthcheck endpoints")
|
flagSet.Bool("gcp-healthchecks", false, "Enable GCP/GKE healthcheck endpoints")
|
||||||
|
@ -23,6 +23,7 @@ type CookieStoreOptions struct {
|
|||||||
// RedisStoreOptions contains configuration options for the RedisSessionStore.
|
// RedisStoreOptions contains configuration options for the RedisSessionStore.
|
||||||
type RedisStoreOptions struct {
|
type RedisStoreOptions struct {
|
||||||
ConnectionURL string `flag:"redis-connection-url" cfg:"redis_connection_url"`
|
ConnectionURL string `flag:"redis-connection-url" cfg:"redis_connection_url"`
|
||||||
|
Username string `flag:"redis-username" cfg:"redis_username"`
|
||||||
Password string `flag:"redis-password" cfg:"redis_password"`
|
Password string `flag:"redis-password" cfg:"redis_password"`
|
||||||
UseSentinel bool `flag:"redis-use-sentinel" cfg:"redis_use_sentinel"`
|
UseSentinel bool `flag:"redis-use-sentinel" cfg:"redis_use_sentinel"`
|
||||||
SentinelPassword string `flag:"redis-sentinel-password" cfg:"redis_sentinel_password"`
|
SentinelPassword string `flag:"redis-sentinel-password" cfg:"redis_sentinel_password"`
|
||||||
|
@ -100,6 +100,13 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) {
|
|||||||
return nil, fmt.Errorf("could not parse redis urls: %v", err)
|
return nil, fmt.Errorf("could not parse redis urls: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Password != "" {
|
||||||
|
opt.Password = opts.Password
|
||||||
|
}
|
||||||
|
if opts.Username != "" {
|
||||||
|
opt.Username = opts.Username
|
||||||
|
}
|
||||||
|
|
||||||
if err := setupTLSConfig(opts, opt); err != nil {
|
if err := setupTLSConfig(opts, opt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -108,6 +115,7 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) {
|
|||||||
MasterName: opts.SentinelMasterName,
|
MasterName: opts.SentinelMasterName,
|
||||||
SentinelAddrs: addrs,
|
SentinelAddrs: addrs,
|
||||||
SentinelPassword: opts.SentinelPassword,
|
SentinelPassword: opts.SentinelPassword,
|
||||||
|
Username: opts.Username,
|
||||||
Password: opts.Password,
|
Password: opts.Password,
|
||||||
TLSConfig: opt.TLSConfig,
|
TLSConfig: opt.TLSConfig,
|
||||||
ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
|
ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
|
||||||
@ -122,12 +130,20 @@ func buildClusterClient(opts options.RedisStoreOptions) (Client, error) {
|
|||||||
return nil, fmt.Errorf("could not parse redis urls: %v", err)
|
return nil, fmt.Errorf("could not parse redis urls: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.Password != "" {
|
||||||
|
opt.Password = opts.Password
|
||||||
|
}
|
||||||
|
if opts.Username != "" {
|
||||||
|
opt.Username = opts.Username
|
||||||
|
}
|
||||||
|
|
||||||
if err := setupTLSConfig(opts, opt); err != nil {
|
if err := setupTLSConfig(opts, opt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
client := redis.NewClusterClient(&redis.ClusterOptions{
|
client := redis.NewClusterClient(&redis.ClusterOptions{
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
|
Username: opts.Username,
|
||||||
Password: opts.Password,
|
Password: opts.Password,
|
||||||
TLSConfig: opt.TLSConfig,
|
TLSConfig: opt.TLSConfig,
|
||||||
ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
|
ConnMaxIdleTime: time.Duration(opts.IdleTimeout) * time.Second,
|
||||||
@ -146,6 +162,9 @@ func buildStandaloneClient(opts options.RedisStoreOptions) (Client, error) {
|
|||||||
if opts.Password != "" {
|
if opts.Password != "" {
|
||||||
opt.Password = opts.Password
|
opt.Password = opts.Password
|
||||||
}
|
}
|
||||||
|
if opts.Username != "" {
|
||||||
|
opt.Username = opts.Username
|
||||||
|
}
|
||||||
|
|
||||||
if err := setupTLSConfig(opts, opt); err != nil {
|
if err := setupTLSConfig(opts, opt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const redisUsername = "testuser"
|
||||||
const redisPassword = "0123456789abcdefghijklmnopqrstuv"
|
const redisPassword = "0123456789abcdefghijklmnopqrstuv"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -231,6 +232,56 @@ var _ = Describe("Redis SessionStore Tests", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("with a redis username and password", func() {
|
||||||
|
BeforeEach(func() {
|
||||||
|
mr.RequireUserAuth(redisUsername, redisPassword)
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
mr.RequireUserAuth("", "")
|
||||||
|
})
|
||||||
|
|
||||||
|
tests.RunSessionStoreTests(
|
||||||
|
func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
|
||||||
|
// Set the connection URL
|
||||||
|
opts.Type = options.RedisSessionStoreType
|
||||||
|
opts.Redis.ConnectionURL = "redis://" + redisUsername + "@" + mr.Addr()
|
||||||
|
opts.Redis.Password = redisPassword
|
||||||
|
|
||||||
|
// Capture the session store so that we can close the client
|
||||||
|
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 := "redis://" + redisUsername + "@" + mr.Addr()
|
||||||
|
opts.Type = options.RedisSessionStoreType
|
||||||
|
opts.Redis.ClusterConnectionURLs = []string{clusterAddr}
|
||||||
|
opts.Redis.UseCluster = true
|
||||||
|
opts.Redis.Username = redisUsername
|
||||||
|
opts.Redis.Password = redisPassword
|
||||||
|
|
||||||
|
// Capture the session store so that we can close the client
|
||||||
|
var err error
|
||||||
|
ss, err = NewRedisSessionStore(opts, cookieOpts)
|
||||||
|
return ss, err
|
||||||
|
},
|
||||||
|
func(d time.Duration) error {
|
||||||
|
mr.FastForward(d)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Context("with TLS connection", func() {
|
Context("with TLS connection", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
mr.Close()
|
mr.Close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user