2017-09-18 18:48:07 +03:00
package auth
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
2018-01-10 19:48:04 +03:00
"github.com/containous/traefik/middlewares/tracing"
2017-09-18 18:48:07 +03:00
"github.com/containous/traefik/testhelpers"
"github.com/containous/traefik/types"
"github.com/stretchr/testify/assert"
2018-04-23 16:28:04 +03:00
"github.com/stretchr/testify/require"
2017-09-18 18:48:07 +03:00
"github.com/urfave/negroni"
)
func TestForwardAuthFail ( t * testing . T ) {
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
http . Error ( w , "Forbidden" , http . StatusForbidden )
} ) )
defer server . Close ( )
middleware , err := NewAuthenticator ( & types . Auth {
Forward : & types . Forward {
Address : server . URL ,
} ,
2018-01-10 19:48:04 +03:00
} , & tracing . Tracing { } )
2017-09-18 18:48:07 +03:00
assert . NoError ( t , err , "there should be no error" )
handler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
fmt . Fprintln ( w , "traefik" )
} )
n := negroni . New ( middleware )
n . UseHandler ( handler )
ts := httptest . NewServer ( n )
defer ts . Close ( )
client := & http . Client { }
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
res , err := client . Do ( req )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , http . StatusForbidden , res . StatusCode , "they should be equal" )
body , err := ioutil . ReadAll ( res . Body )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , "Forbidden\n" , string ( body ) , "they should be equal" )
}
func TestForwardAuthSuccess ( t * testing . T ) {
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
fmt . Fprintln ( w , "Success" )
} ) )
defer server . Close ( )
middleware , err := NewAuthenticator ( & types . Auth {
Forward : & types . Forward {
Address : server . URL ,
} ,
2018-01-10 19:48:04 +03:00
} , & tracing . Tracing { } )
2017-09-18 18:48:07 +03:00
assert . NoError ( t , err , "there should be no error" )
handler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
fmt . Fprintln ( w , "traefik" )
} )
n := negroni . New ( middleware )
n . UseHandler ( handler )
ts := httptest . NewServer ( n )
defer ts . Close ( )
client := & http . Client { }
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
res , err := client . Do ( req )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , http . StatusOK , res . StatusCode , "they should be equal" )
body , err := ioutil . ReadAll ( res . Body )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , "traefik\n" , string ( body ) , "they should be equal" )
}
2017-11-02 13:06:03 +03:00
func TestForwardAuthRedirect ( t * testing . T ) {
authTs := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
http . Redirect ( w , r , "http://example.com/redirect-test" , http . StatusFound )
} ) )
defer authTs . Close ( )
authMiddleware , err := NewAuthenticator ( & types . Auth {
Forward : & types . Forward {
Address : authTs . URL ,
} ,
2018-01-10 19:48:04 +03:00
} , & tracing . Tracing { } )
2017-11-02 13:06:03 +03:00
assert . NoError ( t , err , "there should be no error" )
handler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
fmt . Fprintln ( w , "traefik" )
} )
n := negroni . New ( authMiddleware )
n . UseHandler ( handler )
ts := httptest . NewServer ( n )
defer ts . Close ( )
client := & http . Client {
CheckRedirect : func ( r * http . Request , via [ ] * http . Request ) error {
return http . ErrUseLastResponse
} ,
}
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
res , err := client . Do ( req )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , http . StatusFound , res . StatusCode , "they should be equal" )
location , err := res . Location ( )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , "http://example.com/redirect-test" , location . String ( ) , "they should be equal" )
body , err := ioutil . ReadAll ( res . Body )
assert . NoError ( t , err , "there should be no error" )
assert . NotEmpty ( t , string ( body ) , "there should be something in the body" )
}
2018-04-23 16:28:04 +03:00
func TestForwardAuthFailResponseHeaders ( t * testing . T ) {
2017-11-02 13:06:03 +03:00
authTs := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
cookie := & http . Cookie { Name : "example" , Value : "testing" , Path : "/" }
http . SetCookie ( w , cookie )
2018-04-23 16:28:04 +03:00
w . Header ( ) . Add ( "X-Foo" , "bar" )
2017-11-02 13:06:03 +03:00
http . Error ( w , "Forbidden" , http . StatusForbidden )
} ) )
defer authTs . Close ( )
authMiddleware , err := NewAuthenticator ( & types . Auth {
Forward : & types . Forward {
Address : authTs . URL ,
} ,
2018-01-10 19:48:04 +03:00
} , & tracing . Tracing { } )
2017-11-02 13:06:03 +03:00
assert . NoError ( t , err , "there should be no error" )
handler := http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
fmt . Fprintln ( w , "traefik" )
} )
n := negroni . New ( authMiddleware )
n . UseHandler ( handler )
ts := httptest . NewServer ( n )
defer ts . Close ( )
req := testhelpers . MustNewRequest ( http . MethodGet , ts . URL , nil )
2018-04-23 16:28:04 +03:00
client := & http . Client { }
2017-11-02 13:06:03 +03:00
res , err := client . Do ( req )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , http . StatusForbidden , res . StatusCode , "they should be equal" )
2018-04-23 16:28:04 +03:00
require . Len ( t , res . Cookies ( ) , 1 )
2017-11-02 13:06:03 +03:00
for _ , cookie := range res . Cookies ( ) {
assert . Equal ( t , "testing" , cookie . Value , "they should be equal" )
}
2018-04-23 16:28:04 +03:00
expectedHeaders := http . Header {
"Content-Length" : [ ] string { "10" } ,
"Content-Type" : [ ] string { "text/plain; charset=utf-8" } ,
"X-Foo" : [ ] string { "bar" } ,
"Set-Cookie" : [ ] string { "example=testing; Path=/" } ,
"X-Content-Type-Options" : [ ] string { "nosniff" } ,
}
assert . Len ( t , res . Header , 6 )
for key , value := range expectedHeaders {
assert . Equal ( t , value , res . Header [ key ] )
}
2017-11-02 13:06:03 +03:00
body , err := ioutil . ReadAll ( res . Body )
assert . NoError ( t , err , "there should be no error" )
assert . Equal ( t , "Forbidden\n" , string ( body ) , "they should be equal" )
}
2017-09-18 18:48:07 +03:00
func Test_writeHeader ( t * testing . T ) {
testCases := [ ] struct {
name string
headers map [ string ] string
trustForwardHeader bool
emptyHost bool
expectedHeaders map [ string ] string
} {
{
name : "trust Forward Header" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
trustForwardHeader : true ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
} ,
{
name : "not trust Forward Header" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
trustForwardHeader : false ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "foo.bar" ,
} ,
} ,
{
name : "trust Forward Header with empty Host" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
trustForwardHeader : true ,
emptyHost : true ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
} ,
{
name : "not trust Forward Header with empty Host" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
} ,
trustForwardHeader : false ,
emptyHost : true ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "" ,
} ,
} ,
2017-12-10 02:58:21 +03:00
{
name : "trust Forward Header with forwarded URI" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
"X-Forwarded-Uri" : "/forward?q=1" ,
} ,
trustForwardHeader : true ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
"X-Forwarded-Uri" : "/forward?q=1" ,
} ,
} ,
{
name : "not trust Forward Header with forward requested URI" ,
headers : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "fii.bir" ,
"X-Forwarded-Uri" : "/forward?q=1" ,
} ,
trustForwardHeader : false ,
expectedHeaders : map [ string ] string {
"Accept" : "application/json" ,
"X-Forwarded-Host" : "foo.bar" ,
"X-Forwarded-Uri" : "/path?q=1" ,
} ,
2018-06-13 16:14:03 +03:00
} , {
name : "trust Forward Header with forwarded request Method" ,
headers : map [ string ] string {
"X-Forwarded-Method" : "OPTIONS" ,
} ,
trustForwardHeader : true ,
expectedHeaders : map [ string ] string {
"X-Forwarded-Method" : "OPTIONS" ,
} ,
} ,
{
name : "not trust Forward Header with forward request Method" ,
headers : map [ string ] string {
"X-Forwarded-Method" : "OPTIONS" ,
} ,
trustForwardHeader : false ,
expectedHeaders : map [ string ] string {
"X-Forwarded-Method" : "GET" ,
} ,
2017-12-10 02:58:21 +03:00
} ,
2017-09-18 18:48:07 +03:00
}
for _ , test := range testCases {
t . Run ( test . name , func ( t * testing . T ) {
2017-12-10 02:58:21 +03:00
req := testhelpers . MustNewRequest ( http . MethodGet , "http://foo.bar/path?q=1" , nil )
2017-09-18 18:48:07 +03:00
for key , value := range test . headers {
req . Header . Set ( key , value )
}
if test . emptyHost {
req . Host = ""
}
2017-12-10 02:58:21 +03:00
forwardReq := testhelpers . MustNewRequest ( http . MethodGet , "http://foo.bar/path?q=1" , nil )
2017-09-18 18:48:07 +03:00
writeHeader ( req , forwardReq , test . trustForwardHeader )
for key , value := range test . expectedHeaders {
assert . Equal ( t , value , forwardReq . Header . Get ( key ) )
}
} )
}
}