outposts/proxy: fix potential empty redirect, add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> #2141
This commit is contained in:
parent
47777529ac
commit
1c2b452406
9
.github/workflows/ci-outpost.yml
vendored
9
.github/workflows/ci-outpost.yml
vendored
|
@ -45,15 +45,6 @@ jobs:
|
||||||
- name: Go unittests
|
- name: Go unittests
|
||||||
run: |
|
run: |
|
||||||
go test -timeout 0 -v -race -coverprofile=coverage.out -covermode=atomic -cover ./... | go-junit-report > junit.xml
|
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:
|
ci-outpost-mark:
|
||||||
needs:
|
needs:
|
||||||
- lint-golint
|
- lint-golint
|
||||||
|
|
|
@ -71,7 +71,7 @@ func TestForwardHandleNginx_Single_Claims(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rr = httptest.NewRecorder()
|
rr = httptest.NewRecorder()
|
||||||
a.forwardHandleTraefik(rr, req)
|
a.forwardHandleNginx(rr, req)
|
||||||
|
|
||||||
h := rr.Result().Header
|
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 {
|
func (a *Application) proxyModifyResponse(res *http.Response) error {
|
||||||
|
res.Header.Set("X-Powered-By", "authentik_proxy2")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,21 +26,14 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
a.log.WithError(err).Warning("failed to decode session")
|
a.log.WithError(err).Warning("failed to decode session")
|
||||||
}
|
}
|
||||||
redirectUrl := r.URL.String()
|
redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path)
|
||||||
// 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
|
|
||||||
}
|
|
||||||
if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN {
|
if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN {
|
||||||
dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".")
|
dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".")
|
||||||
// In forward_domain we only check that the current URL's host
|
// In forward_domain we only check that the current URL's host
|
||||||
// ends with the cookie domain (remove the leading period if set)
|
// ends with the cookie domain (remove the leading period if set)
|
||||||
if !strings.HasSuffix(r.URL.Hostname(), dom) {
|
if !strings.HasSuffix(r.URL.Hostname(), dom) {
|
||||||
a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found")
|
a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found")
|
||||||
redirectUrl = ""
|
redirectUrl = a.proxyConfig.ExternalHost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Values[constants.SessionRedirect] = redirectUrl
|
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 a new issue