From 49b6aabb02edba5fc41b0cea106da9629ad1d9d9 Mon Sep 17 00:00:00 2001 From: Jens L Date: Thu, 22 Sep 2022 10:10:29 +0200 Subject: [PATCH] outposts/proxy: fix redirect path when external host is a subdirectory (#3628) fix redirect path when external host is a subdirectory Signed-off-by: Jens Langhammer Signed-off-by: Jens Langhammer --- .../proxyv2/application/mode_proxy_test.go | 35 +++++++++++++++++++ internal/outpost/proxyv2/application/test.go | 2 ++ internal/outpost/proxyv2/application/utils.go | 13 ++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/internal/outpost/proxyv2/application/mode_proxy_test.go b/internal/outpost/proxyv2/application/mode_proxy_test.go index a4951f4c2..4ea037da2 100644 --- a/internal/outpost/proxyv2/application/mode_proxy_test.go +++ b/internal/outpost/proxyv2/application/mode_proxy_test.go @@ -25,6 +25,41 @@ func TestProxy_ModifyRequest(t *testing.T) { assert.Equal(t, "frontend", req.Host) } +func TestProxy_Redirect(t *testing.T) { + a := newTestApplication() + _ = a.configureProxy() + req, _ := http.NewRequest("GET", "https://ext.t.goauthentik.io/foo", nil) + rr := httptest.NewRecorder() + + a.mux.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusFound, rr.Code) + loc, _ := rr.Result().Location() + assert.Equal( + t, + "https://ext.t.goauthentik.io/outpost.goauthentik.io/start?rd=https%3A%2F%2Fext.t.goauthentik.io%2Ffoo", + loc.String(), + ) +} + +func TestProxy_Redirect_Subdirectory(t *testing.T) { + a := newTestApplication() + a.proxyConfig.ExternalHost = a.proxyConfig.ExternalHost + "/subdir" + _ = a.configureProxy() + req, _ := http.NewRequest("GET", "https://ext.t.goauthentik.io/foo", nil) + rr := httptest.NewRecorder() + + a.mux.ServeHTTP(rr, req) + + assert.Equal(t, http.StatusFound, rr.Code) + loc, _ := rr.Result().Location() + assert.Equal( + t, + "https://ext.t.goauthentik.io/subdir/outpost.goauthentik.io/start?rd=https%3A%2F%2Fext.t.goauthentik.io%2Ffoo", + loc.String(), + ) +} + func TestProxy_ModifyRequest_Claims(t *testing.T) { a := newTestApplication() req, _ := http.NewRequest("GET", "http://frontend/foo", nil) diff --git a/internal/outpost/proxyv2/application/test.go b/internal/outpost/proxyv2/application/test.go index 3bb93591c..e41eb8078 100644 --- a/internal/outpost/proxyv2/application/test.go +++ b/internal/outpost/proxyv2/application/test.go @@ -16,6 +16,8 @@ func newTestApplication() *Application { ClientSecret: api.PtrString(ak.TestSecret()), CookieSecret: api.PtrString(ak.TestSecret()), ExternalHost: "https://ext.t.goauthentik.io", + InternalHost: api.PtrString("http://backend"), + InternalHostSslValidation: api.PtrBool(true), CookieDomain: api.PtrString(""), Mode: *api.NewNullableProxyMode(api.PROXYMODE_FORWARD_SINGLE.Ptr()), SkipPathRegex: api.PtrString("/skip.*"), diff --git a/internal/outpost/proxyv2/application/utils.go b/internal/outpost/proxyv2/application/utils.go index babda4e8c..67405c2b3 100644 --- a/internal/outpost/proxyv2/application/utils.go +++ b/internal/outpost/proxyv2/application/utils.go @@ -12,6 +12,15 @@ import ( "goauthentik.io/internal/outpost/proxyv2/constants" ) +func urlPathSet(originalUrl string, newPath string) string { + u, err := url.Parse(originalUrl) + if err != nil { + return originalUrl + } + u.Path = newPath + return u.String() +} + func urlJoin(originalUrl string, newPath string) string { u, err := url.Parse(originalUrl) if err != nil { @@ -26,7 +35,9 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { if err != nil { a.log.WithError(err).Warning("failed to decode session") } - redirectUrl := urlJoin(a.proxyConfig.ExternalHost, r.URL.Path) + + redirectUrl := urlPathSet(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