git.iko.soy/typeable/oauth2-proxy
on master help sign in
Add Redis sentinel compatibility
518c1d3Joel Speed
main.go+5−1
@@ -24,6 +24,7 @@ func main() {
24 upstreams := StringArray{}
24 upstreams := StringArray{}
25 skipAuthRegex := StringArray{}
25 skipAuthRegex := StringArray{}
26 googleGroups := StringArray{}
26 googleGroups := StringArray{}
27+ redisSentinelConnectionURLs := StringArray{}
27
28
28 config := flagSet.String("config", "", "path to config file")
29 config := flagSet.String("config", "", "path to config file")
29 showVersion := flagSet.Bool("version", false, "print version string")
30 showVersion := flagSet.Bool("version", false, "print version string")
@@ -76,7 +77,10 @@ func main() {
76 flagSet.Bool("cookie-httponly", true, "set HttpOnly cookie flag")
77 flagSet.Bool("cookie-httponly", true, "set HttpOnly cookie flag")
77
78
78 flagSet.String("session-store-type", "cookie", "the session storage provider to use")
79 flagSet.String("session-store-type", "cookie", "the session storage provider to use")
79− flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage type (eg: redis://HOST[:PORT])")
80+ flagSet.String("redis-connection-url", "", "URL of redis server for redis session storage (eg: redis://HOST[:PORT])")
81+ flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-conneciton-urls to use this feature")
82+ flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjuction with --redis-use-sentinel")
83+ flagSet.Var(&redisSentinelConnectionURLs, "redis-sentinel-connection-urls", "List of Redis sentinel conneciton URLs (eg redis://HOST[:PORT]). Used in conjuction with --redis-use-sentinel")
80
84
81 flagSet.String("logging-filename", "", "File to log requests to, empty for stdout")
85 flagSet.String("logging-filename", "", "File to log requests to, empty for stdout")
82 flagSet.Int("logging-max-size", 100, "Maximum size in megabytes of the log file before rotation")
86 flagSet.Int("logging-max-size", 100, "Maximum size in megabytes of the log file before rotation")
pkg/apis/options/sessions.go+4−1
@@ -25,5 +25,8 @@ var RedisSessionStoreType = "redis"
25
25
26// RedisStoreOptions contains configuration options for the RedisSessionStore.
26// RedisStoreOptions contains configuration options for the RedisSessionStore.
27type RedisStoreOptions struct {
27type RedisStoreOptions struct {
28− RedisConnectionURL string `flag:"redis-connection-url" cfg:"redis_connection_url" env:"OAUTH2_PROXY_REDIS_CONNECTION_URL"`
28+ RedisConnectionURL string `flag:"redis-connection-url" cfg:"redis_connection_url" env:"OAUTH2_PROXY_REDIS_CONNECTION_URL"`
29+ UseSentinel bool `flag:"redis-use-sentinel" cfg:"redis_use_sentinel" env:"OAUTH2_PROXY_REDIS_USE_SENTINEL"`
30+ SentinelMasterName string `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name" env:"OAUTH2_PROXY_REDIS_SENTINEL_MASTER_NAME"`
31+ SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls" env:"OAUTH2_PROXY_REDIS_SENTINEL_CONNECTION_URLS"`
29}
32}
pkg/sessions/redis/redis_store.go+20−4
@@ -36,13 +36,11 @@ type SessionStore struct {
36// NewRedisSessionStore initialises a new instance of the SessionStore from
36// NewRedisSessionStore initialises a new instance of the SessionStore from
37// the configuration given
37// the configuration given
38func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) {
38func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) {
39− opt, err := redis.ParseURL(opts.RedisStoreOptions.RedisConnectionURL)
39+ client, err := newRedisClient(opts.RedisStoreOptions)
40 if err != nil {
40 if err != nil {
41− return nil, fmt.Errorf("unable to parse redis url: %s", err)
41+ return nil, fmt.Errorf("error constructing redis client: %v", err)
42 }
42 }
43
43
44− client := redis.NewClient(opt)
45−
46 rs := &SessionStore{
44 rs := &SessionStore{
47 Client: client,
45 Client: client,
48 CookieCipher: opts.Cipher,
46 CookieCipher: opts.Cipher,
@@ -52,6 +50,24 @@ func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.Cook
52
50
53}
51}
54
52
53+func newRedisClient(opts options.RedisStoreOptions) (*redis.Client, error) {
54+ if opts.UseSentinel {
55+ client := redis.NewFailoverClient(&redis.FailoverOptions{
56+ MasterName: opts.SentinelMasterName,
57+ SentinelAddrs: opts.SentinelConnectionURLs,
58+ })
59+ return client, nil
60+ }
61+
62+ opt, err := redis.ParseURL(opts.RedisConnectionURL)
63+ if err != nil {
64+ return nil, fmt.Errorf("unable to parse redis url: %s", err)
65+ }
66+
67+ client := redis.NewClient(opt)
68+ return client, nil
69+}
70+
55// Save takes a sessions.SessionState and stores the information from it
71// Save takes a sessions.SessionState and stores the information from it
56// to redies, and adds a new ticket cookie on the HTTP response writer
72// to redies, and adds a new ticket cookie on the HTTP response writer
57func (store *SessionStore) Save(rw http.ResponseWriter, req *http.Request, s *sessions.SessionState) error {
73func (store *SessionStore) Save(rw http.ResponseWriter, req *http.Request, s *sessions.SessionState) error {