git.iko.soy/typeable/oauth2-proxy
on master help sign in
Move Options and Validation to package
commit44b27e02081bd1f2016d97854fcad678aec3a9af authorJoel Speed <joel.speed@hotmail.co.uk> dateMon 13 Apr 2020, 13:50 (7 years ago) parentde0c92a
10 files changed+417−379
http.go+3−2 http_test.go+5−4 main.go+3−2 oauthproxy.go+19−17 oauthproxy_test.go+55−53 realclientip.go → pkg/apis/logging/realclientip.go+7−13 realclientip_test.go → pkg/apis/logging/realclientip_test.go+5−5 pkg/apis/options/options.go+210 options.go → pkg/validation/options.go+47−217 options_test.go → pkg/validation/options_test.go+63−66
http.go+3−2
@@ -9,13 +9,14 @@ import (
99 "strings"
1010 "time"
1111
12+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
1213 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
1314)
1415
1516// Server represents an HTTP server
1617type Server struct {
1718 Handler http.Handler
18− Opts *Options
19+ Opts *options.Options
1920 stop chan struct{} // channel for waiting shutdown
2021}
2122
@@ -167,7 +168,7 @@ func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
167168 return tc, nil
168169}
169170
170−func redirectToHTTPS(opts *Options, h http.Handler) http.Handler {
171+func redirectToHTTPS(opts *options.Options, h http.Handler) http.Handler {
171172 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
172173 proto := r.Header.Get("X-Forwarded-Proto")
173174 if opts.ForceHTTPS && (r.TLS == nil || (proto != "" && strings.ToLower(proto) != "https")) {
http_test.go+5−4
@@ -7,6 +7,7 @@ import (
77 "testing"
88 "time"
99
10+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
1011 "github.com/stretchr/testify/assert"
1112)
1213
@@ -110,7 +111,7 @@ func TestGCPHealthcheckNotIngressPut(t *testing.T) {
110111}
111112
112113func TestRedirectToHTTPSTrue(t *testing.T) {
113− opts := NewOptions()
114+ opts := options.NewOptions()
114115 opts.ForceHTTPS = true
115116 handler := func(w http.ResponseWriter, req *http.Request) {
116117 w.Write([]byte("test"))
@@ -125,7 +126,7 @@ func TestRedirectToHTTPSTrue(t *testing.T) {
125126}
126127
127128func TestRedirectToHTTPSFalse(t *testing.T) {
128− opts := NewOptions()
129+ opts := options.NewOptions()
129130 handler := func(w http.ResponseWriter, req *http.Request) {
130131 w.Write([]byte("test"))
131132 }
@@ -139,7 +140,7 @@ func TestRedirectToHTTPSFalse(t *testing.T) {
139140}
140141
141142func TestRedirectNotWhenHTTPS(t *testing.T) {
142− opts := NewOptions()
143+ opts := options.NewOptions()
143144 opts.ForceHTTPS = true
144145 handler := func(w http.ResponseWriter, req *http.Request) {
145146 w.Write([]byte("test"))
@@ -160,7 +161,7 @@ func TestRedirectNotWhenHTTPS(t *testing.T) {
160161}
161162
162163func TestGracefulShutdown(t *testing.T) {
163− opts := NewOptions()
164+ opts := options.NewOptions()
164165 stop := make(chan struct{}, 1)
165166 srv := Server{Handler: http.DefaultServeMux, Opts: opts, stop: stop}
166167 var wg sync.WaitGroup
main.go+3−2
@@ -13,6 +13,7 @@ import (
1313
1414 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
1515 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
16+ "github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
1617 "github.com/spf13/pflag"
1718)
1819
@@ -148,14 +149,14 @@ func main() {
148149 return
149150 }
150151
151− opts := NewOptions()
152+ opts := options.NewOptions()
152153 err := options.Load(*config, flagSet, opts)
153154 if err != nil {
154155 logger.Printf("ERROR: Failed to load config: %v", err)
155156 os.Exit(1)
156157 }
157158
158− err = opts.Validate()
159+ err = validation.Validate(opts)
159160 if err != nil {
160161 logger.Printf("%s", err)
161162 os.Exit(1)
oauthproxy.go+19−17
@@ -19,6 +19,8 @@ import (
1919
2020 "github.com/coreos/go-oidc"
2121 "github.com/mbland/hmacauth"
22+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/logging"
23+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
2224 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
2325 "github.com/oauth2-proxy/oauth2-proxy/pkg/cookies"
2426 "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
@@ -112,7 +114,7 @@ type OAuthProxy struct {
112114 jwtBearerVerifiers []*oidc.IDTokenVerifier
113115 compiledRegex []*regexp.Regexp
114116 templates *template.Template
115− realClientIPParser realClientIPParser
117+ realClientIPParser logging.RealClientIPParser
116118 Banner string
117119 Footer string
118120}
@@ -143,7 +145,7 @@ func (u *UpstreamProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
143145
144146// NewReverseProxy creates a new reverse proxy for proxying requests to upstream
145147// servers
146−func NewReverseProxy(target *url.URL, opts *Options) (proxy *httputil.ReverseProxy) {
148+func NewReverseProxy(target *url.URL, opts *options.Options) (proxy *httputil.ReverseProxy) {
147149 proxy = httputil.NewSingleHostReverseProxy(target)
148150 proxy.FlushInterval = opts.FlushInterval
149151 if opts.SSLUpstreamInsecureSkipVerify {
@@ -181,7 +183,7 @@ func NewFileServer(path string, filesystemPath string) (proxy http.Handler) {
181183}
182184
183185// NewWebSocketOrRestReverseProxy creates a reverse proxy for REST or websocket based on url
184−func NewWebSocketOrRestReverseProxy(u *url.URL, opts *Options, auth hmacauth.HmacAuth) http.Handler {
186+func NewWebSocketOrRestReverseProxy(u *url.URL, opts *options.Options, auth hmacauth.HmacAuth) http.Handler {
185187 u.Path = ""
186188 proxy := NewReverseProxy(u, opts)
187189 if !opts.PassHostHeader {
@@ -209,14 +211,14 @@ func NewWebSocketOrRestReverseProxy(u *url.URL, opts *Options, auth hmacauth.Hma
209211}
210212
211213// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
212−func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
214+func NewOAuthProxy(opts *options.Options, validator func(string) bool) *OAuthProxy {
213215 serveMux := http.NewServeMux()
214216 var auth hmacauth.HmacAuth
215− if sigData := opts.signatureData; sigData != nil {
216− auth = hmacauth.NewHmacAuth(sigData.hash, []byte(sigData.key),
217+ if sigData := opts.GetSignatureData(); sigData != nil {
218+ auth = hmacauth.NewHmacAuth(sigData.Hash, []byte(sigData.Key),
217219 SignatureHeader, SignatureHeaders)
218220 }
219− for _, u := range opts.proxyURLs {
221+ for _, u := range opts.GetProxyURLs() {
220222 path := u.Path
221223 host := u.Host
222224 switch u.Scheme {
@@ -252,7 +254,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
252254 panic(fmt.Sprintf("unknown upstream protocol %s", u.Scheme))
253255 }
254256 }
255− for _, u := range opts.compiledRegex {
257+ for _, u := range opts.GetCompiledRegex() {
256258 logger.Printf("compiled skip-auth-regex => %q", u)
257259 }
258260
@@ -262,12 +264,12 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
262264 logger.Printf("Skipping JWT tokens from extra JWT issuer: %q", issuer)
263265 }
264266 }
265− redirectURL := opts.redirectURL
267+ redirectURL := opts.GetRedirectURL()
266268 if redirectURL.Path == "" {
267269 redirectURL.Path = fmt.Sprintf("%s/callback", opts.ProxyPrefix)
268270 }
269271
270− logger.Printf("OAuthProxy configured for %s Client ID: %s", opts.provider.Data().ProviderName, opts.ClientID)
272+ logger.Printf("OAuthProxy configured for %s Client ID: %s", opts.GetProvider().Data().ProviderName, opts.ClientID)
271273 refresh := "disabled"
272274 if opts.Cookie.Refresh != time.Duration(0) {
273275 refresh = fmt.Sprintf("after %s", opts.Cookie.Refresh)
@@ -298,18 +300,18 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy {
298300 UserInfoPath: fmt.Sprintf("%s/userinfo", opts.ProxyPrefix),
299301
300302 ProxyPrefix: opts.ProxyPrefix,
301− provider: opts.provider,
303+ provider: opts.GetProvider(),
302304 providerNameOverride: opts.ProviderName,
303− sessionStore: opts.sessionStore,
305+ sessionStore: opts.GetSessionStore(),
304306 serveMux: serveMux,
305307 redirectURL: redirectURL,
306308 whitelistDomains: opts.WhitelistDomains,
307309 skipAuthRegex: opts.SkipAuthRegex,
308310 skipAuthPreflight: opts.SkipAuthPreflight,
309311 skipJwtBearerTokens: opts.SkipJwtBearerTokens,
310− jwtBearerVerifiers: opts.jwtBearerVerifiers,
311− compiledRegex: opts.compiledRegex,
312− realClientIPParser: opts.realClientIPParser,
312+ jwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
313+ compiledRegex: opts.GetCompiledRegex(),
314+ realClientIPParser: opts.GetRealClientIPParser(),
313315 SetXAuthRequest: opts.SetXAuthRequest,
314316 PassBasicAuth: opts.PassBasicAuth,
315317 SetBasicAuth: opts.SetBasicAuth,
@@ -760,7 +762,7 @@ func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) {
760762// OAuthCallback is the OAuth2 authentication flow callback that finishes the
761763// OAuth2 authentication flow
762764func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) {
763− remoteAddr := getClientString(p.realClientIPParser, req, true)
765+ remoteAddr := logging.GetClientString(p.realClientIPParser, req, true)
764766
765767 // finish the oauth cycle
766768 err := req.ParseForm()
@@ -888,7 +890,7 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
888890 }
889891 }
890892
891− remoteAddr := getClientString(p.realClientIPParser, req, true)
893+ remoteAddr := logging.GetClientString(p.realClientIPParser, req, true)
892894 if session == nil {
893895 session, err = p.LoadCookiedSession(req)
894896 if err != nil {
oauthproxy_test.go+55−53
@@ -18,9 +18,11 @@ import (
1818
1919 "github.com/coreos/go-oidc"
2020 "github.com/mbland/hmacauth"
21+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
2122 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
2223 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
2324 "github.com/oauth2-proxy/oauth2-proxy/pkg/sessions/cookie"
25+ "github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
2426 "github.com/oauth2-proxy/oauth2-proxy/providers"
2527 "github.com/stretchr/testify/assert"
2628 "github.com/stretchr/testify/require"
@@ -71,7 +73,7 @@ func TestWebSocketProxy(t *testing.T) {
7173
7274 backendURL, _ := url.Parse(backend.URL)
7375
74− options := NewOptions()
76+ options := options.NewOptions()
7577 var auth hmacauth.HmacAuth
7678 options.PassHostHeader = true
7779 proxyHandler := NewWebSocketOrRestReverseProxy(backendURL, options, auth)
@@ -121,7 +123,7 @@ func TestNewReverseProxy(t *testing.T) {
121123 backendHost := net.JoinHostPort(backendHostname, backendPort)
122124 proxyURL, _ := url.Parse(backendURL.Scheme + "://" + backendHost + "/")
123125
124− proxyHandler := NewReverseProxy(proxyURL, &Options{FlushInterval: time.Second})
126+ proxyHandler := NewReverseProxy(proxyURL, &options.Options{FlushInterval: time.Second})
125127 setProxyUpstreamHostHeader(proxyHandler, proxyURL)
126128 frontend := httptest.NewServer(proxyHandler)
127129 defer frontend.Close()
@@ -143,7 +145,7 @@ func TestEncodedSlashes(t *testing.T) {
143145 defer backend.Close()
144146
145147 b, _ := url.Parse(backend.URL)
146− proxyHandler := NewReverseProxy(b, &Options{FlushInterval: time.Second})
148+ proxyHandler := NewReverseProxy(b, &options.Options{FlushInterval: time.Second})
147149 setProxyDirector(proxyHandler)
148150 frontend := httptest.NewServer(proxyHandler)
149151 defer frontend.Close()
@@ -161,11 +163,11 @@ func TestEncodedSlashes(t *testing.T) {
161163}
162164
163165func TestRobotsTxt(t *testing.T) {
164− opts := NewOptions()
166+ opts := options.NewOptions()
165167 opts.ClientID = "asdlkjx"
166168 opts.ClientSecret = "alkgks"
167169 opts.Cookie.Secret = "asdkugkj"
168− opts.Validate()
170+ validation.Validate(opts)
169171
170172 proxy := NewOAuthProxy(opts, func(string) bool { return true })
171173 rw := httptest.NewRecorder()
@@ -176,7 +178,7 @@ func TestRobotsTxt(t *testing.T) {
176178}
177179
178180func TestIsValidRedirect(t *testing.T) {
179− opts := NewOptions()
181+ opts := options.NewOptions()
180182 opts.ClientID = "skdlfj"
181183 opts.ClientSecret = "fgkdsgj"
182184 opts.Cookie.Secret = "ljgiogbj"
@@ -189,7 +191,7 @@ func TestIsValidRedirect(t *testing.T) {
189191 "anyport.bar:*",
190192 ".sub.anyport.bar:*",
191193 }
192− opts.Validate()
194+ validation.Validate(opts)
193195
194196 proxy := NewOAuthProxy(opts, func(string) bool { return true })
195197
@@ -451,7 +453,7 @@ func TestBasicAuthPassword(t *testing.T) {
451453 w.WriteHeader(200)
452454 w.Write([]byte(payload))
453455 }))
454− opts := NewOptions()
456+ opts := options.NewOptions()
455457 opts.Upstreams = append(opts.Upstreams, providerServer.URL)
456458 // The CookieSecret must be 32 bytes in order to create the AES
457459 // cipher.
@@ -464,12 +466,12 @@ func TestBasicAuthPassword(t *testing.T) {
464466 opts.PassUserHeaders = true
465467 opts.PreferEmailToUser = true
466468 opts.BasicAuthPassword = "This is a secure password"
467− opts.Validate()
469+ validation.Validate(opts)
468470
469471 providerURL, _ := url.Parse(providerServer.URL)
470472 const emailAddress = "john.doe@example.com"
471473
472− opts.provider = NewTestProvider(providerURL, emailAddress)
474+ opts.SetProvider(NewTestProvider(providerURL, emailAddress))
473475 proxy := NewOAuthProxy(opts, func(email string) bool {
474476 return email == emailAddress
475477 })
@@ -518,12 +520,12 @@ func TestBasicAuthPassword(t *testing.T) {
518520}
519521
520522func TestBasicAuthWithEmail(t *testing.T) {
521− opts := NewOptions()
523+ opts := options.NewOptions()
522524 opts.PassBasicAuth = true
523525 opts.PassUserHeaders = false
524526 opts.PreferEmailToUser = false
525527 opts.BasicAuthPassword = "This is a secure password"
526− opts.Validate()
528+ validation.Validate(opts)
527529
528530 const emailAddress = "john.doe@example.com"
529531 const userName = "9fcab5c9b889a557"
@@ -564,11 +566,11 @@ func TestBasicAuthWithEmail(t *testing.T) {
564566}
565567
566568func TestPassUserHeadersWithEmail(t *testing.T) {
567− opts := NewOptions()
569+ opts := options.NewOptions()
568570 opts.PassBasicAuth = false
569571 opts.PassUserHeaders = true
570572 opts.PreferEmailToUser = false
571− opts.Validate()
573+ validation.Validate(opts)
572574
573575 const emailAddress = "john.doe@example.com"
574576 const userName = "9fcab5c9b889a557"
@@ -605,7 +607,7 @@ func TestPassUserHeadersWithEmail(t *testing.T) {
605607type PassAccessTokenTest struct {
606608 providerServer *httptest.Server
607609 proxy *OAuthProxy
608− opts *Options
610+ opts *options.Options
609611}
610612
611613type PassAccessTokenTestOptions struct {
@@ -632,7 +634,7 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) *PassAccessTokenTes
632634 w.Write([]byte(payload))
633635 }))
634636
635− t.opts = NewOptions()
637+ t.opts = options.NewOptions()
636638 t.opts.Upstreams = append(t.opts.Upstreams, t.providerServer.URL)
637639 if opts.ProxyUpstream != "" {
638640 t.opts.Upstreams = append(t.opts.Upstreams, opts.ProxyUpstream)
@@ -644,12 +646,12 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) *PassAccessTokenTes
644646 t.opts.ClientSecret = "gfjgojl"
645647 t.opts.Cookie.Secure = false
646648 t.opts.PassAccessToken = opts.PassAccessToken
647− t.opts.Validate()
649+ validation.Validate(t.opts)
648650
649651 providerURL, _ := url.Parse(t.providerServer.URL)
650652 const emailAddress = "michael.bland@gsa.gov"
651653
652− t.opts.provider = NewTestProvider(providerURL, emailAddress)
654+ t.opts.SetProvider(NewTestProvider(providerURL, emailAddress))
653655 t.proxy = NewOAuthProxy(t.opts, func(email string) bool {
654656 return email == emailAddress
655657 })
@@ -779,7 +781,7 @@ func TestDoNotForwardAccessTokenUpstream(t *testing.T) {
779781}
780782
781783type SignInPageTest struct {
782− opts *Options
784+ opts *options.Options
783785 proxy *OAuthProxy
784786 signInRegexp *regexp.Regexp
785787 signInProviderRegexp *regexp.Regexp
@@ -791,12 +793,12 @@ const signInSkipProvider = `>Found<`
791793func NewSignInPageTest(skipProvider bool) *SignInPageTest {
792794 var sipTest SignInPageTest
793795
794− sipTest.opts = NewOptions()
796+ sipTest.opts = options.NewOptions()
795797 sipTest.opts.Cookie.Secret = "adklsj2"
796798 sipTest.opts.ClientID = "lkdgj"
797799 sipTest.opts.ClientSecret = "sgiufgoi"
798800 sipTest.opts.SkipProviderButton = skipProvider
799− sipTest.opts.Validate()
801+ validation.Validate(sipTest.opts)
800802
801803 sipTest.proxy = NewOAuthProxy(sipTest.opts, func(email string) bool {
802804 return true
@@ -876,7 +878,7 @@ func TestSignInPageSkipProviderDirect(t *testing.T) {
876878}
877879
878880type ProcessCookieTest struct {
879− opts *Options
881+ opts *options.Options
880882 proxy *OAuthProxy
881883 rw *httptest.ResponseRecorder
882884 req *http.Request
@@ -887,12 +889,12 @@ type ProcessCookieTestOpts struct {
887889 providerValidateCookieResponse bool
888890}
889891
890−type OptionsModifier func(*Options)
892+type OptionsModifier func(*options.Options)
891893
892894func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifier) *ProcessCookieTest {
893895 var pcTest ProcessCookieTest
894896
895− pcTest.opts = NewOptions()
897+ pcTest.opts = options.NewOptions()
896898 for _, modifier := range modifiers {
897899 modifier(pcTest.opts)
898900 }
@@ -902,7 +904,7 @@ func NewProcessCookieTest(opts ProcessCookieTestOpts, modifiers ...OptionsModifi
902904 // First, set the CookieRefresh option so proxy.AesCipher is created,
903905 // needed to encrypt the access_token.
904906 pcTest.opts.Cookie.Refresh = time.Hour
905− pcTest.opts.Validate()
907+ validation.Validate(pcTest.opts)
906908
907909 pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool {
908910 return pcTest.validateUser
@@ -971,7 +973,7 @@ func TestProcessCookieNoCookieError(t *testing.T) {
971973}
972974
973975func TestProcessCookieRefreshNotSet(t *testing.T) {
974− pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) {
976+ pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
975977 opts.Cookie.Expire = time.Duration(23) * time.Hour
976978 })
977979 reference := time.Now().Add(time.Duration(-2) * time.Hour)
@@ -988,7 +990,7 @@ func TestProcessCookieRefreshNotSet(t *testing.T) {
988990}
989991
990992func TestProcessCookieFailIfCookieExpired(t *testing.T) {
991− pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) {
993+ pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
992994 opts.Cookie.Expire = time.Duration(24) * time.Hour
993995 })
994996 reference := time.Now().Add(time.Duration(25) * time.Hour * -1)
@@ -1003,7 +1005,7 @@ func TestProcessCookieFailIfCookieExpired(t *testing.T) {
10031005}
10041006
10051007func TestProcessCookieFailIfRefreshSetAndCookieExpired(t *testing.T) {
1006− pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *Options) {
1008+ pcTest := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
10071009 opts.Cookie.Expire = time.Duration(24) * time.Hour
10081010 })
10091011 reference := time.Now().Add(time.Duration(25) * time.Hour * -1)
@@ -1073,7 +1075,7 @@ func TestAuthOnlyEndpointUnauthorizedOnNoCookieSetError(t *testing.T) {
10731075}
10741076
10751077func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) {
1076− test := NewAuthOnlyEndpointTest(func(opts *Options) {
1078+ test := NewAuthOnlyEndpointTest(func(opts *options.Options) {
10771079 opts.Cookie.Expire = time.Duration(24) * time.Hour
10781080 })
10791081 reference := time.Now().Add(time.Duration(25) * time.Hour * -1)
@@ -1103,9 +1105,9 @@ func TestAuthOnlyEndpointUnauthorizedOnEmailValidationFailure(t *testing.T) {
11031105func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
11041106 var pcTest ProcessCookieTest
11051107
1106− pcTest.opts = NewOptions()
1108+ pcTest.opts = options.NewOptions()
11071109 pcTest.opts.SetXAuthRequest = true
1108− pcTest.opts.Validate()
1110+ validation.Validate(pcTest.opts)
11091111
11101112 pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool {
11111113 return pcTest.validateUser
@@ -1133,10 +1135,10 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
11331135func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
11341136 var pcTest ProcessCookieTest
11351137
1136− pcTest.opts = NewOptions()
1138+ pcTest.opts = options.NewOptions()
11371139 pcTest.opts.SetXAuthRequest = true
11381140 pcTest.opts.SetBasicAuth = true
1139− pcTest.opts.Validate()
1141+ validation.Validate(pcTest.opts)
11401142
11411143 pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool {
11421144 return pcTest.validateUser
@@ -1166,10 +1168,10 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
11661168func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
11671169 var pcTest ProcessCookieTest
11681170
1169− pcTest.opts = NewOptions()
1171+ pcTest.opts = options.NewOptions()
11701172 pcTest.opts.SetXAuthRequest = true
11711173 pcTest.opts.SetBasicAuth = false
1172− pcTest.opts.Validate()
1174+ validation.Validate(pcTest.opts)
11731175
11741176 pcTest.proxy = NewOAuthProxy(pcTest.opts, func(email string) bool {
11751177 return pcTest.validateUser
@@ -1202,16 +1204,16 @@ func TestAuthSkippedForPreflightRequests(t *testing.T) {
12021204 }))
12031205 defer upstream.Close()
12041206
1205− opts := NewOptions()
1207+ opts := options.NewOptions()
12061208 opts.Upstreams = append(opts.Upstreams, upstream.URL)
12071209 opts.ClientID = "aljsal"
12081210 opts.ClientSecret = "jglkfsdgj"
12091211 opts.Cookie.Secret = "dkfjgdls"
12101212 opts.SkipAuthPreflight = true
1211− opts.Validate()
1213+ validation.Validate(opts)
12121214
12131215 upstreamURL, _ := url.Parse(upstream.URL)
1214− opts.provider = NewTestProvider(upstreamURL, "")
1216+ opts.SetProvider(NewTestProvider(upstreamURL, ""))
12151217
12161218 proxy := NewOAuthProxy(opts, func(string) bool { return false })
12171219 rw := httptest.NewRecorder()
@@ -1242,7 +1244,7 @@ func (v *SignatureAuthenticator) Authenticate(w http.ResponseWriter, r *http.Req
12421244}
12431245
12441246type SignatureTest struct {
1245− opts *Options
1247+ opts *options.Options
12461248 upstream *httptest.Server
12471249 upstreamHost string
12481250 provider *httptest.Server
@@ -1252,7 +1254,7 @@ type SignatureTest struct {
12521254}
12531255
12541256func NewSignatureTest() *SignatureTest {
1255− opts := NewOptions()
1257+ opts := options.NewOptions()
12561258 opts.Cookie.Secret = "cookie secret"
12571259 opts.ClientID = "client ID"
12581260 opts.ClientSecret = "client secret"
@@ -1269,7 +1271,7 @@ func NewSignatureTest() *SignatureTest {
12691271 }
12701272 provider := httptest.NewServer(http.HandlerFunc(providerHandler))
12711273 providerURL, _ := url.Parse(provider.URL)
1272− opts.provider = NewTestProvider(providerURL, "mbland@acm.org")
1274+ opts.SetProvider(NewTestProvider(providerURL, "mbland@acm.org"))
12731275
12741276 return &SignatureTest{
12751277 opts,
@@ -1304,7 +1306,7 @@ func (fnc *fakeNetConn) Read(p []byte) (n int, err error) {
13041306}
13051307
13061308func (st *SignatureTest) MakeRequestWithExpectedKey(method, body, key string) {
1307− err := st.opts.Validate()
1309+ err := validation.Validate(st.opts)
13081310 if err != nil {
13091311 panic(err)
13101312 }
@@ -1360,8 +1362,8 @@ func TestRequestSignaturePostRequest(t *testing.T) {
13601362}
13611363
13621364func TestGetRedirect(t *testing.T) {
1363− options := NewOptions()
1364− _ = options.Validate()
1365+ options := options.NewOptions()
1366+ _ = validation.Validate(options)
13651367 require.NotEmpty(t, options.ProxyPrefix)
13661368 proxy := NewOAuthProxy(options, func(s string) bool { return false })
13671369
@@ -1393,17 +1395,17 @@ func TestGetRedirect(t *testing.T) {
13931395}
13941396
13951397type ajaxRequestTest struct {
1396− opts *Options
1398+ opts *options.Options
13971399 proxy *OAuthProxy
13981400}
13991401
14001402func newAjaxRequestTest() *ajaxRequestTest {
14011403 test := &ajaxRequestTest{}
1402− test.opts = NewOptions()
1404+ test.opts = options.NewOptions()
14031405 test.opts.Cookie.Secret = "sdflsw"
14041406 test.opts.ClientID = "gkljfdl"
14051407 test.opts.ClientSecret = "sdflkjs"
1406− test.opts.Validate()
1408+ validation.Validate(test.opts)
14071409 test.proxy = NewOAuthProxy(test.opts, func(email string) bool {
14081410 return true
14091411 })
@@ -1457,7 +1459,7 @@ func TestAjaxForbiddendRequest(t *testing.T) {
14571459}
14581460
14591461func TestClearSplitCookie(t *testing.T) {
1460− opts := NewOptions()
1462+ opts := options.NewOptions()
14611463 opts.Cookie.Name = "oauth2"
14621464 opts.Cookie.Domains = []string{"abc"}
14631465 store, err := cookie.NewCookieSessionStore(&opts.Session, &opts.Cookie)
@@ -1486,7 +1488,7 @@ func TestClearSplitCookie(t *testing.T) {
14861488}
14871489
14881490func TestClearSingleCookie(t *testing.T) {
1489− opts := NewOptions()
1491+ opts := options.NewOptions()
14901492 opts.Cookie.Name = "oauth2"
14911493 opts.Cookie.Domains = []string{"abc"}
14921494 store, err := cookie.NewCookieSessionStore(&opts.Session, &opts.Cookie)
@@ -1542,12 +1544,12 @@ func TestGetJwtSession(t *testing.T) {
15421544 verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
15431545 &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
15441546
1545− test := NewAuthOnlyEndpointTest(func(opts *Options) {
1547+ test := NewAuthOnlyEndpointTest(func(opts *options.Options) {
15461548 opts.PassAuthorization = true
15471549 opts.SetAuthorization = true
15481550 opts.SetXAuthRequest = true
15491551 opts.SkipJwtBearerTokens = true
1550− opts.jwtBearerVerifiers = append(opts.jwtBearerVerifiers, verifier)
1552+ opts.SetJWTBearerVerifiers(append(opts.GetJWTBearerVerifiers(), verifier))
15511553 })
15521554 tp, _ := test.proxy.provider.(*TestProvider)
15531555 tp.GroupValidator = func(s string) bool {
@@ -1666,10 +1668,10 @@ func Test_noCacheHeadersDoesNotExistsInResponseHeadersFromUpstream(t *testing.T)
16661668 }))
16671669 t.Cleanup(upstream.Close)
16681670
1669− opts := NewOptions()
1671+ opts := options.NewOptions()
16701672 opts.Upstreams = []string{upstream.URL}
16711673 opts.SkipAuthRegex = []string{".*"}
1672− _ = opts.Validate()
1674+ _ = validation.Validate(opts)
16731675 proxy := NewOAuthProxy(opts, func(email string) bool {
16741676 return true
16751677 })
realclientip.go → pkg/apis/logging/realclientip.gorenamed+7−13
@@ -1,19 +1,18 @@
1−package main
1+package logging
22
33import (
44 "fmt"
55 "net"
66 "net/http"
77 "strings"
8−
9− "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
108)
119
12−type realClientIPParser interface {
10+// RealClientIPParser is an interface for a getting the client's real IP to be used for logging.
11+type RealClientIPParser interface {
1312 GetRealClientIP(http.Header) (net.IP, error)
1413}
1514
16−func getRealClientIPParser(headerKey string) (realClientIPParser, error) {
15+func GetRealClientIPParser(headerKey string) (RealClientIPParser, error) {
1716 headerKey = http.CanonicalHeaderKey(headerKey)
1817
1918 switch headerKey {
@@ -73,13 +72,11 @@ func getRemoteIP(req *http.Request) (net.IP, error) {
7372 }
7473}
7574
76−// getClientString obtains the human readable string of the remote IP and optionally the real client IP if available
77−func getClientString(p realClientIPParser, req *http.Request, full bool) (s string) {
75+// GetClientString obtains the human readable string of the remote IP and optionally the real client IP if available
76+func GetClientString(p RealClientIPParser, req *http.Request, full bool) (s string) {
7877 var realClientIPStr string
7978 if p != nil {
80− if realClientIP, err := p.GetRealClientIP(req.Header); err != nil {
81− logger.Printf("Unable to get real client IP: %v", err)
82− } else if realClientIP != nil {
79+ if realClientIP, err := p.GetRealClientIP(req.Header); err == nil && realClientIP != nil {
8380 realClientIPStr = realClientIP.String()
8481 }
8582 }
@@ -87,9 +84,6 @@ func getClientString(p realClientIPParser, req *http.Request, full bool) (s stri
8784 var remoteIPStr string
8885 if remoteIP, err := getRemoteIP(req); err == nil {
8986 remoteIPStr = remoteIP.String()
90− } else {
91− // Should not happen, if it does, likely a bug.
92− logger.Printf("Unable to get remote IP(?!?!): %v", err)
9387 }
9488
9589 if !full && realClientIPStr != "" {
realclientip_test.go → pkg/apis/logging/realclientip_test.gorenamed+5−5
@@ -1,4 +1,4 @@
1−package main
1+package logging
22
33import (
44 "net"
@@ -26,7 +26,7 @@ func TestGetRealClientIPParser(t *testing.T) {
2626 }
2727
2828 for _, test := range tests {
29− p, err := getRealClientIPParser(test.header)
29+ p, err := GetRealClientIPParser(test.header)
3030
3131 if test.errString == "" {
3232 assert.Nil(t, err)
@@ -144,7 +144,7 @@ func TestGetClientString(t *testing.T) {
144144 p := &xForwardedForClientIPParser{header: http.CanonicalHeaderKey("X-Forwarded-For")}
145145
146146 tests := []struct {
147− parser realClientIPParser
147+ parser RealClientIPParser
148148 remoteAddr string
149149 headerValue string
150150 expectedClient string
@@ -167,10 +167,10 @@ func TestGetClientString(t *testing.T) {
167167 RemoteAddr: test.remoteAddr,
168168 }
169169
170− client := getClientString(test.parser, req, false)
170+ client := GetClientString(test.parser, req, false)
171171 assert.Equal(t, test.expectedClient, client)
172172
173− clientFull := getClientString(test.parser, req, true)
173+ clientFull := GetClientString(test.parser, req, true)
174174 assert.Equal(t, test.expectedClientFull, clientFull)
175175 }
176176}
pkg/apis/options/options.gonew file+210
@@ -0,0 +1,210 @@
1+package options
2+
3+import (
4+ "crypto"
5+ "net/url"
6+ "regexp"
7+ "time"
8+
9+ oidc "github.com/coreos/go-oidc"
10+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/logging"
11+ sessionsapi "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
12+ "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
13+ "github.com/oauth2-proxy/oauth2-proxy/providers"
14+)
15+
16+// SignatureData holds hmacauth signature hash and key
17+type SignatureData struct {
18+ Hash crypto.Hash
19+ Key string
20+}
21+
22+// Options holds Configuration Options that can be set by Command Line Flag,
23+// or Config File
24+type Options struct {
25+ ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix" env:"OAUTH2_PROXY_PROXY_PREFIX"`
26+ PingPath string `flag:"ping-path" cfg:"ping_path" env:"OAUTH2_PROXY_PING_PATH"`
27+ ProxyWebSockets bool `flag:"proxy-websockets" cfg:"proxy_websockets" env:"OAUTH2_PROXY_PROXY_WEBSOCKETS"`
28+ HTTPAddress string `flag:"http-address" cfg:"http_address" env:"OAUTH2_PROXY_HTTP_ADDRESS"`
29+ HTTPSAddress string `flag:"https-address" cfg:"https_address" env:"OAUTH2_PROXY_HTTPS_ADDRESS"`
30+ ReverseProxy bool `flag:"reverse-proxy" cfg:"reverse_proxy" env:"OAUTH2_PROXY_REVERSE_PROXY"`
31+ RealClientIPHeader string `flag:"real-client-ip-header" cfg:"real_client_ip_header" env:"OAUTH2_PROXY_REAL_CLIENT_IP_HEADER"`
32+ ForceHTTPS bool `flag:"force-https" cfg:"force_https" env:"OAUTH2_PROXY_FORCE_HTTPS"`
33+ RawRedirectURL string `flag:"redirect-url" cfg:"redirect_url" env:"OAUTH2_PROXY_REDIRECT_URL"`
34+ ClientID string `flag:"client-id" cfg:"client_id" env:"OAUTH2_PROXY_CLIENT_ID"`
35+ ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"OAUTH2_PROXY_CLIENT_SECRET"`
36+ ClientSecretFile string `flag:"client-secret-file" cfg:"client_secret_file" env:"OAUTH2_PROXY_CLIENT_SECRET_FILE"`
37+ TLSCertFile string `flag:"tls-cert-file" cfg:"tls_cert_file" env:"OAUTH2_PROXY_TLS_CERT_FILE"`
38+ TLSKeyFile string `flag:"tls-key-file" cfg:"tls_key_file" env:"OAUTH2_PROXY_TLS_KEY_FILE"`
39+
40+ AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file" env:"OAUTH2_PROXY_AUTHENTICATED_EMAILS_FILE"`
41+ KeycloakGroup string `flag:"keycloak-group" cfg:"keycloak_group" env:"OAUTH2_PROXY_KEYCLOAK_GROUP"`
42+ AzureTenant string `flag:"azure-tenant" cfg:"azure_tenant" env:"OAUTH2_PROXY_AZURE_TENANT"`
43+ BitbucketTeam string `flag:"bitbucket-team" cfg:"bitbucket_team" env:"OAUTH2_PROXY_BITBUCKET_TEAM"`
44+ BitbucketRepository string `flag:"bitbucket-repository" cfg:"bitbucket_repository" env:"OAUTH2_PROXY_BITBUCKET_REPOSITORY"`
45+ EmailDomains []string `flag:"email-domain" cfg:"email_domains" env:"OAUTH2_PROXY_EMAIL_DOMAINS"`
46+ WhitelistDomains []string `flag:"whitelist-domain" cfg:"whitelist_domains" env:"OAUTH2_PROXY_WHITELIST_DOMAINS"`
47+ GitHubOrg string `flag:"github-org" cfg:"github_org" env:"OAUTH2_PROXY_GITHUB_ORG"`
48+ GitHubTeam string `flag:"github-team" cfg:"github_team" env:"OAUTH2_PROXY_GITHUB_TEAM"`
49+ GitHubRepo string `flag:"github-repo" cfg:"github_repo" env:"OAUTH2_PROXY_GITHUB_REPO"`
50+ GitHubToken string `flag:"github-token" cfg:"github_token" env:"OAUTH2_PROXY_GITHUB_TOKEN"`
51+ GitLabGroup string `flag:"gitlab-group" cfg:"gitlab_group" env:"OAUTH2_PROXY_GITLAB_GROUP"`
52+ GoogleGroups []string `flag:"google-group" cfg:"google_group" env:"OAUTH2_PROXY_GOOGLE_GROUPS"`
53+ GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email" env:"OAUTH2_PROXY_GOOGLE_ADMIN_EMAIL"`
54+ GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json" env:"OAUTH2_PROXY_GOOGLE_SERVICE_ACCOUNT_JSON"`
55+ HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file" env:"OAUTH2_PROXY_HTPASSWD_FILE"`
56+ DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form" env:"OAUTH2_PROXY_DISPLAY_HTPASSWD_FORM"`
57+ CustomTemplatesDir string `flag:"custom-templates-dir" cfg:"custom_templates_dir" env:"OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR"`
58+ Banner string `flag:"banner" cfg:"banner" env:"OAUTH2_PROXY_BANNER"`
59+ Footer string `flag:"footer" cfg:"footer" env:"OAUTH2_PROXY_FOOTER"`
60+
61+ Cookie CookieOptions `cfg:",squash"`
62+ Session SessionOptions `cfg:",squash"`
63+
64+ Upstreams []string `flag:"upstream" cfg:"upstreams" env:"OAUTH2_PROXY_UPSTREAMS"`
65+ SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex" env:"OAUTH2_PROXY_SKIP_AUTH_REGEX"`
66+ SkipJwtBearerTokens bool `flag:"skip-jwt-bearer-tokens" cfg:"skip_jwt_bearer_tokens" env:"OAUTH2_PROXY_SKIP_JWT_BEARER_TOKENS"`
67+ ExtraJwtIssuers []string `flag:"extra-jwt-issuers" cfg:"extra_jwt_issuers" env:"OAUTH2_PROXY_EXTRA_JWT_ISSUERS"`
68+ PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth" env:"OAUTH2_PROXY_PASS_BASIC_AUTH"`
69+ SetBasicAuth bool `flag:"set-basic-auth" cfg:"set_basic_auth" env:"OAUTH2_PROXY_SET_BASIC_AUTH"`
70+ PreferEmailToUser bool `flag:"prefer-email-to-user" cfg:"prefer_email_to_user" env:"OAUTH2_PROXY_PREFER_EMAIL_TO_USER"`
71+ BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password" env:"OAUTH2_PROXY_BASIC_AUTH_PASSWORD"`
72+ PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token" env:"OAUTH2_PROXY_PASS_ACCESS_TOKEN"`
73+ PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header" env:"OAUTH2_PROXY_PASS_HOST_HEADER"`
74+ SkipProviderButton bool `flag:"skip-provider-button" cfg:"skip_provider_button" env:"OAUTH2_PROXY_SKIP_PROVIDER_BUTTON"`
75+ PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers" env:"OAUTH2_PROXY_PASS_USER_HEADERS"`
76+ SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify" env:"OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY"`
77+ SSLUpstreamInsecureSkipVerify bool `flag:"ssl-upstream-insecure-skip-verify" cfg:"ssl_upstream_insecure_skip_verify" env:"OAUTH2_PROXY_SSL_UPSTREAM_INSECURE_SKIP_VERIFY"`
78+ SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest" env:"OAUTH2_PROXY_SET_XAUTHREQUEST"`
79+ SetAuthorization bool `flag:"set-authorization-header" cfg:"set_authorization_header" env:"OAUTH2_PROXY_SET_AUTHORIZATION_HEADER"`
80+ PassAuthorization bool `flag:"pass-authorization-header" cfg:"pass_authorization_header" env:"OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER"`
81+ SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight" env:"OAUTH2_PROXY_SKIP_AUTH_PREFLIGHT"`
82+ FlushInterval time.Duration `flag:"flush-interval" cfg:"flush_interval" env:"OAUTH2_PROXY_FLUSH_INTERVAL"`
83+
84+ // These options allow for other providers besides Google, with
85+ // potential overrides.
86+ ProviderType string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"`
87+ ProviderName string `flag:"provider-display-name" cfg:"provider_display_name" env:"OAUTH2_PROXY_PROVIDER_DISPLAY_NAME"`
88+ OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"`
89+ InsecureOIDCAllowUnverifiedEmail bool `flag:"insecure-oidc-allow-unverified-email" cfg:"insecure_oidc_allow_unverified_email" env:"OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL"`
90+ InsecureOIDCSkipIssuerVerification bool `flag:"insecure-oidc-skip-issuer-verification" cfg:"insecure_oidc_skip_issuer_verification" env:"OAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION"`
91+ SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_PROXY_SKIP_OIDC_DISCOVERY"`
92+ OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_PROXY_OIDC_JWKS_URL"`
93+ LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"`
94+ RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"`
95+ ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"`
96+ ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"`
97+ ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"`
98+ Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"`
99+ Prompt string `flag:"prompt" cfg:"prompt" env:"OAUTH2_PROXY_PROMPT"`
100+ ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Deprecated by OIDC 1.0
101+ UserIDClaim string `flag:"user-id-claim" cfg:"user_id_claim" env:"OAUTH2_PROXY_USER_ID_CLAIM"`
102+
103+ // Configuration values for logging
104+ LoggingFilename string `flag:"logging-filename" cfg:"logging_filename" env:"OAUTH2_PROXY_LOGGING_FILENAME"`
105+ LoggingMaxSize int `flag:"logging-max-size" cfg:"logging_max_size" env:"OAUTH2_PROXY_LOGGING_MAX_SIZE"`
106+ LoggingMaxAge int `flag:"logging-max-age" cfg:"logging_max_age" env:"OAUTH2_PROXY_LOGGING_MAX_AGE"`
107+ LoggingMaxBackups int `flag:"logging-max-backups" cfg:"logging_max_backups" env:"OAUTH2_PROXY_LOGGING_MAX_BACKUPS"`
108+ LoggingLocalTime bool `flag:"logging-local-time" cfg:"logging_local_time" env:"OAUTH2_PROXY_LOGGING_LOCAL_TIME"`
109+ LoggingCompress bool `flag:"logging-compress" cfg:"logging_compress" env:"OAUTH2_PROXY_LOGGING_COMPRESS"`
110+ StandardLogging bool `flag:"standard-logging" cfg:"standard_logging" env:"OAUTH2_PROXY_STANDARD_LOGGING"`
111+ StandardLoggingFormat string `flag:"standard-logging-format" cfg:"standard_logging_format" env:"OAUTH2_PROXY_STANDARD_LOGGING_FORMAT"`
112+ RequestLogging bool `flag:"request-logging" cfg:"request_logging" env:"OAUTH2_PROXY_REQUEST_LOGGING"`
113+ RequestLoggingFormat string `flag:"request-logging-format" cfg:"request_logging_format" env:"OAUTH2_PROXY_REQUEST_LOGGING_FORMAT"`
114+ ExcludeLoggingPaths string `flag:"exclude-logging-paths" cfg:"exclude_logging_paths" env:"OAUTH2_PROXY_EXCLUDE_LOGGING_PATHS"`
115+ SilencePingLogging bool `flag:"silence-ping-logging" cfg:"silence_ping_logging" env:"OAUTH2_PROXY_SILENCE_PING_LOGGING"`
116+ AuthLogging bool `flag:"auth-logging" cfg:"auth_logging" env:"OAUTH2_PROXY_LOGGING_AUTH_LOGGING"`
117+ AuthLoggingFormat string `flag:"auth-logging-format" cfg:"auth_logging_format" env:"OAUTH2_PROXY_AUTH_LOGGING_FORMAT"`
118+ SignatureKey string `flag:"signature-key" cfg:"signature_key" env:"OAUTH2_PROXY_SIGNATURE_KEY"`
119+ AcrValues string `flag:"acr-values" cfg:"acr_values" env:"OAUTH2_PROXY_ACR_VALUES"`
120+ JWTKey string `flag:"jwt-key" cfg:"jwt_key" env:"OAUTH2_PROXY_JWT_KEY"`
121+ JWTKeyFile string `flag:"jwt-key-file" cfg:"jwt_key_file" env:"OAUTH2_PROXY_JWT_KEY_FILE"`
122+ PubJWKURL string `flag:"pubjwk-url" cfg:"pubjwk_url" env:"OAUTH2_PROXY_PUBJWK_URL"`
123+ GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks" env:"OAUTH2_PROXY_GCP_HEALTHCHECKS"`
124+
125+ // internal values that are set after config validation
126+ redirectURL *url.URL
127+ proxyURLs []*url.URL
128+ compiledRegex []*regexp.Regexp
129+ provider providers.Provider
130+ sessionStore sessionsapi.SessionStore
131+ signatureData *SignatureData
132+ oidcVerifier *oidc.IDTokenVerifier
133+ jwtBearerVerifiers []*oidc.IDTokenVerifier
134+ realClientIPParser logging.RealClientIPParser
135+}
136+
137+// Options for Getting internal values
138+func (o *Options) GetRedirectURL() *url.URL { return o.redirectURL }
139+func (o *Options) GetProxyURLs() []*url.URL { return o.proxyURLs }
140+func (o *Options) GetCompiledRegex() []*regexp.Regexp { return o.compiledRegex }
141+func (o *Options) GetProvider() providers.Provider { return o.provider }
142+func (o *Options) GetSessionStore() sessionsapi.SessionStore { return o.sessionStore }
143+func (o *Options) GetSignatureData() *SignatureData { return o.signatureData }
144+func (o *Options) GetOIDCVerifier() *oidc.IDTokenVerifier { return o.oidcVerifier }
145+func (o *Options) GetJWTBearerVerifiers() []*oidc.IDTokenVerifier { return o.jwtBearerVerifiers }
146+func (o *Options) GetRealClientIPParser() logging.RealClientIPParser { return o.realClientIPParser }
147+
148+// Options for Setting internal values
149+func (o *Options) SetRedirectURL(s *url.URL) { o.redirectURL = s }
150+func (o *Options) SetProxyURLs(s []*url.URL) { o.proxyURLs = s }
151+func (o *Options) SetCompiledRegex(s []*regexp.Regexp) { o.compiledRegex = s }
152+func (o *Options) SetProvider(s providers.Provider) { o.provider = s }
153+func (o *Options) SetSessionStore(s sessionsapi.SessionStore) { o.sessionStore = s }
154+func (o *Options) SetSignatureData(s *SignatureData) { o.signatureData = s }
155+func (o *Options) SetOIDCVerifier(s *oidc.IDTokenVerifier) { o.oidcVerifier = s }
156+func (o *Options) SetJWTBearerVerifiers(s []*oidc.IDTokenVerifier) { o.jwtBearerVerifiers = s }
157+func (o *Options) SetRealClientIPParser(s logging.RealClientIPParser) { o.realClientIPParser = s }
158+
159+// NewOptions constructs a new Options with defaulted values
160+func NewOptions() *Options {
161+ return &Options{
162+ ProxyPrefix: "/oauth2",
163+ PingPath: "/ping",
164+ ProxyWebSockets: true,
165+ HTTPAddress: "127.0.0.1:4180",
166+ HTTPSAddress: ":443",
167+ RealClientIPHeader: "X-Real-IP",
168+ ForceHTTPS: false,
169+ DisplayHtpasswdForm: true,
170+ Cookie: CookieOptions{
171+ Name: "_oauth2_proxy",
172+ Secure: true,
173+ HTTPOnly: true,
174+ Expire: time.Duration(168) * time.Hour,
175+ Refresh: time.Duration(0),
176+ },
177+ Session: SessionOptions{
178+ Type: "cookie",
179+ },
180+ SetXAuthRequest: false,
181+ SkipAuthPreflight: false,
182+ PassBasicAuth: true,
183+ SetBasicAuth: false,
184+ PassUserHeaders: true,
185+ PassAccessToken: false,
186+ PassHostHeader: true,
187+ SetAuthorization: false,
188+ PassAuthorization: false,
189+ PreferEmailToUser: false,
190+ Prompt: "", // Change to "login" when ApprovalPrompt officially deprecated
191+ ApprovalPrompt: "force",
192+ UserIDClaim: "email",
193+ InsecureOIDCAllowUnverifiedEmail: false,
194+ SkipOIDCDiscovery: false,
195+ LoggingFilename: "",
196+ LoggingMaxSize: 100,
197+ LoggingMaxAge: 7,
198+ LoggingMaxBackups: 0,
199+ LoggingLocalTime: true,
200+ LoggingCompress: false,
201+ ExcludeLoggingPaths: "",
202+ SilencePingLogging: false,
203+ StandardLogging: true,
204+ StandardLoggingFormat: logger.DefaultStandardLoggingFormat,
205+ RequestLogging: true,
206+ RequestLoggingFormat: logger.DefaultRequestLoggingFormat,
207+ AuthLogging: true,
208+ AuthLoggingFormat: logger.DefaultAuthLoggingFormat,
209+ }
210+}
options.go → pkg/validation/options.gorenamed+47−217
@@ -1,4 +1,4 @@
1−package main
1+package validation
22
33import (
44 "context"
@@ -14,11 +14,11 @@ import (
1414 "strings"
1515 "time"
1616
17− oidc "github.com/coreos/go-oidc"
17+ "github.com/coreos/go-oidc"
1818 "github.com/dgrijalva/jwt-go"
1919 "github.com/mbland/hmacauth"
20+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/logging"
2021 "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
21− sessionsapi "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/sessions"
2222 "github.com/oauth2-proxy/oauth2-proxy/pkg/encryption"
2323 "github.com/oauth2-proxy/oauth2-proxy/pkg/logger"
2424 "github.com/oauth2-proxy/oauth2-proxy/pkg/requests"
@@ -27,197 +27,9 @@ import (
2727 "gopkg.in/natefinch/lumberjack.v2"
2828)
2929
30−// Options holds Configuration Options that can be set by Command Line Flag,
31−// or Config File
32−type Options struct {
33− ProxyPrefix string `flag:"proxy-prefix" cfg:"proxy_prefix" env:"OAUTH2_PROXY_PROXY_PREFIX"`
34− PingPath string `flag:"ping-path" cfg:"ping_path" env:"OAUTH2_PROXY_PING_PATH"`
35− ProxyWebSockets bool `flag:"proxy-websockets" cfg:"proxy_websockets" env:"OAUTH2_PROXY_PROXY_WEBSOCKETS"`
36− HTTPAddress string `flag:"http-address" cfg:"http_address" env:"OAUTH2_PROXY_HTTP_ADDRESS"`
37− HTTPSAddress string `flag:"https-address" cfg:"https_address" env:"OAUTH2_PROXY_HTTPS_ADDRESS"`
38− ReverseProxy bool `flag:"reverse-proxy" cfg:"reverse_proxy" env:"OAUTH2_PROXY_REVERSE_PROXY"`
39− RealClientIPHeader string `flag:"real-client-ip-header" cfg:"real_client_ip_header" env:"OAUTH2_PROXY_REAL_CLIENT_IP_HEADER"`
40− ForceHTTPS bool `flag:"force-https" cfg:"force_https" env:"OAUTH2_PROXY_FORCE_HTTPS"`
41− RedirectURL string `flag:"redirect-url" cfg:"redirect_url" env:"OAUTH2_PROXY_REDIRECT_URL"`
42− ClientID string `flag:"client-id" cfg:"client_id" env:"OAUTH2_PROXY_CLIENT_ID"`
43− ClientSecret string `flag:"client-secret" cfg:"client_secret" env:"OAUTH2_PROXY_CLIENT_SECRET"`
44− ClientSecretFile string `flag:"client-secret-file" cfg:"client_secret_file" env:"OAUTH2_PROXY_CLIENT_SECRET_FILE"`
45− TLSCertFile string `flag:"tls-cert-file" cfg:"tls_cert_file" env:"OAUTH2_PROXY_TLS_CERT_FILE"`
46− TLSKeyFile string `flag:"tls-key-file" cfg:"tls_key_file" env:"OAUTH2_PROXY_TLS_KEY_FILE"`
47−
48− AuthenticatedEmailsFile string `flag:"authenticated-emails-file" cfg:"authenticated_emails_file" env:"OAUTH2_PROXY_AUTHENTICATED_EMAILS_FILE"`
49− KeycloakGroup string `flag:"keycloak-group" cfg:"keycloak_group" env:"OAUTH2_PROXY_KEYCLOAK_GROUP"`
50− AzureTenant string `flag:"azure-tenant" cfg:"azure_tenant" env:"OAUTH2_PROXY_AZURE_TENANT"`
51− BitbucketTeam string `flag:"bitbucket-team" cfg:"bitbucket_team" env:"OAUTH2_PROXY_BITBUCKET_TEAM"`
52− BitbucketRepository string `flag:"bitbucket-repository" cfg:"bitbucket_repository" env:"OAUTH2_PROXY_BITBUCKET_REPOSITORY"`
53− EmailDomains []string `flag:"email-domain" cfg:"email_domains" env:"OAUTH2_PROXY_EMAIL_DOMAINS"`
54− WhitelistDomains []string `flag:"whitelist-domain" cfg:"whitelist_domains" env:"OAUTH2_PROXY_WHITELIST_DOMAINS"`
55− GitHubOrg string `flag:"github-org" cfg:"github_org" env:"OAUTH2_PROXY_GITHUB_ORG"`
56− GitHubTeam string `flag:"github-team" cfg:"github_team" env:"OAUTH2_PROXY_GITHUB_TEAM"`
57− GitHubRepo string `flag:"github-repo" cfg:"github_repo" env:"OAUTH2_PROXY_GITHUB_REPO"`
58− GitHubToken string `flag:"github-token" cfg:"github_token" env:"OAUTH2_PROXY_GITHUB_TOKEN"`
59− GitLabGroup string `flag:"gitlab-group" cfg:"gitlab_group" env:"OAUTH2_PROXY_GITLAB_GROUP"`
60− GoogleGroups []string `flag:"google-group" cfg:"google_group" env:"OAUTH2_PROXY_GOOGLE_GROUPS"`
61− GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email" env:"OAUTH2_PROXY_GOOGLE_ADMIN_EMAIL"`
62− GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json" env:"OAUTH2_PROXY_GOOGLE_SERVICE_ACCOUNT_JSON"`
63− HtpasswdFile string `flag:"htpasswd-file" cfg:"htpasswd_file" env:"OAUTH2_PROXY_HTPASSWD_FILE"`
64− DisplayHtpasswdForm bool `flag:"display-htpasswd-form" cfg:"display_htpasswd_form" env:"OAUTH2_PROXY_DISPLAY_HTPASSWD_FORM"`
65− CustomTemplatesDir string `flag:"custom-templates-dir" cfg:"custom_templates_dir" env:"OAUTH2_PROXY_CUSTOM_TEMPLATES_DIR"`
66− Banner string `flag:"banner" cfg:"banner" env:"OAUTH2_PROXY_BANNER"`
67− Footer string `flag:"footer" cfg:"footer" env:"OAUTH2_PROXY_FOOTER"`
68−
69− Cookie options.CookieOptions `cfg:",squash"`
70− Session options.SessionOptions `cfg:",squash"`
71−
72− Upstreams []string `flag:"upstream" cfg:"upstreams" env:"OAUTH2_PROXY_UPSTREAMS"`
73− SkipAuthRegex []string `flag:"skip-auth-regex" cfg:"skip_auth_regex" env:"OAUTH2_PROXY_SKIP_AUTH_REGEX"`
74− SkipJwtBearerTokens bool `flag:"skip-jwt-bearer-tokens" cfg:"skip_jwt_bearer_tokens" env:"OAUTH2_PROXY_SKIP_JWT_BEARER_TOKENS"`
75− ExtraJwtIssuers []string `flag:"extra-jwt-issuers" cfg:"extra_jwt_issuers" env:"OAUTH2_PROXY_EXTRA_JWT_ISSUERS"`
76− PassBasicAuth bool `flag:"pass-basic-auth" cfg:"pass_basic_auth" env:"OAUTH2_PROXY_PASS_BASIC_AUTH"`
77− SetBasicAuth bool `flag:"set-basic-auth" cfg:"set_basic_auth" env:"OAUTH2_PROXY_SET_BASIC_AUTH"`
78− PreferEmailToUser bool `flag:"prefer-email-to-user" cfg:"prefer_email_to_user" env:"OAUTH2_PROXY_PREFER_EMAIL_TO_USER"`
79− BasicAuthPassword string `flag:"basic-auth-password" cfg:"basic_auth_password" env:"OAUTH2_PROXY_BASIC_AUTH_PASSWORD"`
80− PassAccessToken bool `flag:"pass-access-token" cfg:"pass_access_token" env:"OAUTH2_PROXY_PASS_ACCESS_TOKEN"`
81− PassHostHeader bool `flag:"pass-host-header" cfg:"pass_host_header" env:"OAUTH2_PROXY_PASS_HOST_HEADER"`
82− SkipProviderButton bool `flag:"skip-provider-button" cfg:"skip_provider_button" env:"OAUTH2_PROXY_SKIP_PROVIDER_BUTTON"`
83− PassUserHeaders bool `flag:"pass-user-headers" cfg:"pass_user_headers" env:"OAUTH2_PROXY_PASS_USER_HEADERS"`
84− SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify" env:"OAUTH2_PROXY_SSL_INSECURE_SKIP_VERIFY"`
85− SSLUpstreamInsecureSkipVerify bool `flag:"ssl-upstream-insecure-skip-verify" cfg:"ssl_upstream_insecure_skip_verify" env:"OAUTH2_PROXY_SSL_UPSTREAM_INSECURE_SKIP_VERIFY"`
86− SetXAuthRequest bool `flag:"set-xauthrequest" cfg:"set_xauthrequest" env:"OAUTH2_PROXY_SET_XAUTHREQUEST"`
87− SetAuthorization bool `flag:"set-authorization-header" cfg:"set_authorization_header" env:"OAUTH2_PROXY_SET_AUTHORIZATION_HEADER"`
88− PassAuthorization bool `flag:"pass-authorization-header" cfg:"pass_authorization_header" env:"OAUTH2_PROXY_PASS_AUTHORIZATION_HEADER"`
89− SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight" env:"OAUTH2_PROXY_SKIP_AUTH_PREFLIGHT"`
90− FlushInterval time.Duration `flag:"flush-interval" cfg:"flush_interval" env:"OAUTH2_PROXY_FLUSH_INTERVAL"`
91−
92− // These options allow for other providers besides Google, with
93− // potential overrides.
94− Provider string `flag:"provider" cfg:"provider" env:"OAUTH2_PROXY_PROVIDER"`
95− ProviderName string `flag:"provider-display-name" cfg:"provider_display_name" env:"OAUTH2_PROXY_PROVIDER_DISPLAY_NAME"`
96− OIDCIssuerURL string `flag:"oidc-issuer-url" cfg:"oidc_issuer_url" env:"OAUTH2_PROXY_OIDC_ISSUER_URL"`
97− InsecureOIDCAllowUnverifiedEmail bool `flag:"insecure-oidc-allow-unverified-email" cfg:"insecure_oidc_allow_unverified_email" env:"OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL"`
98− InsecureOIDCSkipIssuerVerification bool `flag:"insecure-oidc-skip-issuer-verification" cfg:"insecure_oidc_skip_issuer_verification" env:"OAUTH2_PROXY_INSECURE_OIDC_SKIP_ISSUER_VERIFICATION"`
99− SkipOIDCDiscovery bool `flag:"skip-oidc-discovery" cfg:"skip_oidc_discovery" env:"OAUTH2_PROXY_SKIP_OIDC_DISCOVERY"`
100− OIDCJwksURL string `flag:"oidc-jwks-url" cfg:"oidc_jwks_url" env:"OAUTH2_PROXY_OIDC_JWKS_URL"`
101− LoginURL string `flag:"login-url" cfg:"login_url" env:"OAUTH2_PROXY_LOGIN_URL"`
102− RedeemURL string `flag:"redeem-url" cfg:"redeem_url" env:"OAUTH2_PROXY_REDEEM_URL"`
103− ProfileURL string `flag:"profile-url" cfg:"profile_url" env:"OAUTH2_PROXY_PROFILE_URL"`
104− ProtectedResource string `flag:"resource" cfg:"resource" env:"OAUTH2_PROXY_RESOURCE"`
105− ValidateURL string `flag:"validate-url" cfg:"validate_url" env:"OAUTH2_PROXY_VALIDATE_URL"`
106− Scope string `flag:"scope" cfg:"scope" env:"OAUTH2_PROXY_SCOPE"`
107− Prompt string `flag:"prompt" cfg:"prompt" env:"OAUTH2_PROXY_PROMPT"`
108− ApprovalPrompt string `flag:"approval-prompt" cfg:"approval_prompt" env:"OAUTH2_PROXY_APPROVAL_PROMPT"` // Deprecated by OIDC 1.0
109− UserIDClaim string `flag:"user-id-claim" cfg:"user_id_claim" env:"OAUTH2_PROXY_USER_ID_CLAIM"`
110−
111− // Configuration values for logging
112− LoggingFilename string `flag:"logging-filename" cfg:"logging_filename" env:"OAUTH2_PROXY_LOGGING_FILENAME"`
113− LoggingMaxSize int `flag:"logging-max-size" cfg:"logging_max_size" env:"OAUTH2_PROXY_LOGGING_MAX_SIZE"`
114− LoggingMaxAge int `flag:"logging-max-age" cfg:"logging_max_age" env:"OAUTH2_PROXY_LOGGING_MAX_AGE"`
115− LoggingMaxBackups int `flag:"logging-max-backups" cfg:"logging_max_backups" env:"OAUTH2_PROXY_LOGGING_MAX_BACKUPS"`
116− LoggingLocalTime bool `flag:"logging-local-time" cfg:"logging_local_time" env:"OAUTH2_PROXY_LOGGING_LOCAL_TIME"`
117− LoggingCompress bool `flag:"logging-compress" cfg:"logging_compress" env:"OAUTH2_PROXY_LOGGING_COMPRESS"`
118− StandardLogging bool `flag:"standard-logging" cfg:"standard_logging" env:"OAUTH2_PROXY_STANDARD_LOGGING"`
119− StandardLoggingFormat string `flag:"standard-logging-format" cfg:"standard_logging_format" env:"OAUTH2_PROXY_STANDARD_LOGGING_FORMAT"`
120− RequestLogging bool `flag:"request-logging" cfg:"request_logging" env:"OAUTH2_PROXY_REQUEST_LOGGING"`
121− RequestLoggingFormat string `flag:"request-logging-format" cfg:"request_logging_format" env:"OAUTH2_PROXY_REQUEST_LOGGING_FORMAT"`
122− ExcludeLoggingPaths string `flag:"exclude-logging-paths" cfg:"exclude_logging_paths" env:"OAUTH2_PROXY_EXCLUDE_LOGGING_PATHS"`
123− SilencePingLogging bool `flag:"silence-ping-logging" cfg:"silence_ping_logging" env:"OAUTH2_PROXY_SILENCE_PING_LOGGING"`
124− AuthLogging bool `flag:"auth-logging" cfg:"auth_logging" env:"OAUTH2_PROXY_LOGGING_AUTH_LOGGING"`
125− AuthLoggingFormat string `flag:"auth-logging-format" cfg:"auth_logging_format" env:"OAUTH2_PROXY_AUTH_LOGGING_FORMAT"`
126− SignatureKey string `flag:"signature-key" cfg:"signature_key" env:"OAUTH2_PROXY_SIGNATURE_KEY"`
127− AcrValues string `flag:"acr-values" cfg:"acr_values" env:"OAUTH2_PROXY_ACR_VALUES"`
128− JWTKey string `flag:"jwt-key" cfg:"jwt_key" env:"OAUTH2_PROXY_JWT_KEY"`
129− JWTKeyFile string `flag:"jwt-key-file" cfg:"jwt_key_file" env:"OAUTH2_PROXY_JWT_KEY_FILE"`
130− PubJWKURL string `flag:"pubjwk-url" cfg:"pubjwk_url" env:"OAUTH2_PROXY_PUBJWK_URL"`
131− GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks" env:"OAUTH2_PROXY_GCP_HEALTHCHECKS"`
132−
133− // internal values that are set after config validation
134− redirectURL *url.URL
135− proxyURLs []*url.URL
136− compiledRegex []*regexp.Regexp
137− provider providers.Provider
138− sessionStore sessionsapi.SessionStore
139− signatureData *SignatureData
140− oidcVerifier *oidc.IDTokenVerifier
141− jwtBearerVerifiers []*oidc.IDTokenVerifier
142− realClientIPParser realClientIPParser
143−}
144−
145−// SignatureData holds hmacauth signature hash and key
146−type SignatureData struct {
147− hash crypto.Hash
148− key string
149−}
150−
151−// NewOptions constructs a new Options with defaulted values
152−func NewOptions() *Options {
153− return &Options{
154− ProxyPrefix: "/oauth2",
155− PingPath: "/ping",
156− ProxyWebSockets: true,
157− HTTPAddress: "127.0.0.1:4180",
158− HTTPSAddress: ":443",
159− ForceHTTPS: false,
160− DisplayHtpasswdForm: true,
161− Cookie: options.CookieOptions{
162− Name: "_oauth2_proxy",
163− Secure: true,
164− HTTPOnly: true,
165− Expire: time.Duration(168) * time.Hour,
166− Refresh: time.Duration(0),
167− },
168− Session: options.SessionOptions{
169− Type: "cookie",
170− },
171− SetXAuthRequest: false,
172− SkipAuthPreflight: false,
173− PassBasicAuth: true,
174− SetBasicAuth: false,
175− PassUserHeaders: true,
176− PassAccessToken: false,
177− PassHostHeader: true,
178− SetAuthorization: false,
179− PassAuthorization: false,
180− PreferEmailToUser: false,
181− Prompt: "", // Change to "login" when ApprovalPrompt officially deprecated
182− ApprovalPrompt: "force",
183− UserIDClaim: "email",
184− InsecureOIDCAllowUnverifiedEmail: false,
185− SkipOIDCDiscovery: false,
186− LoggingFilename: "",
187− LoggingMaxSize: 100,
188− LoggingMaxAge: 7,
189− LoggingMaxBackups: 0,
190− LoggingLocalTime: true,
191− LoggingCompress: false,
192− ExcludeLoggingPaths: "",
193− SilencePingLogging: false,
194− StandardLogging: true,
195− StandardLoggingFormat: logger.DefaultStandardLoggingFormat,
196− RequestLogging: true,
197− RequestLoggingFormat: logger.DefaultRequestLoggingFormat,
198− AuthLogging: true,
199− AuthLoggingFormat: logger.DefaultAuthLoggingFormat,
200− }
201−}
202−
203−// jwtIssuer hold parsed JWT issuer info that's used to construct a verifier.
204−type jwtIssuer struct {
205− issuerURI string
206− audience string
207−}
208−
209−func parseURL(toParse string, urltype string, msgs []string) (*url.URL, []string) {
210− parsed, err := url.Parse(toParse)
211− if err != nil {
212− return nil, append(msgs, fmt.Sprintf(
213− "error parsing %s-url=%q %s", urltype, toParse, err))
214− }
215− return parsed, msgs
216−}
217−
21830// Validate checks that required options are set and validates those that they
21931// are of the correct format
220−func (o *Options) Validate() error {
32+func Validate(o *options.Options) error {
22133 if o.SSLInsecureSkipVerify {
22234 // TODO: Accept a certificate bundle.
22335 insecureTransport := &http.Transport{
@@ -234,7 +46,7 @@ func (o *Options) Validate() error {
23446 msgs = append(msgs, "missing setting: client-id")
23547 }
23648 // login.gov uses a signed JWT to authenticate, not a client-secret
237− if o.Provider != "login.gov" {
49+ if o.ProviderType != "login.gov" {
23850 if o.ClientSecret == "" && o.ClientSecretFile == "" {
23951 msgs = append(msgs, "missing setting: client-secret or client-secret-file")
24052 }
@@ -311,20 +123,20 @@ func (o *Options) Validate() error {
311123 msgs = append(msgs, "missing setting: oidc-jwks-url")
312124 }
313125 keySet := oidc.NewRemoteKeySet(ctx, o.OIDCJwksURL)
314− o.oidcVerifier = oidc.NewVerifier(o.OIDCIssuerURL, keySet, &oidc.Config{
126+ o.SetOIDCVerifier(oidc.NewVerifier(o.OIDCIssuerURL, keySet, &oidc.Config{
315127 ClientID: o.ClientID,
316128 SkipIssuerCheck: o.InsecureOIDCSkipIssuerVerification,
317− })
129+ }))
318130 } else {
319131 // Configure discoverable provider data.
320132 provider, err := oidc.NewProvider(ctx, o.OIDCIssuerURL)
321133 if err != nil {
322134 return err
323135 }
324− o.oidcVerifier = provider.Verifier(&oidc.Config{
136+ o.SetOIDCVerifier(provider.Verifier(&oidc.Config{
325137 ClientID: o.ClientID,
326138 SkipIssuerCheck: o.InsecureOIDCSkipIssuerVerification,
327− })
139+ }))
328140
329141 o.LoginURL = provider.Endpoint().AuthURL
330142 o.RedeemURL = provider.Endpoint().TokenURL
@@ -340,8 +152,8 @@ func (o *Options) Validate() error {
340152
341153 if o.SkipJwtBearerTokens {
342154 // If we are using an oidc provider, go ahead and add that provider to the list
343− if o.oidcVerifier != nil {
344− o.jwtBearerVerifiers = append(o.jwtBearerVerifiers, o.oidcVerifier)
155+ if o.GetOIDCVerifier() != nil {
156+ o.SetJWTBearerVerifiers(append(o.GetJWTBearerVerifiers(), o.GetOIDCVerifier()))
345157 }
346158 // Configure extra issuers
347159 if len(o.ExtraJwtIssuers) > 0 {
@@ -352,12 +164,14 @@ func (o *Options) Validate() error {
352164 if err != nil {
353165 msgs = append(msgs, fmt.Sprintf("error building verifiers: %s", err))
354166 }
355− o.jwtBearerVerifiers = append(o.jwtBearerVerifiers, verifier)
167+ o.SetJWTBearerVerifiers(append(o.GetJWTBearerVerifiers(), verifier))
356168 }
357169 }
358170 }
359171
360− o.redirectURL, msgs = parseURL(o.RedirectURL, "redirect", msgs)
172+ var redirectURL *url.URL
173+ redirectURL, msgs = parseURL(o.RawRedirectURL, "redirect", msgs)
174+ o.SetRedirectURL(redirectURL)
361175
362176 for _, u := range o.Upstreams {
363177 upstreamURL, err := url.Parse(u)
@@ -367,7 +181,7 @@ func (o *Options) Validate() error {
367181 if upstreamURL.Path == "" {
368182 upstreamURL.Path = "/"
369183 }
370− o.proxyURLs = append(o.proxyURLs, upstreamURL)
184+ o.SetProxyURLs(append(o.GetProxyURLs(), upstreamURL))
371185 }
372186 }
373187
@@ -377,7 +191,7 @@ func (o *Options) Validate() error {
377191 msgs = append(msgs, fmt.Sprintf("error compiling regex=%q %s", u, err))
378192 continue
379193 }
380− o.compiledRegex = append(o.compiledRegex, compiledRegex)
194+ o.SetCompiledRegex(append(o.GetCompiledRegex(), compiledRegex))
381195 }
382196 msgs = parseProviderInfo(o, msgs)
383197
@@ -418,7 +232,7 @@ func (o *Options) Validate() error {
418232 if err != nil {
419233 msgs = append(msgs, fmt.Sprintf("error initialising session storage: %v", err))
420234 } else {
421− o.sessionStore = sessionStore
235+ o.SetSessionStore(sessionStore)
422236 }
423237
424238 if o.Cookie.Refresh >= o.Cookie.Expire {
@@ -458,10 +272,11 @@ func (o *Options) Validate() error {
458272 msgs = setupLogger(o, msgs)
459273
460274 if o.ReverseProxy {
461− o.realClientIPParser, err = getRealClientIPParser(o.RealClientIPHeader)
275+ parser, err := logging.GetRealClientIPParser(o.RealClientIPHeader)
462276 if err != nil {
463277 msgs = append(msgs, fmt.Sprintf("real_client_ip_header (%s) not accepted parameter value: %v", o.RealClientIPHeader, err))
464278 }
279+ o.SetRealClientIPParser(parser)
465280 }
466281
467282 if len(msgs) != 0 {
@@ -471,7 +286,7 @@ func (o *Options) Validate() error {
471286 return nil
472287}
473288
474−func parseProviderInfo(o *Options, msgs []string) []string {
289+func parseProviderInfo(o *options.Options, msgs []string) []string {
475290 p := &providers.ProviderData{
476291 Scope: o.Scope,
477292 ClientID: o.ClientID,
@@ -487,8 +302,8 @@ func parseProviderInfo(o *Options, msgs []string) []string {
487302 p.ValidateURL, msgs = parseURL(o.ValidateURL, "validate", msgs)
488303 p.ProtectedResource, msgs = parseURL(o.ProtectedResource, "resource", msgs)
489304
490− o.provider = providers.New(o.Provider, p)
491− switch p := o.provider.(type) {
305+ o.SetProvider(providers.New(o.ProviderType, p))
306+ switch p := o.GetProvider().(type) {
492307 case *providers.AzureProvider:
493308 p.Configure(o.AzureTenant)
494309 case *providers.GitHubProvider:
@@ -511,18 +326,18 @@ func parseProviderInfo(o *Options, msgs []string) []string {
511326 case *providers.OIDCProvider:
512327 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
513328 p.UserIDClaim = o.UserIDClaim
514− if o.oidcVerifier == nil {
329+ if o.GetOIDCVerifier() == nil {
515330 msgs = append(msgs, "oidc provider requires an oidc issuer URL")
516331 } else {
517− p.Verifier = o.oidcVerifier
332+ p.Verifier = o.GetOIDCVerifier()
518333 }
519334 case *providers.GitLabProvider:
520335 p.AllowUnverifiedEmail = o.InsecureOIDCAllowUnverifiedEmail
521336 p.Group = o.GitLabGroup
522337 p.EmailDomains = o.EmailDomains
523338
524− if o.oidcVerifier != nil {
525− p.Verifier = o.oidcVerifier
339+ if o.GetOIDCVerifier() != nil {
340+ p.Verifier = o.GetOIDCVerifier()
526341 } else {
527342 // Initialize with default verifier for gitlab.com
528343 ctx := context.Background()
@@ -573,7 +388,7 @@ func parseProviderInfo(o *Options, msgs []string) []string {
573388 return msgs
574389}
575390
576−func parseSignatureKey(o *Options, msgs []string) []string {
391+func parseSignatureKey(o *options.Options, msgs []string) []string {
577392 if o.SignatureKey == "" {
578393 return msgs
579394 }
@@ -591,7 +406,7 @@ func parseSignatureKey(o *Options, msgs []string) []string {
591406 return append(msgs, "unsupported signature hash algorithm: "+
592407 o.SignatureKey)
593408 }
594− o.signatureData = &SignatureData{hash: hash, key: secretKey}
409+ o.SetSignatureData(&options.SignatureData{Hash: hash, Key: secretKey})
595410 return msgs
596411}
597412
@@ -634,7 +449,7 @@ func newVerifierFromJwtIssuer(jwtIssuer jwtIssuer) (*oidc.IDTokenVerifier, error
634449 return verifier, nil
635450}
636451
637−func validateCookieName(o *Options, msgs []string) []string {
452+func validateCookieName(o *options.Options, msgs []string) []string {
638453 cookie := &http.Cookie{Name: o.Cookie.Name}
639454 if cookie.String() == "" {
640455 return append(msgs, fmt.Sprintf("invalid cookie name: %q", o.Cookie.Name))
@@ -642,7 +457,7 @@ func validateCookieName(o *Options, msgs []string) []string {
642457 return msgs
643458}
644459
645−func setupLogger(o *Options, msgs []string) []string {
460+func setupLogger(o *options.Options, msgs []string) []string {
646461 // Setup the log file
647462 if len(o.LoggingFilename) > 0 {
648463 // Validate that the file/dir can be written
@@ -681,7 +496,7 @@ func setupLogger(o *Options, msgs []string) []string {
681496 logger.SetAuthTemplate(o.AuthLoggingFormat)
682497 logger.SetReqTemplate(o.RequestLoggingFormat)
683498 logger.SetGetClientFunc(func(r *http.Request) string {
684− return getClientString(o.realClientIPParser, r, false)
499+ return logging.GetClientString(o.GetRealClientIPParser(), r, false)
685500 })
686501
687502 excludePaths := make([]string, 0)
@@ -698,3 +513,18 @@ func setupLogger(o *Options, msgs []string) []string {
698513
699514 return msgs
700515}
516+
517+// jwtIssuer hold parsed JWT issuer info that's used to construct a verifier.
518+type jwtIssuer struct {
519+ issuerURI string
520+ audience string
521+}
522+
523+func parseURL(toParse string, urltype string, msgs []string) (*url.URL, []string) {
524+ parsed, err := url.Parse(toParse)
525+ if err != nil {
526+ return nil, append(msgs, fmt.Sprintf(
527+ "error parsing %s-url=%q %s", urltype, toParse, err))
528+ }
529+ return parsed, msgs
530+}
options_test.go → pkg/validation/options_test.gorenamed+63−66
@@ -1,4 +1,4 @@
1−package main
1+package validation
22
33import (
44 "crypto"
@@ -10,6 +10,7 @@ import (
1010 "testing"
1111 "time"
1212
13+ "github.com/oauth2-proxy/oauth2-proxy/pkg/apis/options"
1314 "github.com/stretchr/testify/assert"
1415)
1516
@@ -19,8 +20,8 @@ const (
1920 clientSecret = "xyzzyplugh"
2021)
2122
22−func testOptions() *Options {
23− o := NewOptions()
23+func testOptions() *options.Options {
24+ o := options.NewOptions()
2425 o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8080/")
2526 o.Cookie.Secret = cookieSecret
2627 o.ClientID = clientID
@@ -37,9 +38,9 @@ func errorMsg(msgs []string) string {
3738}
3839
3940func TestNewOptions(t *testing.T) {
40− o := NewOptions()
41+ o := options.NewOptions()
4142 o.EmailDomains = []string{"*"}
42− err := o.Validate()
43+ err := Validate(o)
4344 assert.NotEqual(t, nil, err)
4445
4546 expected := errorMsg([]string{
@@ -50,15 +51,15 @@ func TestNewOptions(t *testing.T) {
5051}
5152
5253func TestClientSecretFileOptionFails(t *testing.T) {
53− o := NewOptions()
54+ o := options.NewOptions()
5455 o.Cookie.Secret = cookieSecret
5556 o.ClientID = clientID
5657 o.ClientSecretFile = clientSecret
5758 o.EmailDomains = []string{"*"}
58− err := o.Validate()
59+ err := Validate(o)
5960 assert.NotEqual(t, nil, err)
6061
61− p := o.provider.Data()
62+ p := o.GetProvider().Data()
6263 assert.Equal(t, clientSecret, p.ClientSecretFile)
6364 assert.Equal(t, "", p.ClientSecret)
6465
@@ -80,15 +81,15 @@ func TestClientSecretFileOption(t *testing.T) {
8081 clientSecretFileName := f.Name()
8182 defer os.Remove(clientSecretFileName)
8283
83− o := NewOptions()
84+ o := options.NewOptions()
8485 o.Cookie.Secret = cookieSecret
8586 o.ClientID = clientID
8687 o.ClientSecretFile = clientSecretFileName
8788 o.EmailDomains = []string{"*"}
88− err = o.Validate()
89+ err = Validate(o)
8990 assert.Equal(t, nil, err)
9091
91− p := o.provider.Data()
92+ p := o.GetProvider().Data()
9293 assert.Equal(t, clientSecretFileName, p.ClientSecretFile)
9394 assert.Equal(t, "", p.ClientSecret)
9495
@@ -100,7 +101,7 @@ func TestClientSecretFileOption(t *testing.T) {
100101func TestGoogleGroupOptions(t *testing.T) {
101102 o := testOptions()
102103 o.GoogleGroups = []string{"googlegroup"}
103− err := o.Validate()
104+ err := Validate(o)
104105 assert.NotEqual(t, nil, err)
105106
106107 expected := errorMsg([]string{
@@ -114,7 +115,7 @@ func TestGoogleGroupInvalidFile(t *testing.T) {
114115 o.GoogleGroups = []string{"test_group"}
115116 o.GoogleAdminEmail = "admin@example.com"
116117 o.GoogleServiceAccountJSON = "file_doesnt_exist.json"
117− err := o.Validate()
118+ err := Validate(o)
118119 assert.NotEqual(t, nil, err)
119120
120121 expected := errorMsg([]string{
@@ -125,36 +126,36 @@ func TestGoogleGroupInvalidFile(t *testing.T) {
125126
126127func TestInitializedOptions(t *testing.T) {
127128 o := testOptions()
128− assert.Equal(t, nil, o.Validate())
129+ assert.Equal(t, nil, Validate(o))
129130}
130131
131132// Note that it's not worth testing nonparseable URLs, since url.Parse()
132133// seems to parse damn near anything.
133134func TestRedirectURL(t *testing.T) {
134135 o := testOptions()
135− o.RedirectURL = "https://myhost.com/oauth2/callback"
136− assert.Equal(t, nil, o.Validate())
136+ o.RawRedirectURL = "https://myhost.com/oauth2/callback"
137+ assert.Equal(t, nil, Validate(o))
137138 expected := &url.URL{
138139 Scheme: "https", Host: "myhost.com", Path: "/oauth2/callback"}
139− assert.Equal(t, expected, o.redirectURL)
140+ assert.Equal(t, expected, o.GetRedirectURL())
140141}
141142
142143func TestProxyURLs(t *testing.T) {
143144 o := testOptions()
144145 o.Upstreams = append(o.Upstreams, "http://127.0.0.1:8081")
145− assert.Equal(t, nil, o.Validate())
146+ assert.Equal(t, nil, Validate(o))
146147 expected := []*url.URL{
147148 {Scheme: "http", Host: "127.0.0.1:8080", Path: "/"},
148149 // note the '/' was added
149150 {Scheme: "http", Host: "127.0.0.1:8081", Path: "/"},
150151 }
151− assert.Equal(t, expected, o.proxyURLs)
152+ assert.Equal(t, expected, o.GetProxyURLs())
152153}
153154
154155func TestProxyURLsError(t *testing.T) {
155156 o := testOptions()
156157 o.Upstreams = append(o.Upstreams, "127.0.0.1:8081")
157− err := o.Validate()
158+ err := Validate(o)
158159 assert.NotEqual(t, nil, err)
159160 assert.Contains(t, err.Error(), "error parsing upstream")
160161}
@@ -163,9 +164,9 @@ func TestCompiledRegex(t *testing.T) {
163164 o := testOptions()
164165 regexps := []string{"/foo/.*", "/ba[rz]/quux"}
165166 o.SkipAuthRegex = regexps
166− assert.Equal(t, nil, o.Validate())
167+ assert.Equal(t, nil, Validate(o))
167168 actual := make([]string, 0)
168− for _, regex := range o.compiledRegex {
169+ for _, regex := range o.GetCompiledRegex() {
169170 actual = append(actual, regex.String())
170171 }
171172 assert.Equal(t, regexps, actual)
@@ -174,7 +175,7 @@ func TestCompiledRegex(t *testing.T) {
174175func TestCompiledRegexError(t *testing.T) {
175176 o := testOptions()
176177 o.SkipAuthRegex = []string{"(foobaz", "barquux)"}
177− err := o.Validate()
178+ err := Validate(o)
178179 assert.NotEqual(t, nil, err)
179180
180181 expected := errorMsg([]string{
@@ -185,7 +186,7 @@ func TestCompiledRegexError(t *testing.T) {
185186 assert.Equal(t, expected, err.Error())
186187
187188 o.SkipAuthRegex = []string{"foobaz", "barquux)"}
188− err = o.Validate()
189+ err = Validate(o)
189190 assert.NotEqual(t, nil, err)
190191
191192 expected = errorMsg([]string{
@@ -196,8 +197,8 @@ func TestCompiledRegexError(t *testing.T) {
196197
197198func TestDefaultProviderApiSettings(t *testing.T) {
198199 o := testOptions()
199− assert.Equal(t, nil, o.Validate())
200− p := o.provider.Data()
200+ assert.Equal(t, nil, Validate(o))
201+ p := o.GetProvider().Data()
201202 assert.Equal(t, "https://accounts.google.com/o/oauth2/auth?access_type=offline",
202203 p.LoginURL.String())
203204 assert.Equal(t, "https://www.googleapis.com/oauth2/v3/token",
@@ -208,76 +209,76 @@ func TestDefaultProviderApiSettings(t *testing.T) {
208209
209210func TestPassAccessTokenRequiresSpecificCookieSecretLengths(t *testing.T) {
210211 o := testOptions()
211− assert.Equal(t, nil, o.Validate())
212+ assert.Equal(t, nil, Validate(o))
212213
213214 assert.Equal(t, false, o.PassAccessToken)
214215 o.PassAccessToken = true
215216 o.Cookie.Secret = "cookie of invalid length-"
216− assert.NotEqual(t, nil, o.Validate())
217+ assert.NotEqual(t, nil, Validate(o))
217218
218219 o.PassAccessToken = false
219220 o.Cookie.Refresh = time.Duration(24) * time.Hour
220− assert.NotEqual(t, nil, o.Validate())
221+ assert.NotEqual(t, nil, Validate(o))
221222
222223 o.Cookie.Secret = "16 bytes AES-128"
223− assert.Equal(t, nil, o.Validate())
224+ assert.Equal(t, nil, Validate(o))
224225
225226 o.Cookie.Secret = "24 byte secret AES-192--"
226− assert.Equal(t, nil, o.Validate())
227+ assert.Equal(t, nil, Validate(o))
227228
228229 o.Cookie.Secret = "32 byte secret for AES-256------"
229− assert.Equal(t, nil, o.Validate())
230+ assert.Equal(t, nil, Validate(o))
230231}
231232
232233func TestCookieRefreshMustBeLessThanCookieExpire(t *testing.T) {
233234 o := testOptions()
234− assert.Equal(t, nil, o.Validate())
235+ assert.Equal(t, nil, Validate(o))
235236
236237 o.Cookie.Secret = "0123456789abcdef"
237238 o.Cookie.Refresh = o.Cookie.Expire
238− assert.NotEqual(t, nil, o.Validate())
239+ assert.NotEqual(t, nil, Validate(o))
239240
240241 o.Cookie.Refresh -= time.Duration(1)
241− assert.Equal(t, nil, o.Validate())
242+ assert.Equal(t, nil, Validate(o))
242243}
243244
244245func TestBase64CookieSecret(t *testing.T) {
245246 o := testOptions()
246− assert.Equal(t, nil, o.Validate())
247+ assert.Equal(t, nil, Validate(o))
247248
248249 // 32 byte, base64 (urlsafe) encoded key
249250 o.Cookie.Secret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ="
250− assert.Equal(t, nil, o.Validate())
251+ assert.Equal(t, nil, Validate(o))
251252
252253 // 32 byte, base64 (urlsafe) encoded key, w/o padding
253254 o.Cookie.Secret = "yHBw2lh2Cvo6aI_jn_qMTr-pRAjtq0nzVgDJNb36jgQ"
254− assert.Equal(t, nil, o.Validate())
255+ assert.Equal(t, nil, Validate(o))
255256
256257 // 24 byte, base64 (urlsafe) encoded key
257258 o.Cookie.Secret = "Kp33Gj-GQmYtz4zZUyUDdqQKx5_Hgkv3"
258− assert.Equal(t, nil, o.Validate())
259+ assert.Equal(t, nil, Validate(o))
259260
260261 // 16 byte, base64 (urlsafe) encoded key
261262 o.Cookie.Secret = "LFEqZYvYUwKwzn0tEuTpLA=="
262− assert.Equal(t, nil, o.Validate())
263+ assert.Equal(t, nil, Validate(o))
263264
264265 // 16 byte, base64 (urlsafe) encoded key, w/o padding
265266 o.Cookie.Secret = "LFEqZYvYUwKwzn0tEuTpLA"
266− assert.Equal(t, nil, o.Validate())
267+ assert.Equal(t, nil, Validate(o))
267268}
268269
269270func TestValidateSignatureKey(t *testing.T) {
270271 o := testOptions()
271272 o.SignatureKey = "sha1:secret"
272− assert.Equal(t, nil, o.Validate())
273− assert.Equal(t, o.signatureData.hash, crypto.SHA1)
274− assert.Equal(t, o.signatureData.key, "secret")
273+ assert.Equal(t, nil, Validate(o))
274+ assert.Equal(t, o.GetSignatureData().Hash, crypto.SHA1)
275+ assert.Equal(t, o.GetSignatureData().Key, "secret")
275276}
276277
277278func TestValidateSignatureKeyInvalidSpec(t *testing.T) {
278279 o := testOptions()
279280 o.SignatureKey = "invalid spec"
280− err := o.Validate()
281+ err := Validate(o)
281282 assert.Equal(t, err.Error(), "invalid configuration:\n"+
282283 " invalid signature hash:key spec: "+o.SignatureKey)
283284}
@@ -285,7 +286,7 @@ func TestValidateSignatureKeyInvalidSpec(t *testing.T) {
285286func TestValidateSignatureKeyUnsupportedAlgorithm(t *testing.T) {
286287 o := testOptions()
287288 o.SignatureKey = "unsupported:default secret"
288− err := o.Validate()
289+ err := Validate(o)
289290 assert.Equal(t, err.Error(), "invalid configuration:\n"+
290291 " unsupported signature hash algorithm: "+o.SignatureKey)
291292}
@@ -293,24 +294,24 @@ func TestValidateSignatureKeyUnsupportedAlgorithm(t *testing.T) {
293294func TestValidateCookie(t *testing.T) {
294295 o := testOptions()
295296 o.Cookie.Name = "_valid_cookie_name"
296− assert.Equal(t, nil, o.Validate())
297+ assert.Equal(t, nil, Validate(o))
297298}
298299
299300func TestValidateCookieBadName(t *testing.T) {
300301 o := testOptions()
301302 o.Cookie.Name = "_bad_cookie_name{}"
302− err := o.Validate()
303+ err := Validate(o)
303304 assert.Equal(t, err.Error(), "invalid configuration:\n"+
304305 fmt.Sprintf(" invalid cookie name: %q", o.Cookie.Name))
305306}
306307
307308func TestSkipOIDCDiscovery(t *testing.T) {
308309 o := testOptions()
309− o.Provider = "oidc"
310+ o.ProviderType = "oidc"
310311 o.OIDCIssuerURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/v2.0/"
311312 o.SkipOIDCDiscovery = true
312313
313− err := o.Validate()
314+ err := Validate(o)
314315 assert.Equal(t, "invalid configuration:\n"+
315316 " missing setting: login-url\n missing setting: redeem-url\n missing setting: oidc-jwks-url", err.Error())
316317
@@ -318,54 +319,50 @@ func TestSkipOIDCDiscovery(t *testing.T) {
318319 o.RedeemURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/oauth2/v2.0/token?p=b2c_1_sign_in"
319320 o.OIDCJwksURL = "https://login.microsoftonline.com/fabrikamb2c.onmicrosoft.com/discovery/v2.0/keys"
320321
321− assert.Equal(t, nil, o.Validate())
322+ assert.Equal(t, nil, Validate(o))
322323}
323324
324325func TestGCPHealthcheck(t *testing.T) {
325326 o := testOptions()
326327 o.GCPHealthChecks = true
327− assert.Equal(t, nil, o.Validate())
328+ assert.Equal(t, nil, Validate(o))
328329}
329330
330331func TestRealClientIPHeader(t *testing.T) {
331− var o *Options
332− var err error
333− var expected string
334−
335332 // Ensure nil if ReverseProxy not set.
336− o = testOptions()
333+ o := testOptions()
337334 o.RealClientIPHeader = "X-Real-IP"
338− assert.Equal(t, nil, o.Validate())
339− assert.Nil(t, o.realClientIPParser)
335+ assert.Equal(t, nil, Validate(o))
336+ assert.Nil(t, o.GetRealClientIPParser())
340337
341338 // Ensure simple use case works.
342339 o = testOptions()
343340 o.ReverseProxy = true
344341 o.RealClientIPHeader = "X-Forwarded-For"
345− assert.Equal(t, nil, o.Validate())
346− assert.NotNil(t, o.realClientIPParser)
342+ assert.Equal(t, nil, Validate(o))
343+ assert.NotNil(t, o.GetRealClientIPParser())
347344
348345 // Ensure unknown header format process an error.
349346 o = testOptions()
350347 o.ReverseProxy = true
351348 o.RealClientIPHeader = "Forwarded"
352− err = o.Validate()
349+ err := Validate(o)
353350 assert.NotEqual(t, nil, err)
354− expected = errorMsg([]string{
351+ expected := errorMsg([]string{
355352 "real_client_ip_header (Forwarded) not accepted parameter value: the http header key (Forwarded) is either invalid or unsupported",
356353 })
357354 assert.Equal(t, expected, err.Error())
358− assert.Nil(t, o.realClientIPParser)
355+ assert.Nil(t, o.GetRealClientIPParser())
359356
360357 // Ensure invalid header format produces an error.
361358 o = testOptions()
362359 o.ReverseProxy = true
363360 o.RealClientIPHeader = "!934invalidheader-23:"
364− err = o.Validate()
361+ err = Validate(o)
365362 assert.NotEqual(t, nil, err)
366363 expected = errorMsg([]string{
367364 "real_client_ip_header (!934invalidheader-23:) not accepted parameter value: the http header key (!934invalidheader-23:) is either invalid or unsupported",
368365 })
369366 assert.Equal(t, expected, err.Error())
370− assert.Nil(t, o.realClientIPParser)
367+ assert.Nil(t, o.GetRealClientIPParser())
371368}