git.iko.soy/typeable/oauth2-proxy
on master help sign in
Add tests for skip auth functionality
cfd3de8Nick Meves
oauthproxy.go+1−1
@@ -286,7 +286,7 @@ func buildSignInMessage(opts *options.Options) string {
286// SkipAuthRegex option (paths only support) or newer SkipAuthRoutes option
286// SkipAuthRegex option (paths only support) or newer SkipAuthRoutes option
287// (method=path support)
287// (method=path support)
288func buildRoutesAllowlist(opts *options.Options) ([]*allowedRoute, error) {
288func buildRoutesAllowlist(opts *options.Options) ([]*allowedRoute, error) {
289− var routes []*allowedRoute
289+ routes := make([]*allowedRoute, 0, len(opts.SkipAuthRegex)+len(opts.SkipAuthRoutes))
290
290
291 for _, path := range opts.SkipAuthRegex {
291 for _, path := range opts.SkipAuthRegex {
292 compiledRegex, err := regexp.Compile(path)
292 compiledRegex, err := regexp.Compile(path)
oauthproxy_test.go+253−20
@@ -1482,28 +1482,28 @@ func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
1482}
1482}
1483
1483
1484func TestAuthSkippedForPreflightRequests(t *testing.T) {
1484func TestAuthSkippedForPreflightRequests(t *testing.T) {
1485− upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1485+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1486 w.WriteHeader(200)
1486 w.WriteHeader(200)
1487 _, err := w.Write([]byte("response"))
1487 _, err := w.Write([]byte("response"))
1488 if err != nil {
1488 if err != nil {
1489 t.Fatal(err)
1489 t.Fatal(err)
1490 }
1490 }
1491 }))
1491 }))
1492− t.Cleanup(upstream.Close)
1492+ t.Cleanup(upstreamServer.Close)
1493
1493
1494 opts := baseTestOptions()
1494 opts := baseTestOptions()
1495 opts.UpstreamServers = options.Upstreams{
1495 opts.UpstreamServers = options.Upstreams{
1496 {
1496 {
1497− ID: upstream.URL,
1497+ ID: upstreamServer.URL,
1498 Path: "/",
1498 Path: "/",
1499− URI: upstream.URL,
1499+ URI: upstreamServer.URL,
1500 },
1500 },
1501 }
1501 }
1502 opts.SkipAuthPreflight = true
1502 opts.SkipAuthPreflight = true
1503 err := validation.Validate(opts)
1503 err := validation.Validate(opts)
1504 assert.NoError(t, err)
1504 assert.NoError(t, err)
1505
1505
1506− upstreamURL, _ := url.Parse(upstream.URL)
1506+ upstreamURL, _ := url.Parse(upstreamServer.URL)
1507 opts.SetProvider(NewTestProvider(upstreamURL, ""))
1507 opts.SetProvider(NewTestProvider(upstreamURL, ""))
1508
1508
1509 proxy, err := NewOAuthProxy(opts, func(string) bool { return false })
1509 proxy, err := NewOAuthProxy(opts, func(string) bool { return false })
@@ -1561,17 +1561,17 @@ func NewSignatureTest() (*SignatureTest, error) {
1561 opts.EmailDomains = []string{"acm.org"}
1561 opts.EmailDomains = []string{"acm.org"}
1562
1562
1563 authenticator := &SignatureAuthenticator{}
1563 authenticator := &SignatureAuthenticator{}
1564− upstream := httptest.NewServer(
1564+ upstreamServer := httptest.NewServer(
1565 http.HandlerFunc(authenticator.Authenticate))
1565 http.HandlerFunc(authenticator.Authenticate))
1566− upstreamURL, err := url.Parse(upstream.URL)
1566+ upstreamURL, err := url.Parse(upstreamServer.URL)
1567 if err != nil {
1567 if err != nil {
1568 return nil, err
1568 return nil, err
1569 }
1569 }
1570 opts.UpstreamServers = options.Upstreams{
1570 opts.UpstreamServers = options.Upstreams{
1571 {
1571 {
1572− ID: upstream.URL,
1572+ ID: upstreamServer.URL,
1573 Path: "/",
1573 Path: "/",
1574− URI: upstream.URL,
1574+ URI: upstreamServer.URL,
1575 },
1575 },
1576 }
1576 }
1577
1577
@@ -1590,7 +1590,7 @@ func NewSignatureTest() (*SignatureTest, error) {
1590
1590
1591 return &SignatureTest{
1591 return &SignatureTest{
1592 opts,
1592 opts,
1593− upstream,
1593+ upstreamServer,
1594 upstreamURL.Host,
1594 upstreamURL.Host,
1595 provider,
1595 provider,
1596 make(http.Header),
1596 make(http.Header),
@@ -1974,20 +1974,20 @@ func Test_prepareNoCache(t *testing.T) {
1974}
1974}
1975
1975
1976func Test_noCacheHeaders(t *testing.T) {
1976func Test_noCacheHeaders(t *testing.T) {
1977− upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1977+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1978 _, err := w.Write([]byte("upstream"))
1978 _, err := w.Write([]byte("upstream"))
1979 if err != nil {
1979 if err != nil {
1980 t.Error(err)
1980 t.Error(err)
1981 }
1981 }
1982 }))
1982 }))
1983− t.Cleanup(upstream.Close)
1983+ t.Cleanup(upstreamServer.Close)
1984
1984
1985 opts := baseTestOptions()
1985 opts := baseTestOptions()
1986 opts.UpstreamServers = options.Upstreams{
1986 opts.UpstreamServers = options.Upstreams{
1987 {
1987 {
1988− ID: upstream.URL,
1988+ ID: upstreamServer.URL,
1989 Path: "/",
1989 Path: "/",
1990− URI: upstream.URL,
1990+ URI: upstreamServer.URL,
1991 },
1991 },
1992 }
1992 }
1993 opts.SkipAuthRegex = []string{".*"}
1993 opts.SkipAuthRegex = []string{".*"}
@@ -2224,7 +2224,8 @@ func TestTrustedIPs(t *testing.T) {
2224 opts.TrustedIPs = tt.trustedIPs
2224 opts.TrustedIPs = tt.trustedIPs
2225 opts.ReverseProxy = tt.reverseProxy
2225 opts.ReverseProxy = tt.reverseProxy
2226 opts.RealClientIPHeader = tt.realClientIPHeader
2226 opts.RealClientIPHeader = tt.realClientIPHeader
2227− validation.Validate(opts)
2227+ err := validation.Validate(opts)
2228+ assert.NoError(t, err)
2228
2229
2229 proxy, err := NewOAuthProxy(opts, func(string) bool { return true })
2230 proxy, err := NewOAuthProxy(opts, func(string) bool { return true })
2230 assert.NoError(t, err)
2231 assert.NoError(t, err)
@@ -2240,6 +2241,237 @@ func TestTrustedIPs(t *testing.T) {
2240 }
2241 }
2241}
2242}
2242
2243
2244+func Test_buildRoutesAllowlist(t *testing.T) {
2245+ testCases := []struct {
2246+ name string
2247+ skipAuthRegex []string
2248+ skipAuthRoutes []string
2249+ expectedMethods []string
2250+ expectedRegexes []string
2251+ shouldError bool
2252+ }{
2253+ {
2254+ name: "No skip auth configured",
2255+ skipAuthRegex: []string{},
2256+ skipAuthRoutes: []string{},
2257+ expectedMethods: []string{},
2258+ expectedRegexes: []string{},
2259+ shouldError: false,
2260+ },
2261+ {
2262+ name: "Only skipAuthRegex configured",
2263+ skipAuthRegex: []string{
2264+ "^/foo/bar",
2265+ "^/baz/[0-9]+/thing",
2266+ },
2267+ skipAuthRoutes: []string{},
2268+ expectedMethods: []string{
2269+ "",
2270+ "",
2271+ },
2272+ expectedRegexes: []string{
2273+ "^/foo/bar",
2274+ "^/baz/[0-9]+/thing",
2275+ },
2276+ shouldError: false,
2277+ },
2278+ {
2279+ name: "Only skipAuthRoutes configured",
2280+ skipAuthRegex: []string{},
2281+ skipAuthRoutes: []string{
2282+ "GET=^/foo/bar",
2283+ "POST=^/baz/[0-9]+/thing",
2284+ "^/all/methods$",
2285+ "WEIRD=^/methods/are/allowed",
2286+ "PATCH=/second/equals?are=handled&just=fine",
2287+ },
2288+ expectedMethods: []string{
2289+ "GET",
2290+ "POST",
2291+ "",
2292+ "WEIRD",
2293+ "PATCH",
2294+ },
2295+ expectedRegexes: []string{
2296+ "^/foo/bar",
2297+ "^/baz/[0-9]+/thing",
2298+ "^/all/methods$",
2299+ "^/methods/are/allowed",
2300+ "/second/equals?are=handled&just=fine",
2301+ },
2302+ shouldError: false,
2303+ },
2304+ {
2305+ name: "Both skipAuthRegexes and skipAuthRoutes configured",
2306+ skipAuthRegex: []string{
2307+ "^/foo/bar/regex",
2308+ "^/baz/[0-9]+/thing/regex",
2309+ },
2310+ skipAuthRoutes: []string{
2311+ "GET=^/foo/bar",
2312+ "POST=^/baz/[0-9]+/thing",
2313+ "^/all/methods$",
2314+ },
2315+ expectedMethods: []string{
2316+ "",
2317+ "",
2318+ "GET",
2319+ "POST",
2320+ "",
2321+ },
2322+ expectedRegexes: []string{
2323+ "^/foo/bar/regex",
2324+ "^/baz/[0-9]+/thing/regex",
2325+ "^/foo/bar",
2326+ "^/baz/[0-9]+/thing",
2327+ "^/all/methods$",
2328+ },
2329+ shouldError: false,
2330+ },
2331+ {
2332+ name: "Invalid skipAuthRegex entry",
2333+ skipAuthRegex: []string{
2334+ "^/foo/bar",
2335+ "^/baz/[0-9]+/thing",
2336+ "(bad[regex",
2337+ },
2338+ skipAuthRoutes: []string{},
2339+ expectedMethods: []string{},
2340+ expectedRegexes: []string{},
2341+ shouldError: true,
2342+ },
2343+ {
2344+ name: "Invalid skipAuthRoutes entry",
2345+ skipAuthRegex: []string{},
2346+ skipAuthRoutes: []string{
2347+ "GET=^/foo/bar",
2348+ "POST=^/baz/[0-9]+/thing",
2349+ "^/all/methods$",
2350+ "PUT=(bad[regex",
2351+ },
2352+ expectedMethods: []string{},
2353+ expectedRegexes: []string{},
2354+ shouldError: true,
2355+ },
2356+ }
2357+
2358+ for _, tc := range testCases {
2359+ t.Run(tc.name, func(t *testing.T) {
2360+ opts := &options.Options{
2361+ SkipAuthRegex: tc.skipAuthRegex,
2362+ SkipAuthRoutes: tc.skipAuthRoutes,
2363+ }
2364+ routes, err := buildRoutesAllowlist(opts)
2365+ if tc.shouldError {
2366+ assert.Error(t, err)
2367+ return
2368+ } else {
2369+ assert.NoError(t, err)
2370+ }
2371+ for i, route := range routes {
2372+ assert.Greater(t, len(tc.expectedMethods), i)
2373+ assert.Equal(t, route.method, tc.expectedMethods[i])
2374+ assert.Greater(t, len(tc.expectedRegexes), i)
2375+ assert.Equal(t, route.pathRegex.String(), tc.expectedRegexes[i])
2376+ }
2377+ })
2378+ }
2379+}
2380+
2381+func TestAllowedRequest(t *testing.T) {
2382+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2383+ w.WriteHeader(200)
2384+ _, err := w.Write([]byte("Allowed Request"))
2385+ if err != nil {
2386+ t.Fatal(err)
2387+ }
2388+ }))
2389+ t.Cleanup(upstreamServer.Close)
2390+
2391+ opts := baseTestOptions()
2392+ opts.UpstreamServers = options.Upstreams{
2393+ {
2394+ ID: upstreamServer.URL,
2395+ Path: "/",
2396+ URI: upstreamServer.URL,
2397+ },
2398+ }
2399+ opts.SkipAuthRegex = []string{
2400+ "^/skip/auth/regex$",
2401+ }
2402+ opts.SkipAuthRoutes = []string{
2403+ "GET=^/skip/auth/routes/get",
2404+ }
2405+ err := validation.Validate(opts)
2406+ assert.NoError(t, err)
2407+ proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
2408+ if err != nil {
2409+ t.Fatal(err)
2410+ }
2411+
2412+ testCases := []struct {
2413+ name string
2414+ method string
2415+ url string
2416+ allowed bool
2417+ }{
2418+ {
2419+ name: "Regex GET allowed",
2420+ method: "GET",
2421+ url: "/skip/auth/regex",
2422+ allowed: true,
2423+ },
2424+ {
2425+ name: "Regex POST allowed ",
2426+ method: "POST",
2427+ url: "/skip/auth/regex",
2428+ allowed: true,
2429+ },
2430+ {
2431+ name: "Regex denied",
2432+ method: "GET",
2433+ url: "/wrong/denied",
2434+ allowed: false,
2435+ },
2436+ {
2437+ name: "Route allowed",
2438+ method: "GET",
2439+ url: "/skip/auth/routes/get",
2440+ allowed: true,
2441+ },
2442+ {
2443+ name: "Route denied with wrong method",
2444+ method: "PATCH",
2445+ url: "/skip/auth/routes/get",
2446+ allowed: false,
2447+ },
2448+ {
2449+ name: "Route denied with wrong path",
2450+ method: "GET",
2451+ url: "/skip/auth/routes/wrong/path",
2452+ allowed: false,
2453+ },
2454+ }
2455+
2456+ for _, tc := range testCases {
2457+ t.Run(tc.name, func(t *testing.T) {
2458+ req, err := http.NewRequest(tc.method, tc.url, nil)
2459+ assert.NoError(t, err)
2460+ assert.Equal(t, tc.allowed, proxy.isAllowedRoute(req))
2461+
2462+ rw := httptest.NewRecorder()
2463+ proxy.ServeHTTP(rw, req)
2464+
2465+ if tc.allowed {
2466+ assert.Equal(t, 200, rw.Code)
2467+ assert.Equal(t, "Allowed Request", rw.Body.String())
2468+ } else {
2469+ assert.Equal(t, 403, rw.Code)
2470+ }
2471+ })
2472+ }
2473+}
2474+
2243func TestProxyAllowedGroups(t *testing.T) {
2475func TestProxyAllowedGroups(t *testing.T) {
2244 tests := []struct {
2476 tests := []struct {
2245 name string
2477 name string
@@ -2265,18 +2497,18 @@ func TestProxyAllowedGroups(t *testing.T) {
2265 CreatedAt: &created,
2497 CreatedAt: &created,
2266 }
2498 }
2267
2499
2268− upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2500+ upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2269 w.WriteHeader(200)
2501 w.WriteHeader(200)
2270 }))
2502 }))
2271− t.Cleanup(upstream.Close)
2503+ t.Cleanup(upstreamServer.Close)
2272
2504
2273 test, err := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
2505 test, err := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
2274 opts.AllowedGroups = tt.allowedGroups
2506 opts.AllowedGroups = tt.allowedGroups
2275 opts.UpstreamServers = options.Upstreams{
2507 opts.UpstreamServers = options.Upstreams{
2276 {
2508 {
2277− ID: upstream.URL,
2509+ ID: upstreamServer.URL,
2278 Path: "/",
2510 Path: "/",
2279− URI: upstream.URL,
2511+ URI: upstreamServer.URL,
2280 },
2512 },
2281 }
2513 }
2282 })
2514 })
@@ -2287,7 +2519,8 @@ func TestProxyAllowedGroups(t *testing.T) {
2287 test.req, _ = http.NewRequest("GET", "/", nil)
2519 test.req, _ = http.NewRequest("GET", "/", nil)
2288
2520
2289 test.req.Header.Add("accept", applicationJSON)
2521 test.req.Header.Add("accept", applicationJSON)
2290− test.SaveSession(session)
2522+ err = test.SaveSession(session)
2523+ assert.NoError(t, err)
2291 test.proxy.ServeHTTP(test.rw, test.req)
2524 test.proxy.ServeHTTP(test.rw, test.req)
2292
2525
2293 if tt.expectUnauthorized {
2526 if tt.expectUnauthorized {