| package main |
| |
| import ( |
| "net/http" |
| "net/http/httptest" |
| "net/url" |
| "testing" |
| |
| "github.com/stretchr/testify/require" |
| "go.skia.org/infra/go/testutils/unittest" |
| "go.skia.org/infra/kube/go/auth-proxy/auth/mocks" |
| ) |
| |
| const email = "nobody@example.org" |
| |
| func setupForTest(t *testing.T, cb http.HandlerFunc) (*url.URL, *bool, *httptest.ResponseRecorder, *http.Request) { |
| *allowPost = false |
| *passive = false |
| called := false |
| ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| cb(w, r) |
| called = true |
| })) |
| t.Cleanup(func() { |
| ts.Close() |
| }) |
| u, err := url.Parse(ts.URL) |
| require.NoError(t, err) |
| |
| w := httptest.NewRecorder() |
| r := httptest.NewRequest("POST", ts.URL, nil) |
| return u, &called, w, r |
| } |
| |
| func TestProxyServeHTTP_AllowPostAndNotAuthenticated_WebAuthHeaderValueIsEmptyString(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) { |
| // Note that if the header webAuthHeaderName hadn't been set then the value would be nil. |
| require.Equal(t, []string{""}, r.Header.Values(webAuthHeaderName)) |
| require.Equal(t, []string(nil), r.Header.Values("X-SOME-UNSET-HEADER")) |
| }) |
| *allowPost = true |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return("") |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.True(t, *called) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsLoggedIn_HeaderWithUserEmailIsIncludedInRequest(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) { |
| require.Equal(t, []string{email}, r.Header.Values(webAuthHeaderName)) |
| }) |
| |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return(email) |
| authMock.On("IsViewer", r).Return(true) |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.True(t, *called) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsNotLoggedIn_HeaderWithUserEmailIsStrippedFromRequest(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) {}) |
| r.Header.Add(webAuthHeaderName, email) // Try to spoof the header. |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return("") |
| authMock.On("LoginURL", w, r).Return("http://example.org/login") |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.False(t, *called) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsLoggedInButNotAViewer_ReturnsStatusForbidden(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) {}) |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return(email) |
| authMock.On("IsViewer", r).Return(false) |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.False(t, *called) |
| require.Equal(t, http.StatusForbidden, w.Result().StatusCode) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsLoggedIn_HeaderWithUserEmailIsIncludedInRequestAndSpoofedEmailIsRemoved(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) { |
| require.Equal(t, []string{email}, r.Header.Values(webAuthHeaderName)) |
| }) |
| r.Header.Add(webAuthHeaderName, "haxor@example.org") // Try to spoof the header. |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return(email) |
| authMock.On("IsViewer", r).Return(true) |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.True(t, *called) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsNotLoggedInAndPassiveFlagIsSet_RequestIsPassedAlongWithoutEmailHeader(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) { |
| require.Equal(t, []string{""}, r.Header.Values(webAuthHeaderName)) |
| }) |
| |
| *passive = true |
| r.Header.Add(webAuthHeaderName, "haxor@example.org") // Try to spoof the header. |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return("") |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.True(t, *called) |
| authMock.AssertExpectations(t) |
| } |
| |
| func TestProxyServeHTTP_UserIsLoggedInAndPassiveFlagIsSet_RequestIsPassedAlongWithEmailHeader(t *testing.T) { |
| unittest.SmallTest(t) |
| |
| u, called, w, r := setupForTest(t, func(w http.ResponseWriter, r *http.Request) { |
| require.Equal(t, []string{email}, r.Header.Values(webAuthHeaderName)) |
| }) |
| |
| *passive = true |
| r.Header.Add(webAuthHeaderName, "haxor@example.org") // Try to spoof the header. |
| authMock := &mocks.Auth{} |
| authMock.On("LoggedInAs", r).Return(email) |
| |
| proxy := newProxy(u, authMock) |
| |
| proxy.ServeHTTP(w, r) |
| require.True(t, *called) |
| authMock.AssertExpectations(t) |
| } |