outposts/proxy: fix potential empty redirect, add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> #2141
This commit is contained in:
		
							
								
								
									
										9
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							| @ -45,15 +45,6 @@ jobs: | ||||
|       - name: Go unittests | ||||
|         run: | | ||||
|           go test -timeout 0 -v -race -coverprofile=coverage.out -covermode=atomic -cover ./... | go-junit-report > junit.xml | ||||
|       - uses: testspace-com/setup-testspace@v1 | ||||
|         with: | ||||
|           domain: ${{github.repository_owner}} | ||||
|       - name: run testspace | ||||
|         if: ${{ always() }} | ||||
|         run: | | ||||
|           gocov convert coverage.out | gocov-xml > coverage.xml | ||||
|           testspace [outpost]junit.xml --link=codecov | ||||
|           testspace [outpost]coverage.xml --link=codecov | ||||
|   ci-outpost-mark: | ||||
|     needs: | ||||
|       - lint-golint | ||||
|  | ||||
| @ -71,7 +71,7 @@ func TestForwardHandleNginx_Single_Claims(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	rr = httptest.NewRecorder() | ||||
| 	a.forwardHandleTraefik(rr, req) | ||||
| 	a.forwardHandleNginx(rr, req) | ||||
|  | ||||
| 	h := rr.Result().Header | ||||
|  | ||||
|  | ||||
| @ -79,5 +79,6 @@ func (a *Application) proxyModifyRequest(u *url.URL) func(req *http.Request) { | ||||
| } | ||||
|  | ||||
| func (a *Application) proxyModifyResponse(res *http.Response) error { | ||||
| 	res.Header.Set("X-Powered-By", "authentik_proxy2") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -26,21 +26,14 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { | ||||
| 	if err == nil { | ||||
| 		a.log.WithError(err).Warning("failed to decode session") | ||||
| 	} | ||||
| 	redirectUrl := r.URL.String() | ||||
| 	// simple way to copy the URL | ||||
| 	u, _ := url.Parse(redirectUrl) | ||||
| 	// In proxy and forward_single mode we only have one URL that we route on | ||||
| 	// if we somehow got here without that URL, make sure we're at least redirected back to it | ||||
| 	if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE { | ||||
| 		u.Host = a.proxyConfig.ExternalHost | ||||
| 	} | ||||
| 	redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path) | ||||
| 	if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN { | ||||
| 		dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".") | ||||
| 		// In forward_domain we only check that the current URL's host | ||||
| 		// ends with the cookie domain (remove the leading period if set) | ||||
| 		if !strings.HasSuffix(r.URL.Hostname(), dom) { | ||||
| 			a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found") | ||||
| 			redirectUrl = "" | ||||
| 			redirectUrl = a.proxyConfig.ExternalHost | ||||
| 		} | ||||
| 	} | ||||
| 	s.Values[constants.SessionRedirect] = redirectUrl | ||||
|  | ||||
							
								
								
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								internal/outpost/proxyv2/application/utils_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"goauthentik.io/api" | ||||
| 	"goauthentik.io/internal/outpost/proxyv2/constants" | ||||
| ) | ||||
|  | ||||
| func TestRedirectToStart_Proxy(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.Mode = api.PROXYMODE_PROXY.Ptr() | ||||
| 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||
| 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.redirectToStart(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusFound, rr.Code) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
|  | ||||
| func TestRedirectToStart_Forward(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_SINGLE.Ptr() | ||||
| 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||
| 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.redirectToStart(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusFound, rr.Code) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
|  | ||||
| func TestRedirectToStart_Forward_Domain_Invalid(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||
| 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||
| 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||
| 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.redirectToStart(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusFound, rr.Code) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||
| 	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
|  | ||||
| func TestRedirectToStart_Forward_Domain(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.CookieDomain = api.PtrString("goauthentik.io") | ||||
| 	a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr() | ||||
| 	a.proxyConfig.ExternalHost = "https://test.goauthentik.io" | ||||
| 	req, _ := http.NewRequest("GET", "/foo/bar/baz", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.redirectToStart(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusFound, rr.Code) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String()) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SeesionName) | ||||
| 	assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer