Move Cipher intialisation to session store initialisation

This commit is contained in:
Joel Speed 2020-05-25 13:36:44 +01:00
parent d9af3ffc5e
commit c8dbf1cf60
No known key found for this signature in database
GPG Key ID: 6E80578D6751DEFB
7 changed files with 32 additions and 36 deletions

View File

@ -1,12 +1,9 @@
package options package options
import "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
// SessionOptions contains configuration options for the SessionStore providers. // SessionOptions contains configuration options for the SessionStore providers.
type SessionOptions struct { type SessionOptions struct {
Type string `flag:"session-store-type" cfg:"session_store_type"` Type string `flag:"session-store-type" cfg:"session_store_type"`
Cipher encryption.Cipher `cfg:",internal"` Redis RedisStoreOptions `cfg:",squash"`
Redis RedisStoreOptions `cfg:",squash"`
} }
// CookieSessionStoreType is used to indicate the CookieSessionStore should be // CookieSessionStoreType is used to indicate the CookieSessionStore should be

View File

@ -126,9 +126,9 @@ func (s *SessionStore) makeCookie(req *http.Request, name string, value string,
// NewCookieSessionStore initialises a new instance of the SessionStore from // NewCookieSessionStore initialises a new instance of the SessionStore from
// the configuration given // the configuration given
func NewCookieSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { func NewCookieSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions, cipher encryption.Cipher) (sessions.SessionStore, error) {
return &SessionStore{ return &SessionStore{
CookieCipher: opts.Cipher, CookieCipher: cipher,
CookieOptions: cookieOpts, CookieOptions: cookieOpts,
}, nil }, nil
} }

View File

@ -39,7 +39,7 @@ type SessionStore struct {
// NewRedisSessionStore initialises a new instance of the SessionStore from // NewRedisSessionStore initialises a new instance of the SessionStore from
// the configuration given // the configuration given
func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions, cipher encryption.Cipher) (sessions.SessionStore, error) {
client, err := newRedisCmdable(opts.Redis) client, err := newRedisCmdable(opts.Redis)
if err != nil { if err != nil {
return nil, fmt.Errorf("error constructing redis client: %v", err) return nil, fmt.Errorf("error constructing redis client: %v", err)
@ -47,7 +47,7 @@ func NewRedisSessionStore(opts *options.SessionOptions, cookieOpts *options.Cook
rs := &SessionStore{ rs := &SessionStore{
Client: client, Client: client,
CookieCipher: opts.Cipher, CookieCipher: cipher,
CookieOptions: cookieOpts, CookieOptions: cookieOpts,
} }
return rs, nil return rs, nil

View File

@ -1,6 +1,7 @@
package redis package redis
import ( import (
"crypto/rand"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"net/url" "net/url"
@ -10,11 +11,19 @@ import (
"github.com/alicebob/miniredis/v2" "github.com/alicebob/miniredis/v2"
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
"github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestRedisStore(t *testing.T) { func TestRedisStore(t *testing.T) {
secret := make([]byte, 32)
_, err := rand.Read(secret)
assert.NoError(t, err)
cipher, err := encryption.NewBase64Cipher(encryption.NewCFBCipher, encryption.SecretBytes(string(secret)))
assert.NoError(t, err)
t.Run("save session on redis standalone", func(t *testing.T) { t.Run("save session on redis standalone", func(t *testing.T) {
redisServer, err := miniredis.Run() redisServer, err := miniredis.Run()
require.NoError(t, err) require.NoError(t, err)
@ -25,7 +34,7 @@ func TestRedisStore(t *testing.T) {
Host: redisServer.Addr(), Host: redisServer.Addr(),
} }
opts.Session.Redis.ConnectionURL = redisURL.String() opts.Session.Redis.ConnectionURL = redisURL.String()
redisStore, err := NewRedisSessionStore(&opts.Session, &opts.Cookie) redisStore, err := NewRedisSessionStore(&opts.Session, &opts.Cookie, cipher)
require.NoError(t, err) require.NoError(t, err)
err = redisStore.Save( err = redisStore.Save(
httptest.NewRecorder(), httptest.NewRecorder(),
@ -49,7 +58,7 @@ func TestRedisStore(t *testing.T) {
opts.Session.Redis.SentinelConnectionURLs = []string{sentinelURL.String()} opts.Session.Redis.SentinelConnectionURLs = []string{sentinelURL.String()}
opts.Session.Redis.UseSentinel = true opts.Session.Redis.UseSentinel = true
opts.Session.Redis.SentinelMasterName = sentinel.MasterInfo().Name opts.Session.Redis.SentinelMasterName = sentinel.MasterInfo().Name
redisStore, err := NewRedisSessionStore(&opts.Session, &opts.Cookie) redisStore, err := NewRedisSessionStore(&opts.Session, &opts.Cookie, cipher)
require.NoError(t, err) require.NoError(t, err)
err = redisStore.Save( err = redisStore.Save(
httptest.NewRecorder(), httptest.NewRecorder(),

View File

@ -5,17 +5,22 @@ import (
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options" "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions" "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
"github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
"github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/cookie" "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/cookie"
"github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/redis" "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/redis"
) )
// NewSessionStore creates a SessionStore from the provided configuration // NewSessionStore creates a SessionStore from the provided configuration
func NewSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { func NewSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) {
cipher, err := encryption.NewBase64Cipher(encryption.NewCFBCipher, encryption.SecretBytes(cookieOpts.Secret))
if err != nil {
return nil, fmt.Errorf("error initialising cipher: %v", err)
}
switch opts.Type { switch opts.Type {
case options.CookieSessionStoreType: case options.CookieSessionStoreType:
return cookie.NewCookieSessionStore(opts, cookieOpts) return cookie.NewCookieSessionStore(opts, cookieOpts, cipher)
case options.RedisSessionStoreType: case options.RedisSessionStoreType:
return redis.NewRedisSessionStore(opts, cookieOpts) return redis.NewRedisSessionStore(opts, cookieOpts, cipher)
default: default:
return nil, fmt.Errorf("unknown session store type '%s'", opts.Type) return nil, fmt.Errorf("unknown session store type '%s'", opts.Type)
} }

View File

@ -353,24 +353,11 @@ var _ = Describe("NewSessionStore", func() {
SameSite: "strict", SameSite: "strict",
} }
var err error // A secret is required but not defaulted
ss, err = sessions.NewSessionStore(opts, cookieOpts)
Expect(err).ToNot(HaveOccurred())
})
SessionStoreInterfaceTests(persistent)
})
Context("with a cipher", func() {
BeforeEach(func() {
secret := make([]byte, 32) secret := make([]byte, 32)
_, err := rand.Read(secret) _, err := rand.Read(secret)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
cookieOpts.Secret = base64.URLEncoding.EncodeToString(secret) cookieOpts.Secret = base64.URLEncoding.EncodeToString(secret)
cipher, err := encryption.NewBase64Cipher(encryption.NewCFBCipher, encryption.SecretBytes(cookieOpts.Secret))
Expect(err).ToNot(HaveOccurred())
Expect(cipher).ToNot(BeNil())
opts.Cipher = cipher
ss, err = sessions.NewSessionStore(opts, cookieOpts) ss, err = sessions.NewSessionStore(opts, cookieOpts)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -384,9 +371,16 @@ var _ = Describe("NewSessionStore", func() {
ss = nil ss = nil
opts = &options.SessionOptions{} opts = &options.SessionOptions{}
// A secret is required to create a Cipher, validation ensures it is the correct
// length before a session store is initialised.
secret := make([]byte, 32)
_, err := rand.Read(secret)
Expect(err).ToNot(HaveOccurred())
// Set default options in CookieOptions // Set default options in CookieOptions
cookieOpts = &options.CookieOptions{ cookieOpts = &options.CookieOptions{
Name: "_oauth2_proxy", Name: "_oauth2_proxy",
Secret: base64.URLEncoding.EncodeToString(secret),
Path: "/", Path: "/",
Expire: time.Duration(168) * time.Hour, Expire: time.Duration(168) * time.Hour,
Refresh: time.Duration(1) * time.Hour, Refresh: time.Duration(1) * time.Hour,

View File

@ -37,8 +37,6 @@ func Validate(o *options.Options) error {
} }
msgs := make([]string, 0) msgs := make([]string, 0)
var cipher encryption.Cipher
if o.Cookie.Secret == "" { if o.Cookie.Secret == "" {
msgs = append(msgs, "missing setting: cookie-secret") msgs = append(msgs, "missing setting: cookie-secret")
} else { } else {
@ -60,12 +58,6 @@ func Validate(o *options.Options) error {
msgs = append(msgs, msgs = append(msgs,
fmt.Sprintf("Cookie secret must be 16, 24, or 32 bytes to create an AES cipher. Got %d bytes.%s", fmt.Sprintf("Cookie secret must be 16, 24, or 32 bytes to create an AES cipher. Got %d bytes.%s",
len(encryption.SecretBytes(o.Cookie.Secret)), suffix)) len(encryption.SecretBytes(o.Cookie.Secret)), suffix))
} else {
var err error
cipher, err = encryption.NewBase64Cipher(encryption.NewCFBCipher, encryption.SecretBytes(o.Cookie.Secret))
if err != nil {
msgs = append(msgs, fmt.Sprintf("cookie-secret error: %v", err))
}
} }
} }
@ -218,7 +210,6 @@ func Validate(o *options.Options) error {
} }
msgs = parseProviderInfo(o, msgs) msgs = parseProviderInfo(o, msgs)
o.Session.Cipher = cipher
sessionStore, err := sessions.NewSessionStore(&o.Session, &o.Cookie) sessionStore, err := sessions.NewSessionStore(&o.Session, &o.Cookie)
if err != nil { if err != nil {
msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err)) msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err))