From f9b1106df22664ad2737958033dda220db102f76 Mon Sep 17 00:00:00 2001 From: hwhelan-CB <39995146+hwhelan-CB@users.noreply.github.com> Date: Sat, 30 Jun 2018 01:54:03 -0400 Subject: [PATCH] Forward auth headers --- configuration/entrypoints.go | 12 +++++++++--- configuration/entrypoints_test.go | 10 ++++++++-- docs/configuration/entrypoints.md | 7 +++++++ middlewares/auth/forward.go | 4 ++++ middlewares/auth/forward_test.go | 13 ++++++++----- types/types.go | 7 ++++--- 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/configuration/entrypoints.go b/configuration/entrypoints.go index fef6ac7cc..dd4fbd43f 100644 --- a/configuration/entrypoints.go +++ b/configuration/entrypoints.go @@ -135,10 +135,16 @@ func makeEntryPointAuth(result map[string]string) *types.Auth { } } + var authResponseHeaders []string + if v, ok := result["auth_forward_authresponseheaders"]; ok { + authResponseHeaders = strings.Split(v, ",") + } + forward = &types.Forward{ - Address: address, - TLS: clientTLS, - TrustForwardHeader: toBool(result, "auth_forward_trustforwardheader"), + Address: address, + TLS: clientTLS, + TrustForwardHeader: toBool(result, "auth_forward_trustforwardheader"), + AuthResponseHeaders: authResponseHeaders, } } diff --git a/configuration/entrypoints_test.go b/configuration/entrypoints_test.go index 231f82364..74911b994 100644 --- a/configuration/entrypoints_test.go +++ b/configuration/entrypoints_test.go @@ -36,6 +36,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { "Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " + "Auth.HeaderField:X-WebAuth-User " + "Auth.Forward.Address:https://authserver.com/auth " + + "Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " + "Auth.Forward.TrustForwardHeader:true " + "Auth.Forward.TLS.CA:path/to/local.crt " + "Auth.Forward.TLS.CAOptional:true " + @@ -50,6 +51,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { "auth_basic_users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "auth_digest_users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e", "auth_forward_address": "https://authserver.com/auth", + "auth_forward_authresponseheaders": "X-Auth,X-Test,X-Secret", "auth_forward_tls_ca": "path/to/local.crt", "auth_forward_tls_caoptional": "true", "auth_forward_tls_cert": "path/to/foo.cert", @@ -191,6 +193,7 @@ func TestEntryPoints_Set(t *testing.T) { "Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " + "Auth.HeaderField:X-WebAuth-User " + "Auth.Forward.Address:https://authserver.com/auth " + + "Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " + "Auth.Forward.TrustForwardHeader:true " + "Auth.Forward.TLS.CA:path/to/local.crt " + "Auth.Forward.TLS.CAOptional:true " + @@ -241,7 +244,8 @@ func TestEntryPoints_Set(t *testing.T) { }, }, Forward: &types.Forward{ - Address: "https://authserver.com/auth", + Address: "https://authserver.com/auth", + AuthResponseHeaders: []string{"X-Auth", "X-Test", "X-Secret"}, TLS: &types.ClientTLS{ CA: "path/to/local.crt", CAOptional: true, @@ -302,6 +306,7 @@ func TestEntryPoints_Set(t *testing.T) { "auth.digest.users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " + "auth.headerField:X-WebAuth-User " + "auth.forward.address:https://authserver.com/auth " + + "auth.forward.authResponseHeaders:X-Auth,X-Test,X-Secret " + "auth.forward.trustForwardHeader:true " + "auth.forward.tls.ca:path/to/local.crt " + "auth.forward.tls.caOptional:true " + @@ -349,7 +354,8 @@ func TestEntryPoints_Set(t *testing.T) { }, }, Forward: &types.Forward{ - Address: "https://authserver.com/auth", + Address: "https://authserver.com/auth", + AuthResponseHeaders: []string{"X-Auth", "X-Test", "X-Secret"}, TLS: &types.ClientTLS{ CA: "path/to/local.crt", CAOptional: true, diff --git a/docs/configuration/entrypoints.md b/docs/configuration/entrypoints.md index c874d85d3..ff36c6231 100644 --- a/docs/configuration/entrypoints.md +++ b/docs/configuration/entrypoints.md @@ -60,6 +60,8 @@ cert = "path/to/foo.cert" key = "path/to/foo.key" insecureSkipVerify = true + [entryPoints.http.auth.forward] + authResponseHeaders = ["X-Auth-User"] [entryPoints.http.proxyProtocol] insecure = true @@ -126,6 +128,7 @@ Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e Auth.HeaderField:X-WebAuth-User Auth.Forward.Address:https://authserver.com/auth +Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret Auth.Forward.TrustForwardHeader:true Auth.Forward.TLS.CA:path/to/local.crt Auth.Forward.TLS.CAOptional:true @@ -310,6 +313,10 @@ Otherwise, the response from the authentication server is returned. # trustForwardHeader = true + # Copy headers from the authentication server to the request + [entryPoints.http.auth.forward] + authResponseHeaders = ["X-Auth-User", "X-Secret"] + # Enable forward auth TLS connection. # # Optional diff --git a/middlewares/auth/forward.go b/middlewares/auth/forward.go index 595e488e0..12e885fda 100644 --- a/middlewares/auth/forward.go +++ b/middlewares/auth/forward.go @@ -94,6 +94,10 @@ func Forward(config *types.Forward, w http.ResponseWriter, r *http.Request, next return } + for _, headerName := range config.AuthResponseHeaders { + r.Header.Set(headerName, forwardResponse.Header.Get(headerName)) + } + r.RequestURI = r.URL.RequestURI() next(w, r) } diff --git a/middlewares/auth/forward_test.go b/middlewares/auth/forward_test.go index c3fc025dc..72ce246b7 100644 --- a/middlewares/auth/forward_test.go +++ b/middlewares/auth/forward_test.go @@ -36,9 +36,8 @@ func TestForwardAuthFail(t *testing.T) { ts := httptest.NewServer(n) defer ts.Close() - client := &http.Client{} req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) - res, err := client.Do(req) + res, err := http.DefaultClient.Do(req) assert.NoError(t, err, "there should be no error") assert.Equal(t, http.StatusForbidden, res.StatusCode, "they should be equal") @@ -49,18 +48,23 @@ func TestForwardAuthFail(t *testing.T) { func TestForwardAuthSuccess(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Auth-User", "user@example.com") + w.Header().Set("X-Auth-Secret", "secret") fmt.Fprintln(w, "Success") })) defer server.Close() middleware, err := NewAuthenticator(&types.Auth{ Forward: &types.Forward{ - Address: server.URL, + Address: server.URL, + AuthResponseHeaders: []string{"X-Auth-User"}, }, }, &tracing.Tracing{}) assert.NoError(t, err, "there should be no error") handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "user@example.com", r.Header.Get("X-Auth-User")) + assert.Empty(t, r.Header.Get("X-Auth-Secret")) fmt.Fprintln(w, "traefik") }) n := negroni.New(middleware) @@ -68,9 +72,8 @@ func TestForwardAuthSuccess(t *testing.T) { ts := httptest.NewServer(n) defer ts.Close() - client := &http.Client{} req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) - res, err := client.Do(req) + res, err := http.DefaultClient.Do(req) assert.NoError(t, err, "there should be no error") assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") diff --git a/types/types.go b/types/types.go index 4ff401619..344e5aba2 100644 --- a/types/types.go +++ b/types/types.go @@ -412,9 +412,10 @@ type Digest struct { // Forward authentication type Forward struct { - Address string `description:"Authentication server address"` - TLS *ClientTLS `description:"Enable TLS support" export:"true"` - TrustForwardHeader bool `description:"Trust X-Forwarded-* headers" export:"true"` + Address string `description:"Authentication server address"` + TLS *ClientTLS `description:"Enable TLS support" export:"true"` + TrustForwardHeader bool `description:"Trust X-Forwarded-* headers" export:"true"` + AuthResponseHeaders []string `description:"Headers to be forwarded from auth response"` } // CanonicalDomain returns a lower case domain with trim space