git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #714 from grnhse/redis-sentinel-password

Support Password & SentinelPassword in Redis session store

commit8515da3e914938e9f0474d0120c86e869aa42297 authorJoel Speed <Joel.speed@hotmail.co.uk> dateFri 14 Aug 2020, 14:09 (6 years ago) parent35ed7a351a9062
6 files changed+102−3
CHANGELOG.md+1 docs/configuration/configuration.md+2 pkg/apis/options/options.go+2 pkg/apis/options/sessions.go+2 pkg/sessions/redis/redis_store.go+10−3 pkg/sessions/redis/redis_store_test.go+85
CHANGELOG.md+1
@@ -11,6 +11,7 @@
1111
1212## Changes since v6.0.0
1313
14+- [#714](https://github.com/oauth2-proxy/oauth2-proxy/pull/714) Support passwords with Redis session stores (@NickMeves)
1415- [#719](https://github.com/oauth2-proxy/oauth2-proxy/pull/719) Add Gosec fixes to areas that are intermittently flagged on PRs (@NickMeves)
1516- [#718](https://github.com/oauth2-proxy/oauth2-proxy/pull/718) Allow Logging to stdout with separate Error Log Channel
1617- [#690](https://github.com/oauth2-proxy/oauth2-proxy/pull/690) Address GoSec security findings & remediate (@NickMeves)
docs/configuration/configuration.md+2
@@ -99,6 +99,8 @@ An example [oauth2-proxy.cfg]({{ site.gitweb }}/contrib/oauth2-proxy.cfg.example
9999| `--redirect-url` | string | the OAuth Redirect URL, e.g. `"https://internalapp.yourcompany.com/oauth2/callback"` | |
100100| `--redis-cluster-connection-urls` | string \| list | List of Redis cluster connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-cluster` | |
101101| `--redis-connection-url` | string | URL of redis server for redis session storage (e.g. `redis://HOST[:PORT]`) | |
102+| `--redis-password` | string | Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url` | |
103+| `--redis-sentinel-password` | string | Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password` | |
102104| `--redis-sentinel-master-name` | string | Redis sentinel master name. Used in conjunction with `--redis-use-sentinel` | |
103105| `--redis-sentinel-connection-urls` | string \| list | List of Redis sentinel connection URLs (e.g. `redis://HOST[:PORT]`). Used in conjunction with `--redis-use-sentinel` | |
104106| `--redis-use-cluster` | bool | Connect to redis cluster. Must set `--redis-cluster-connection-urls` to use this feature | false |
pkg/apis/options/options.go+2
@@ -230,7 +230,9 @@ func NewFlagSet() *pflag.FlagSet {
230230 flagSet.String("session-store-type", "cookie", "the session storage provider to use")
231231 flagSet.Bool("session-cookie-minimal", false, "strip OAuth tokens from cookie session stores if they aren't needed (cookie session store only)")
232232 flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage (eg: redis://HOST[:PORT])")
233+ flagSet.String("redis-password", "", "Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url`")
233234 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")
235+ flagSet.String("redis-sentinel-password", "", "Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password`")
234236 flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjunction with --redis-use-sentinel")
235237 flagSet.String("redis-ca-path", "", "Redis custom CA path")
236238 flagSet.Bool("redis-insecure-skip-tls-verify", false, "Use insecure TLS connection to redis")
pkg/apis/options/sessions.go+2
@@ -23,7 +23,9 @@ type CookieStoreOptions struct {
2323// RedisStoreOptions contains configuration options for the RedisSessionStore.
2424type RedisStoreOptions struct {
2525 ConnectionURL string `flag:"redis-connection-url" cfg:"redis_connection_url"`
26+ Password string `flag:"redis-password" cfg:"redis_password"`
2627 UseSentinel bool `flag:"redis-use-sentinel" cfg:"redis_use_sentinel"`
28+ SentinelPassword string `flag:"redis-sentinel-password" cfg:"redis_sentinel_password"`
2729 SentinelMasterName string `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name"`
2830 SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls"`
2931 UseCluster bool `flag:"redis-use-cluster" cfg:"redis_use_cluster"`
pkg/sessions/redis/redis_store.go+10−3
@@ -88,8 +88,10 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) {
8888 return nil, fmt.Errorf("could not parse redis urls: %v", err)
8989 }
9090 client := redis.NewFailoverClient(&redis.FailoverOptions{
91− MasterName: opts.SentinelMasterName,
92− SentinelAddrs: addrs,
91+ MasterName: opts.SentinelMasterName,
92+ SentinelAddrs: addrs,
93+ SentinelPassword: opts.SentinelPassword,
94+ Password: opts.Password,
9395 })
9496 return newClient(client), nil
9597}
@@ -101,7 +103,8 @@ func buildClusterClient(opts options.RedisStoreOptions) (Client, error) {
101103 return nil, fmt.Errorf("could not parse redis urls: %v", err)
102104 }
103105 client := redis.NewClusterClient(&redis.ClusterOptions{
104− Addrs: addrs,
106+ Addrs: addrs,
107+ Password: opts.Password,
105108 })
106109 return newClusterClient(client), nil
107110}
@@ -114,6 +117,10 @@ func buildStandaloneClient(opts options.RedisStoreOptions) (Client, error) {
114117 return nil, fmt.Errorf("unable to parse redis url: %s", err)
115118 }
116119
120+ if opts.Password != "" {
121+ opt.Password = opts.Password
122+ }
123+
117124 if opts.InsecureSkipTLSVerify {
118125 opt.TLSConfig.InsecureSkipVerify = true
119126 }
pkg/sessions/redis/redis_store_test.go+85
@@ -18,6 +18,8 @@ import (
1818 . "github.com/onsi/gomega"
1919)
2020
21+const redisPassword = "0123456789abcdefghijklmnopqrstuv"
22+
2123func TestSessionStore(t *testing.T) {
2224 logger.SetOutput(GinkgoWriter)
2325
@@ -127,4 +129,87 @@ var _ = Describe("Redis SessionStore Tests", func() {
127129 },
128130 )
129131 })
132+
133+ Context("with a redis password", func() {
134+ BeforeEach(func() {
135+ mr.RequireAuth(redisPassword)
136+ })
137+
138+ AfterEach(func() {
139+ mr.RequireAuth("")
140+ })
141+
142+ tests.RunSessionStoreTests(
143+ func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
144+ // Set the connection URL
145+ opts.Type = options.RedisSessionStoreType
146+ opts.Redis.ConnectionURL = "redis://" + mr.Addr()
147+ opts.Redis.Password = redisPassword
148+
149+ // Capture the session store so that we can close the client
150+ var err error
151+ ss, err = NewRedisSessionStore(opts, cookieOpts)
152+ return ss, err
153+ },
154+ func(d time.Duration) error {
155+ mr.FastForward(d)
156+ return nil
157+ },
158+ )
159+
160+ Context("with sentinel", func() {
161+ var ms *minisentinel.Sentinel
162+
163+ BeforeEach(func() {
164+ ms = minisentinel.NewSentinel(mr)
165+ Expect(ms.Start()).To(Succeed())
166+ })
167+
168+ AfterEach(func() {
169+ ms.Close()
170+ })
171+
172+ tests.RunSessionStoreTests(
173+ func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
174+ // Set the sentinel connection URL
175+ sentinelAddr := "redis://" + ms.Addr()
176+ opts.Type = options.RedisSessionStoreType
177+ opts.Redis.SentinelConnectionURLs = []string{sentinelAddr}
178+ opts.Redis.UseSentinel = true
179+ opts.Redis.SentinelMasterName = ms.MasterInfo().Name
180+ opts.Redis.Password = redisPassword
181+
182+ // Capture the session store so that we can close the client
183+ var err error
184+ ss, err = NewRedisSessionStore(opts, cookieOpts)
185+ return ss, err
186+ },
187+ func(d time.Duration) error {
188+ mr.FastForward(d)
189+ return nil
190+ },
191+ )
192+ })
193+
194+ Context("with cluster", func() {
195+ tests.RunSessionStoreTests(
196+ func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) {
197+ clusterAddr := "redis://" + mr.Addr()
198+ opts.Type = options.RedisSessionStoreType
199+ opts.Redis.ClusterConnectionURLs = []string{clusterAddr}
200+ opts.Redis.UseCluster = true
201+ opts.Redis.Password = redisPassword
202+
203+ // Capture the session store so that we can close the client
204+ var err error
205+ ss, err = NewRedisSessionStore(opts, cookieOpts)
206+ return ss, err
207+ },
208+ func(d time.Duration) error {
209+ mr.FastForward(d)
210+ return nil
211+ },
212+ )
213+ })
214+ })
130215})