mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-31 23:41:09 +02:00
authorize: fix x-forwarded-uri
This commit is contained in:
parent
24a9d627cd
commit
36b819af82
3 changed files with 70 additions and 22 deletions
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
"github.com/pomerium/pomerium/authorize/evaluator"
|
||||
"github.com/pomerium/pomerium/config"
|
||||
"github.com/pomerium/pomerium/internal/httputil"
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/sessions"
|
||||
"github.com/pomerium/pomerium/internal/telemetry/trace"
|
||||
|
@ -44,7 +43,7 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v3.CheckRe
|
|||
isForwardAuth := a.isForwardAuth(in)
|
||||
if isForwardAuth {
|
||||
// update the incoming http request's uri to match the forwarded URI
|
||||
fwdAuthURI := getForwardAuthURL(hreq)
|
||||
fwdAuthURI := urlutil.GetForwardAuthURL(hreq)
|
||||
in.Attributes.Request.Http.Scheme = fwdAuthURI.Scheme
|
||||
in.Attributes.Request.Http.Host = fwdAuthURI.Host
|
||||
in.Attributes.Request.Http.Path = fwdAuthURI.EscapedPath()
|
||||
|
@ -103,26 +102,6 @@ func (a *Authorize) Check(ctx context.Context, in *envoy_service_auth_v3.CheckRe
|
|||
return a.handleResultDenied(ctx, in, req, res, isForwardAuthVerify, res.Allow.Reasons)
|
||||
}
|
||||
|
||||
func getForwardAuthURL(r *http.Request) *url.URL {
|
||||
urqQuery := r.URL.Query().Get("uri")
|
||||
u, _ := urlutil.ParseAndValidateURL(urqQuery)
|
||||
if u == nil {
|
||||
u = &url.URL{
|
||||
Scheme: r.Header.Get(httputil.HeaderForwardedProto),
|
||||
Host: r.Header.Get(httputil.HeaderForwardedHost),
|
||||
Path: r.Header.Get(httputil.HeaderForwardedURI),
|
||||
}
|
||||
}
|
||||
originalURL := r.Header.Get(httputil.HeaderOriginalURL)
|
||||
if originalURL != "" {
|
||||
k, _ := urlutil.ParseAndValidateURL(originalURL)
|
||||
if k != nil {
|
||||
u = k
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// isForwardAuth returns if the current request is a forward auth route.
|
||||
func (a *Authorize) isForwardAuth(req *envoy_service_auth_v3.CheckRequest) bool {
|
||||
opts := a.currentOptions.Load()
|
||||
|
|
47
internal/urlutil/forward.go
Normal file
47
internal/urlutil/forward.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package urlutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Forward headers contains information from the client-facing side of proxy
|
||||
// servers that is altered or lost when a proxy is involved in the path of the
|
||||
// request.
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc7239
|
||||
// https://en.wikipedia.org/wiki/X-Forwarded-For
|
||||
const (
|
||||
HeaderForwardedHost = "X-Forwarded-Host"
|
||||
HeaderForwardedProto = "X-Forwarded-Proto"
|
||||
HeaderForwardedURI = "X-Forwarded-Uri" // traefik
|
||||
HeaderOriginalURL = "X-Original-Url" // nginx
|
||||
)
|
||||
|
||||
// GetForwardAuthURL gets the forward-auth URL for the given request.
|
||||
func GetForwardAuthURL(r *http.Request) *url.URL {
|
||||
urqQuery := r.URL.Query().Get("uri")
|
||||
u, _ := ParseAndValidateURL(urqQuery)
|
||||
if u == nil {
|
||||
u = &url.URL{
|
||||
Scheme: r.Header.Get(HeaderForwardedProto),
|
||||
Host: r.Header.Get(HeaderForwardedHost),
|
||||
}
|
||||
rawPath := r.Header.Get(HeaderForwardedURI)
|
||||
if idx := strings.Index(rawPath, "?"); idx >= 0 {
|
||||
u.RawPath = rawPath[:idx]
|
||||
u.RawQuery = rawPath[idx+1:]
|
||||
} else {
|
||||
u.RawPath = rawPath
|
||||
}
|
||||
}
|
||||
originalURL := r.Header.Get(HeaderOriginalURL)
|
||||
if originalURL != "" {
|
||||
k, _ := ParseAndValidateURL(originalURL)
|
||||
if k != nil {
|
||||
u = k
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
22
internal/urlutil/forward_test.go
Normal file
22
internal/urlutil/forward_test.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package urlutil
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetForwardAuthURL(t *testing.T) {
|
||||
t.Run("double-escaping", func(t *testing.T) {
|
||||
req, err := http.NewRequest("GET", "https://example.com", nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set("X-Forwarded-Proto", "https")
|
||||
req.Header.Set("X-Forwarded-Host", "protected-host.tld")
|
||||
req.Header.Set("X-Forwarded-Uri", "/example?a=b&c=d")
|
||||
|
||||
u := GetForwardAuthURL(req)
|
||||
assert.Equal(t, "https://protected-host.tld?a=b&c=d", u.String())
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue