Initialise SessionStore in Options

This commit is contained in:
Joel Speed 2019-05-07 14:27:09 +01:00
parent 17e97ab884
commit fbee5eae16
No known key found for this signature in database
GPG Key ID: 6E80578D6751DEFB
6 changed files with 48 additions and 11 deletions

View File

@ -16,7 +16,7 @@ import (
"github.com/mbland/hmacauth" "github.com/mbland/hmacauth"
"github.com/pusher/oauth2_proxy/cookie" "github.com/pusher/oauth2_proxy/cookie"
"github.com/pusher/oauth2_proxy/logger" "github.com/pusher/oauth2_proxy/logger"
"github.com/pusher/oauth2_proxy/pkg/apis/sessions" sessionsapi "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
"github.com/pusher/oauth2_proxy/providers" "github.com/pusher/oauth2_proxy/providers"
"github.com/yhat/wsutil" "github.com/yhat/wsutil"
) )
@ -75,6 +75,7 @@ type OAuthProxy struct {
redirectURL *url.URL // the url to receive requests at redirectURL *url.URL // the url to receive requests at
whitelistDomains []string whitelistDomains []string
provider providers.Provider provider providers.Provider
sessionStore sessionsapi.SessionStore
ProxyPrefix string ProxyPrefix string
SignInMessage string SignInMessage string
HtpasswdFile *HtpasswdFile HtpasswdFile *HtpasswdFile
@ -249,6 +250,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
ProxyPrefix: opts.ProxyPrefix, ProxyPrefix: opts.ProxyPrefix,
provider: opts.provider, provider: opts.provider,
sessionStore: opts.sessionStore,
serveMux: serveMux, serveMux: serveMux,
redirectURL: redirectURL, redirectURL: redirectURL,
whitelistDomains: opts.WhitelistDomains, whitelistDomains: opts.WhitelistDomains,
@ -293,7 +295,7 @@ func (p *OAuthProxy) displayCustomLoginForm() bool {
return p.HtpasswdFile != nil && p.DisplayHtpasswdForm return p.HtpasswdFile != nil && p.DisplayHtpasswdForm
} }
func (p *OAuthProxy) redeemCode(host, code string) (s *sessions.SessionState, err error) { func (p *OAuthProxy) redeemCode(host, code string) (s *sessionsapi.SessionState, err error) {
if code == "" { if code == "" {
return nil, errors.New("missing code") return nil, errors.New("missing code")
} }
@ -485,7 +487,7 @@ func (p *OAuthProxy) SetSessionCookie(rw http.ResponseWriter, req *http.Request,
} }
// LoadCookiedSession reads the user's authentication details from the request // LoadCookiedSession reads the user's authentication details from the request
func (p *OAuthProxy) LoadCookiedSession(req *http.Request) (*sessions.SessionState, time.Duration, error) { func (p *OAuthProxy) LoadCookiedSession(req *http.Request) (*sessionsapi.SessionState, time.Duration, error) {
var age time.Duration var age time.Duration
c, err := loadCookie(req, p.CookieName) c, err := loadCookie(req, p.CookieName)
if err != nil { if err != nil {
@ -507,7 +509,7 @@ func (p *OAuthProxy) LoadCookiedSession(req *http.Request) (*sessions.SessionSta
} }
// SaveSession creates a new session cookie value and sets this on the response // SaveSession creates a new session cookie value and sets this on the response
func (p *OAuthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *sessions.SessionState) error { func (p *OAuthProxy) SaveSession(rw http.ResponseWriter, req *http.Request, s *sessionsapi.SessionState) error {
value, err := p.provider.CookieForSession(s, p.CookieCipher) value, err := p.provider.CookieForSession(s, p.CookieCipher)
if err != nil { if err != nil {
return err return err
@ -694,7 +696,7 @@ func (p *OAuthProxy) SignIn(rw http.ResponseWriter, req *http.Request) {
user, ok := p.ManualSignIn(rw, req) user, ok := p.ManualSignIn(rw, req)
if ok { if ok {
session := &sessions.SessionState{User: user} session := &sessionsapi.SessionState{User: user}
p.SaveSession(rw, req, session) p.SaveSession(rw, req, session)
http.Redirect(rw, req, redirect, 302) http.Redirect(rw, req, redirect, 302)
} else { } else {
@ -945,7 +947,7 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int
// CheckBasicAuth checks the requests Authorization header for basic auth // CheckBasicAuth checks the requests Authorization header for basic auth
// credentials and authenticates these against the proxies HtpasswdFile // credentials and authenticates these against the proxies HtpasswdFile
func (p *OAuthProxy) CheckBasicAuth(req *http.Request) (*sessions.SessionState, error) { func (p *OAuthProxy) CheckBasicAuth(req *http.Request) (*sessionsapi.SessionState, error) {
if p.HtpasswdFile == nil { if p.HtpasswdFile == nil {
return nil, nil return nil, nil
} }
@ -967,7 +969,7 @@ func (p *OAuthProxy) CheckBasicAuth(req *http.Request) (*sessions.SessionState,
} }
if p.HtpasswdFile.Validate(pair[0], pair[1]) { if p.HtpasswdFile.Validate(pair[0], pair[1]) {
logger.PrintAuthf(pair[0], req, logger.AuthSuccess, "Authenticated via basic auth and HTpasswd File") logger.PrintAuthf(pair[0], req, logger.AuthSuccess, "Authenticated via basic auth and HTpasswd File")
return &sessions.SessionState{User: pair[0]}, nil return &sessionsapi.SessionState{User: pair[0]}, nil
} }
logger.PrintAuthf(pair[0], req, logger.AuthFailure, "Invalid authentication via basic auth: not in Htpasswd File") logger.PrintAuthf(pair[0], req, logger.AuthFailure, "Invalid authentication via basic auth: not in Htpasswd File")
return nil, nil return nil, nil

View File

@ -19,6 +19,8 @@ import (
"github.com/mbland/hmacauth" "github.com/mbland/hmacauth"
"github.com/pusher/oauth2_proxy/logger" "github.com/pusher/oauth2_proxy/logger"
"github.com/pusher/oauth2_proxy/pkg/apis/options" "github.com/pusher/oauth2_proxy/pkg/apis/options"
sessionsapi "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
"github.com/pusher/oauth2_proxy/pkg/sessions"
"github.com/pusher/oauth2_proxy/providers" "github.com/pusher/oauth2_proxy/providers"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
) )
@ -111,6 +113,7 @@ type Options struct {
proxyURLs []*url.URL proxyURLs []*url.URL
CompiledRegex []*regexp.Regexp CompiledRegex []*regexp.Regexp
provider providers.Provider provider providers.Provider
sessionStore sessionsapi.SessionStore
signatureData *SignatureData signatureData *SignatureData
oidcVerifier *oidc.IDTokenVerifier oidcVerifier *oidc.IDTokenVerifier
} }
@ -136,6 +139,9 @@ func NewOptions() *Options {
CookieExpire: time.Duration(168) * time.Hour, CookieExpire: time.Duration(168) * time.Hour,
CookieRefresh: time.Duration(0), CookieRefresh: time.Duration(0),
}, },
SessionOptions: options.SessionOptions{
Type: "cookie",
},
SetXAuthRequest: false, SetXAuthRequest: false,
SkipAuthPreflight: false, SkipAuthPreflight: false,
PassBasicAuth: true, PassBasicAuth: true,
@ -283,9 +289,19 @@ func (o *Options) Validate() error {
"pass_access_token == true or "+ "pass_access_token == true or "+
"cookie_refresh != 0, but is %d bytes.%s", "cookie_refresh != 0, but is %d bytes.%s",
len(secretBytes(o.CookieSecret)), suffix)) len(secretBytes(o.CookieSecret)), suffix))
} else {
// Enable encryption in the session store
o.EnableCipher = true
} }
} }
sessionStore, err := sessions.NewSessionStore(&o.SessionOptions, &o.CookieOptions)
if err != nil {
msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err))
} else {
o.sessionStore = sessionStore
}
if o.CookieRefresh >= o.CookieExpire { if o.CookieRefresh >= o.CookieExpire {
msgs = append(msgs, fmt.Sprintf( msgs = append(msgs, fmt.Sprintf(
"cookie_refresh (%s) must be less than "+ "cookie_refresh (%s) must be less than "+

View File

@ -2,7 +2,8 @@ package options
// 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" env:"OAUTH2_PROXY_SESSION_STORE_TYPE"` Type string `flag:"session-store-type" cfg:"session_store_type" env:"OAUTH2_PROXY_SESSION_STORE_TYPE"`
EnableCipher bool // Allow the user to choose encryption or not
CookieStoreOptions CookieStoreOptions
} }
@ -11,4 +12,6 @@ type SessionOptions struct {
var CookieSessionStoreType = "cookie" var CookieSessionStoreType = "cookie"
// CookieStoreOptions contains configuration options for the CookieSessionStore. // CookieStoreOptions contains configuration options for the CookieSessionStore.
type CookieStoreOptions struct{} type CookieStoreOptions struct {
EnableCipher bool // Allow the user to choose encryption or not
}

View File

@ -126,7 +126,7 @@ func (s *SessionStore) makeCookie(req *http.Request, name string, value string,
// the configuration given // the configuration given
func NewCookieSessionStore(opts options.CookieStoreOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { func NewCookieSessionStore(opts options.CookieStoreOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) {
var cipher *cookie.Cipher var cipher *cookie.Cipher
if len(cookieOpts.CookieSecret) > 0 { if opts.EnableCipher {
var err error var err error
cipher, err = cookie.NewCipher(utils.SecretBytes(cookieOpts.CookieSecret)) cipher, err = cookie.NewCipher(utils.SecretBytes(cookieOpts.CookieSecret))
if err != nil { if err != nil {

View File

@ -12,6 +12,8 @@ import (
func NewSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) { func NewSessionStore(opts *options.SessionOptions, cookieOpts *options.CookieOptions) (sessions.SessionStore, error) {
switch opts.Type { switch opts.Type {
case options.CookieSessionStoreType: case options.CookieSessionStoreType:
// Ensure EnableCipher is propogated from the parent option
opts.CookieStoreOptions.EnableCipher = opts.EnableCipher
return cookie.NewCookieSessionStore(opts.CookieStoreOptions, cookieOpts) return cookie.NewCookieSessionStore(opts.CookieStoreOptions, cookieOpts)
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

@ -181,12 +181,13 @@ var _ = Describe("NewSessionStore", func() {
SessionStoreInterfaceTests() SessionStoreInterfaceTests()
}) })
Context("with a cookie-secret set", func() { Context("with encryption enabled", func() {
BeforeEach(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.CookieSecret = base64.URLEncoding.EncodeToString(secret) cookieOpts.CookieSecret = base64.URLEncoding.EncodeToString(secret)
opts.EnableCipher = true
ss, err = sessions.NewSessionStore(opts, cookieOpts) ss, err = sessions.NewSessionStore(opts, cookieOpts)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -194,6 +195,19 @@ var _ = Describe("NewSessionStore", func() {
SessionStoreInterfaceTests() SessionStoreInterfaceTests()
}) })
Context("with encryption enabled, but no secret", func() {
BeforeEach(func() {
opts.EnableCipher = true
})
It("returns an error", func() {
ss, err := sessions.NewSessionStore(opts, cookieOpts)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("unable to create cipher: crypto/aes: invalid key size 0"))
Expect(ss).To(BeNil())
})
})
} }
BeforeEach(func() { BeforeEach(func() {