From 9ce444b91ae85fcdcbad47c92e0fffdb943d5901 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Doumenjou Date: Mon, 16 Jul 2018 13:52:03 +0200 Subject: [PATCH] Don't pass the Authorization header to the backends --- autogen/gentemplates/gen.go | 16 ++++ configuration/entrypoints.go | 6 +- configuration/entrypoints_test.go | 8 ++ docs/configuration/backends/consulcatalog.md | 2 + docs/configuration/backends/docker.md | 4 + docs/configuration/backends/ecs.md | 3 + docs/configuration/backends/file.md | 2 + docs/configuration/backends/kubernetes.md | 1 + docs/configuration/backends/marathon.md | 76 ++++++++++------ docs/configuration/backends/mesos.md | 78 ++++++++++------ docs/configuration/backends/rancher.md | 6 +- docs/configuration/entrypoints.md | 45 ++++++++- middlewares/auth/authenticator.go | 12 +++ middlewares/auth/authenticator_test.go | 91 ++++++++++++++++--- provider/consulcatalog/config_test.go | 5 + .../docker/config_container_docker_test.go | 15 ++- .../docker/config_container_swarm_test.go | 19 ++-- provider/docker/config_segment_test.go | 27 ++++-- provider/ecs/config_test.go | 19 ++-- provider/kubernetes/annotations.go | 1 + provider/kubernetes/kubernetes.go | 9 +- provider/kubernetes/kubernetes_test.go | 6 +- provider/kv/keynames.go | 2 + provider/kv/kv_config.go | 8 +- provider/kv/kv_config_test.go | 9 ++ provider/label/names.go | 4 + provider/label/partial.go | 8 +- provider/label/partial_test.go | 18 ++-- provider/marathon/config_test.go | 25 +++++ provider/mesos/config_test.go | 10 ++ provider/rancher/config_test.go | 14 ++- templates/consul_catalog.tmpl | 2 + templates/docker.tmpl | 2 + templates/ecs.tmpl | 2 + templates/kubernetes.tmpl | 2 + templates/kv.tmpl | 2 + templates/marathon.tmpl | 2 + templates/mesos.tmpl | 2 + templates/rancher.tmpl | 2 + types/types.go | 10 +- 40 files changed, 445 insertions(+), 130 deletions(-) diff --git a/autogen/gentemplates/gen.go b/autogen/gentemplates/gen.go index 87647b094..5390fbe2d 100644 --- a/autogen/gentemplates/gen.go +++ b/autogen/gentemplates/gen.go @@ -232,6 +232,7 @@ var _templatesConsul_catalogTmpl = []byte(`[backends] {{if $auth.Basic }} [frontends."frontend-{{ $service.ServiceName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -242,6 +243,7 @@ var _templatesConsul_catalogTmpl = []byte(`[backends] {{if $auth.Digest }} [frontends."frontend-{{ $service.ServiceName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -679,6 +681,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}} {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -689,6 +692,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}} {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -977,6 +981,7 @@ var _templatesEcsTmpl = []byte(`[backends] {{if $auth.Basic }} [frontends."frontend-{{ $serviceName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -987,6 +992,7 @@ var _templatesEcsTmpl = []byte(`[backends] {{if $auth.Digest }} [frontends."frontend-{{ $serviceName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -1217,6 +1223,7 @@ var _templatesKubernetesTmpl = []byte(`[backends] {{if $frontend.Auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{$frontend.Auth.Basic.RemoveHeader}} users = [{{range $frontend.Auth.Basic.Users }} "{{.}}", {{end}}] @@ -1224,6 +1231,7 @@ var _templatesKubernetesTmpl = []byte(`[backends] {{if $frontend.Auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{$frontend.Auth.Digest.RemoveHeader}} users = [{{range $frontend.Auth.Digest.Users }} "{{.}}", {{end}}] @@ -1466,6 +1474,7 @@ var _templatesKvTmpl = []byte(`[backends] {{if $auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -1476,6 +1485,7 @@ var _templatesKvTmpl = []byte(`[backends] {{if $auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -1806,6 +1816,7 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }} {{if $auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -1816,6 +1827,7 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }} {{if $auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -2090,6 +2102,7 @@ var _templatesMesosTmpl = []byte(`[backends] {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader}} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -2100,6 +2113,7 @@ var _templatesMesosTmpl = []byte(`[backends] {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader}} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", @@ -2427,6 +2441,7 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }} {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -2437,6 +2452,7 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }} {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/configuration/entrypoints.go b/configuration/entrypoints.go index 7a5f679b8..abb0eebc9 100644 --- a/configuration/entrypoints.go +++ b/configuration/entrypoints.go @@ -106,14 +106,16 @@ func makeEntryPointAuth(result map[string]string) *types.Auth { var basic *types.Basic if v, ok := result["auth_basic_users"]; ok { basic = &types.Basic{ - Users: strings.Split(v, ","), + Users: strings.Split(v, ","), + RemoveHeader: toBool(result, "auth_basic_removeheader"), } } var digest *types.Digest if v, ok := result["auth_digest_users"]; ok { digest = &types.Digest{ - Users: strings.Split(v, ","), + Users: strings.Split(v, ","), + RemoveHeader: toBool(result, "auth_digest_removeheader"), } } diff --git a/configuration/entrypoints_test.go b/configuration/entrypoints_test.go index 74911b994..214ace662 100644 --- a/configuration/entrypoints_test.go +++ b/configuration/entrypoints_test.go @@ -33,7 +33,9 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { "ProxyProtocol.TrustedIPs:192.168.0.1 " + "ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " + "Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " + + "Auth.Basic.RemoveHeader:true " + "Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " + + "Auth.Digest.RemoveHeader:true " + "Auth.HeaderField:X-WebAuth-User " + "Auth.Forward.Address:https://authserver.com/auth " + "Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " + @@ -49,7 +51,9 @@ func Test_parseEntryPointsConfiguration(t *testing.T) { expectedResult: map[string]string{ "address": ":8000", "auth_basic_users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + "auth_basic_removeheader": "true", "auth_digest_users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e", + "auth_digest_removeheader": "true", "auth_forward_address": "https://authserver.com/auth", "auth_forward_authresponseheaders": "X-Auth,X-Test,X-Secret", "auth_forward_tls_ca": "path/to/local.crt", @@ -190,7 +194,9 @@ func TestEntryPoints_Set(t *testing.T) { "ProxyProtocol.TrustedIPs:192.168.0.1 " + "ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " + "Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " + + "Auth.Basic.RemoveHeader:true " + "Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " + + "Auth.Digest.RemoveHeader:true " + "Auth.HeaderField:X-WebAuth-User " + "Auth.Forward.Address:https://authserver.com/auth " + "Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret " + @@ -232,12 +238,14 @@ func TestEntryPoints_Set(t *testing.T) { }, Auth: &types.Auth{ Basic: &types.Basic{ + RemoveHeader: true, Users: types.Users{ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", }, }, Digest: &types.Digest{ + RemoveHeader: true, Users: types.Users{ "test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e", diff --git a/docs/configuration/backends/consulcatalog.md b/docs/configuration/backends/consulcatalog.md index 7b34e9835..be3a6b9ea 100644 --- a/docs/configuration/backends/consulcatalog.md +++ b/docs/configuration/backends/consulcatalog.md @@ -118,8 +118,10 @@ Additional settings can be defined using Consul Catalog tags. | `.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.
Must be used in conjunction with the below label to take effect. | | `.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `.frontend.auth.basic=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). | +| `.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `.frontend.auth.basic.users=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`. | | `.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `.frontend.auth.digest.users=EXPR` | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | | `.frontend.auth.digest.usersfile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | diff --git a/docs/configuration/backends/docker.md b/docs/configuration/backends/docker.md index b6092db66..6b89ff9fe 100644 --- a/docs/configuration/backends/docker.md +++ b/docs/configuration/backends/docker.md @@ -236,8 +236,10 @@ Labels can be used on containers to override default behavior. | `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.
Must be used in conjunction with the below label to take effect. | | `traefik.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `traefik.frontend.auth.basic=EXPR` | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2] (DEPRECATED). | +| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.basic.users=EXPR` | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2]. | | `traefik.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.digest.users=EXPR` | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | | `traefik.frontend.auth.digest.usersfile=/path/.htdigest` | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `traefik.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | @@ -326,8 +328,10 @@ Segment labels override the default behavior. | `traefik..protocol=http` | Same as `traefik.protocol` | | `traefik..weight=10` | Same as `traefik.weight` | | `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | +| `traefik..frontend.auth.basic.removeHeader=true` | Same as `traefik.frontend.auth.basic.removeHeader` | | `traefik..frontend.auth.basic.users=EXPR` | Same as `traefik.frontend.auth.basic.users` | | `traefik..frontend.auth.basic.usersfile=/path/.htpasswd` | Same as `traefik.frontend.auth.basic.usersfile` | +| `traefik..frontend.auth.digest.removeHeader=true` | Same as `traefik.frontend.auth.digest.removeHeader` | | `traefik..frontend.auth.digest.users=EXPR` | Same as `traefik.frontend.auth.digest.users` | | `traefik..frontend.auth.digest.usersfile=/path/.htdigest` | Same as `traefik.frontend.auth.digest.usersfile` | | `traefik..frontend.auth.forward.address=https://example.com`| Same as `traefik.frontend.auth.forward.address` | diff --git a/docs/configuration/backends/ecs.md b/docs/configuration/backends/ecs.md index dbcaec8d4..7c248409b 100644 --- a/docs/configuration/backends/ecs.md +++ b/docs/configuration/backends/ecs.md @@ -163,8 +163,10 @@ Labels can be used on task containers to override default behaviour: | `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.
Must be used in conjunction with the below label to take effect. | | `traefik.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `traefik.frontend.auth.basic=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). | +| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.basic.users=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`. | | `traefik.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.digest.users=EXPR` | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | | `traefik.frontend.auth.digest.usersfile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `traefik.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | @@ -175,6 +177,7 @@ Labels can be used on task containers to override default behaviour: | `traefik.frontend.auth.forward.tls.key=/path/server.key` | Sets the Certificate for the TLS connection with the authentication server. | | `traefik.frontend.auth.forward.trustForwardHeader=true` | Trusts X-Forwarded-* headers. | | `traefik.frontend.auth.headerField=X-WebAuth-User` | Sets the header used to pass the authenticated user to the application. | +| `traefik.frontend.auth.removeHeader=true` | If set to true, removes the Authorization header. | | `traefik.frontend.entryPoints=http,https` | Assigns this frontend to entry points `http` and `https`.
Overrides `defaultEntryPoints` | | `traefik.frontend.errors..backend=NAME` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | | `traefik.frontend.errors..query=PATH` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | diff --git a/docs/configuration/backends/file.md b/docs/configuration/backends/file.md index e85dd8a27..beb4e0b5e 100644 --- a/docs/configuration/backends/file.md +++ b/docs/configuration/backends/file.md @@ -65,12 +65,14 @@ Træfik can be configured with a file. [frontends.frontend1.auth] headerField = "X-WebAuth-User" [frontends.frontend1.auth.basic] + removeHeader = true users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", ] usersFile = "/path/to/.htpasswd" [frontends.frontend1.auth.digest] + removeHeader = true users = [ "test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e", diff --git a/docs/configuration/backends/kubernetes.md b/docs/configuration/backends/kubernetes.md index 7746aff3d..b574942d1 100644 --- a/docs/configuration/backends/kubernetes.md +++ b/docs/configuration/backends/kubernetes.md @@ -304,6 +304,7 @@ The source of the authentication is a Secret object that contains the credential |----------------------------------------------------------------------|-------|--------|---------|-------------------------------------------------------------------------------------------------------------| | `ingress.kubernetes.io/auth-type: basic` | x | x | x | Contains the authentication type: `basic`, `digest`, `forward`. | | `ingress.kubernetes.io/auth-secret: mysecret` | x | x | | Name of Secret containing the username and password with access to the paths defined in the Ingress object. | +| `ingress.kubernetes.io/auth-remove-header: true` | x | x | | If set to `true` removes the `Authorization` header. | | `ingress.kubernetes.io/auth-header-field: X-WebAuth-User` | x | x | | Pass Authenticated user to application via headers. | | `ingress.kubernetes.io/auth-url: https://example.com` | | | x | [The URL of the authentication server](/configuration/entrypoints/#forward-authentication). | | `ingress.kubernetes.io/auth-trust-headers: false` | | | x | Trust `X-Forwarded-*` headers. | diff --git a/docs/configuration/backends/marathon.md b/docs/configuration/backends/marathon.md index 775de201a..e6ad58d19 100644 --- a/docs/configuration/backends/marathon.md +++ b/docs/configuration/backends/marathon.md @@ -221,10 +221,12 @@ The following labels can be defined on Marathon applications. They adjust the be | `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.
Must be used in conjunction with the below label to take effect. | | `traefik.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `traefik.frontend.auth.basic=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). | +| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.basic.users=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`. | -| `traefik.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.basic.usersFile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.digest.users=EXPR` | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | -| `traefik.frontend.auth.digest.usersfile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.usersFile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `traefik.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem` | Sets the Certificate Authority (CA) for the TLS connection with the authentication server. | | `traefik.frontend.auth.forward.tls.caOptional=true` | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA). | @@ -233,6 +235,7 @@ The following labels can be defined on Marathon applications. They adjust the be | `traefik.frontend.auth.forward.tls.key=/path/server.key` | Sets the Certificate for the TLS connection with the authentication server. | | `traefik.frontend.auth.forward.trustForwardHeader=true` | Trusts X-Forwarded-* headers. | | `traefik.frontend.auth.headerField=X-WebAuth-User` | Sets the header used to pass the authenticated user to the application. | +| `traefik.frontend.auth.removeHeader=true` | If set to true, removes the Authorization header. | | `traefik.frontend.entryPoints=http,https` | Assigns this frontend to entry points `http` and `https`.
Overrides `defaultEntryPoints` | | `traefik.frontend.errors..backend=NAME` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | | `traefik.frontend.errors..query=PATH` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | @@ -293,33 +296,48 @@ You can define as many segments as ports exposed in an application. Segment labels override the default behavior. -| Label | Description | -|---------------------------------------------------------------------------|-------------------------------------------------------------| -| `traefik..backend=BACKEND` | Same as `traefik.backend` | -| `traefik..domain=DOMAIN` | Same as `traefik.domain` | -| `traefik..portIndex=1` | Same as `traefik.portIndex` | -| `traefik..port=PORT` | Same as `traefik.port` | -| `traefik..protocol=http` | Same as `traefik.protocol` | -| `traefik..weight=10` | Same as `traefik.weight` | -| `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | -| `traefik..frontend.entryPoints=https` | Same as `traefik.frontend.entryPoints` | -| `traefik..frontend.errors..backend=NAME` | Same as `traefik.frontend.errors..backend` | -| `traefik..frontend.errors..query=PATH` | Same as `traefik.frontend.errors..query` | -| `traefik..frontend.errors..status=RANGE` | Same as `traefik.frontend.errors..status` | -| `traefik..frontend.passHostHeader=true` | Same as `traefik.frontend.passHostHeader` | -| `traefik..frontend.passTLSCert=true` | Same as `traefik.frontend.passTLSCert` | -| `traefik..frontend.priority=10` | Same as `traefik.frontend.priority` | -| `traefik..frontend.rateLimit.extractorFunc=EXP` | Same as `traefik.frontend.rateLimit.extractorFunc` | -| `traefik..frontend.rateLimit.rateSet..period=6` | Same as `traefik.frontend.rateLimit.rateSet..period` | -| `traefik..frontend.rateLimit.rateSet..average=6` | Same as `traefik.frontend.rateLimit.rateSet..average` | -| `traefik..frontend.rateLimit.rateSet..burst=6` | Same as `traefik.frontend.rateLimit.rateSet..burst` | -| `traefik..frontend.redirect.entryPoint=https` | Same as `traefik.frontend.redirect.entryPoint` | -| `traefik..frontend.redirect.regex=^http://localhost/(.*)` | Same as `traefik.frontend.redirect.regex` | -| `traefik..frontend.redirect.replacement=http://mydomain/$1` | Same as `traefik.frontend.redirect.replacement` | -| `traefik..frontend.redirect.permanent=true` | Same as `traefik.frontend.redirect.permanent` | -| `traefik..frontend.rule=EXP` | Same as `traefik.frontend.rule` | -| `traefik..frontend.whiteList.sourceRange=RANGE` | Same as `traefik.frontend.whiteList.sourceRange` | -| `traefik..frontend.whiteList.useXForwardedFor=true` | Same as `traefik.frontend.whiteList.useXForwardedFor` | +| Label | Description | +|---------------------------------------------------------------------------|----------------------------------------------------------------| +| `traefik..backend=BACKEND` | Same as `traefik.backend` | +| `traefik..domain=DOMAIN` | Same as `traefik.domain` | +| `traefik..portIndex=1` | Same as `traefik.portIndex` | +| `traefik..port=PORT` | Same as `traefik.port` | +| `traefik..protocol=http` | Same as `traefik.protocol` | +| `traefik..weight=10` | Same as `traefik.weight` | +| `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | +| `traefik..frontend.auth.basic.removeHeader=true` | Same as `traefik.frontend.auth.basic.removeHeader` | +| `traefik..frontend.auth.basic.users=EXPR` | Same as `traefik.frontend.auth.basic.users` | +| `traefik..frontend.auth.basic.usersFile=/path/.htpasswd` | Same as `traefik.frontend.auth.basic.usersFile` | +| `traefik..frontend.auth.digest.removeHeader=true` | Same as `traefik.frontend.auth.digest.removeHeader` | +| `traefik..frontend.auth.digest.users=EXPR` | Same as `traefik.frontend.auth.digest.users` | +| `traefik..frontend.auth.digest.usersFile=/path/.htdigest` | Same as `traefik.frontend.auth.digest.usersFile` | +| `traefik..frontend.auth.forward.address=https://example.com`| Same as `traefik.frontend.auth.forward.address` | +| `traefik..frontend.auth.forward.tls.ca=/path/ca.pem` | Same as `traefik.frontend.auth.forward.tls.ca` | +| `traefik..frontend.auth.forward.tls.caOptional=true` | Same as `traefik.frontend.auth.forward.tls.caOptional` | +| `traefik..frontend.auth.forward.tls.cert=/path/server.pem` | Same as `traefik.frontend.auth.forward.tls.cert` | +| `traefik..frontend.auth.forward.tls.insecureSkipVerify=true`| Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify` | +| `traefik..frontend.auth.forward.tls.key=/path/server.key` | Same as `traefik.frontend.auth.forward.tls.key` | +| `traefik..frontend.auth.forward.trustForwardHeader=true` | Same as `traefik.frontend.auth.forward.trustForwardHeader` | +| `traefik..frontend.auth.headerField=X-WebAuth-User` | Same as `traefik.frontend.auth.headerField` | +| `traefik..frontend.auth.removeHeader=true` | Same as `traefik.frontend.auth.removeHeader` | +| `traefik..frontend.entryPoints=https` | Same as `traefik.frontend.entryPoints` | +| `traefik..frontend.errors..backend=NAME` | Same as `traefik.frontend.errors..backend` | +| `traefik..frontend.errors..query=PATH` | Same as `traefik.frontend.errors..query` | +| `traefik..frontend.errors..status=RANGE` | Same as `traefik.frontend.errors..status` | +| `traefik..frontend.passHostHeader=true` | Same as `traefik.frontend.passHostHeader` | +| `traefik..frontend.passTLSCert=true` | Same as `traefik.frontend.passTLSCert` | +| `traefik..frontend.priority=10` | Same as `traefik.frontend.priority` | +| `traefik..frontend.rateLimit.extractorFunc=EXP` | Same as `traefik.frontend.rateLimit.extractorFunc` | +| `traefik..frontend.rateLimit.rateSet..period=6` | Same as `traefik.frontend.rateLimit.rateSet..period` | +| `traefik..frontend.rateLimit.rateSet..average=6` | Same as `traefik.frontend.rateLimit.rateSet..average` | +| `traefik..frontend.rateLimit.rateSet..burst=6` | Same as `traefik.frontend.rateLimit.rateSet..burst` | +| `traefik..frontend.redirect.entryPoint=https` | Same as `traefik.frontend.redirect.entryPoint` | +| `traefik..frontend.redirect.regex=^http://localhost/(.*)` | Same as `traefik.frontend.redirect.regex` | +| `traefik..frontend.redirect.replacement=http://mydomain/$1` | Same as `traefik.frontend.redirect.replacement` | +| `traefik..frontend.redirect.permanent=true` | Same as `traefik.frontend.redirect.permanent` | +| `traefik..frontend.rule=EXP` | Same as `traefik.frontend.rule` | +| `traefik..frontend.whiteList.sourceRange=RANGE` | Same as `traefik.frontend.whiteList.sourceRange` | +| `traefik..frontend.whiteList.useXForwardedFor=true` | Same as `traefik.frontend.whiteList.useXForwardedFor` | #### Custom Headers diff --git a/docs/configuration/backends/mesos.md b/docs/configuration/backends/mesos.md index 51734e523..e1b83e85a 100644 --- a/docs/configuration/backends/mesos.md +++ b/docs/configuration/backends/mesos.md @@ -135,9 +135,11 @@ The following labels can be defined on Mesos tasks. They adjust the behavior for | `traefik.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `traefik.frontend.auth.basic=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). | | `traefik.frontend.auth.basic.users=EXPR` | Sets basic authentication to this frontend in CSV format: `User:Hash,User:Hash`. | -| `traefik.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | +| `traefik.frontend.auth.basic.usersFile=/path/.htpasswd` | Sets basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.digest.users=EXPR` | Sets digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | -| `traefik.frontend.auth.digest.usersfile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.usersFile=/path/.htdigest` | Sets digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `traefik.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | | `traefik.frontend.auth.forward.tls.ca=/path/ca.pem` | Sets the Certificate Authority (CA) for the TLS connection with the authentication server. | | `traefik.frontend.auth.forward.tls.caOptional=true` | Checks the certificates if present but do not force to be signed by a specified Certificate Authority (CA). | @@ -146,6 +148,7 @@ The following labels can be defined on Mesos tasks. They adjust the behavior for | `traefik.frontend.auth.forward.tls.key=/path/server.key` | Sets the Certificate for the TLS connection with the authentication server. | | `traefik.frontend.auth.forward.trustForwardHeader=true` | Trusts X-Forwarded-* headers. | | `traefik.frontend.auth.headerField=X-WebAuth-User` | Sets the header used to pass the authenticated user to the application. | +| `traefik.frontend.auth.removeHeader=true` | If set to true, removes the Authorization header. | | `traefik.frontend.entryPoints=http,https` | Assigns this frontend to entry points `http` and `https`.
Overrides `defaultEntryPoints` | | `traefik.frontend.errors..backend=NAME` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | | `traefik.frontend.errors..query=PATH` | See [custom error pages](/configuration/commons/#custom-error-pages) section. | @@ -207,34 +210,49 @@ Additionally, if a segment name matches a named port, that port will be used unl Segment labels override the default behavior. -| Label | Description | -|---------------------------------------------------------------------------|-------------------------------------------------------------| -| `traefik..backend=BACKEND` | Same as `traefik.backend` | -| `traefik..domain=DOMAIN` | Same as `traefik.domain` | -| `traefik..portIndex=1` | Same as `traefik.portIndex` | -| `traefik..portName=web` | Same as `traefik.portName` | -| `traefik..port=PORT` | Same as `traefik.port` | -| `traefik..protocol=http` | Same as `traefik.protocol` | -| `traefik..weight=10` | Same as `traefik.weight` | -| `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | -| `traefik..frontend.entryPoints=https` | Same as `traefik.frontend.entryPoints` | -| `traefik..frontend.errors..backend=NAME` | Same as `traefik.frontend.errors..backend` | -| `traefik..frontend.errors..query=PATH` | Same as `traefik.frontend.errors..query` | -| `traefik..frontend.errors..status=RANGE` | Same as `traefik.frontend.errors..status` | -| `traefik..frontend.passHostHeader=true` | Same as `traefik.frontend.passHostHeader` | -| `traefik..frontend.passTLSCert=true` | Same as `traefik.frontend.passTLSCert` | -| `traefik..frontend.priority=10` | Same as `traefik.frontend.priority` | -| `traefik..frontend.rateLimit.extractorFunc=EXP` | Same as `traefik.frontend.rateLimit.extractorFunc` | -| `traefik..frontend.rateLimit.rateSet..period=6` | Same as `traefik.frontend.rateLimit.rateSet..period` | -| `traefik..frontend.rateLimit.rateSet..average=6` | Same as `traefik.frontend.rateLimit.rateSet..average` | -| `traefik..frontend.rateLimit.rateSet..burst=6` | Same as `traefik.frontend.rateLimit.rateSet..burst` | -| `traefik..frontend.redirect.entryPoint=https` | Same as `traefik.frontend.redirect.entryPoint` | -| `traefik..frontend.redirect.regex=^http://localhost/(.*)` | Same as `traefik.frontend.redirect.regex` | -| `traefik..frontend.redirect.replacement=http://mydomain/$1` | Same as `traefik.frontend.redirect.replacement` | -| `traefik..frontend.redirect.permanent=true` | Same as `traefik.frontend.redirect.permanent` | -| `traefik..frontend.rule=EXP` | Same as `traefik.frontend.rule` | -| `traefik..frontend.whiteList.sourceRange=RANGE` | Same as `traefik.frontend.whiteList.sourceRange` | -| `traefik..frontend.whiteList.useXForwardedFor=true` | Same as `traefik.frontend.whiteList.useXForwardedFor` | +| Label | Description | +|---------------------------------------------------------------------------|----------------------------------------------------------------| +| `traefik..backend=BACKEND` | Same as `traefik.backend` | +| `traefik..domain=DOMAIN` | Same as `traefik.domain` | +| `traefik..portIndex=1` | Same as `traefik.portIndex` | +| `traefik..portName=web` | Same as `traefik.portName` | +| `traefik..port=PORT` | Same as `traefik.port` | +| `traefik..protocol=http` | Same as `traefik.protocol` | +| `traefik..weight=10` | Same as `traefik.weight` | +| `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | +| `traefik..frontend.auth.basic.removeHeader=true` | Same as `traefik.frontend.auth.basic.removeHeader` | +| `traefik..frontend.auth.basic.users=EXPR` | Same as `traefik.frontend.auth.basic.users` | +| `traefik..frontend.auth.basic.usersFile=/path/.htpasswd` | Same as `traefik.frontend.auth.basic.usersFile` | +| `traefik..frontend.auth.digest.removeHeader=true` | Same as `traefik.frontend.auth.digest.removeHeader` | +| `traefik..frontend.auth.digest.users=EXPR` | Same as `traefik.frontend.auth.digest.users` | +| `traefik..frontend.auth.digest.usersFile=/path/.htdigest` | Same as `traefik.frontend.auth.digest.usersFile` | +| `traefik..frontend.auth.forward.address=https://example.com`| Same as `traefik.frontend.auth.forward.address` | +| `traefik..frontend.auth.forward.tls.ca=/path/ca.pem` | Same as `traefik.frontend.auth.forward.tls.ca` | +| `traefik..frontend.auth.forward.tls.caOptional=true` | Same as `traefik.frontend.auth.forward.tls.caOptional` | +| `traefik..frontend.auth.forward.tls.cert=/path/server.pem` | Same as `traefik.frontend.auth.forward.tls.cert` | +| `traefik..frontend.auth.forward.tls.insecureSkipVerify=true`| Same as `traefik.frontend.auth.forward.tls.insecureSkipVerify` | +| `traefik..frontend.auth.forward.tls.key=/path/server.key` | Same as `traefik.frontend.auth.forward.tls.key` | +| `traefik..frontend.auth.forward.trustForwardHeader=true` | Same as `traefik.frontend.auth.forward.trustForwardHeader` | +| `traefik..frontend.auth.headerField=X-WebAuth-User` | Same as `traefik.frontend.auth.headerField` | +| `traefik..frontend.auth.removeHeader=true` | Same as `traefik.frontend.auth.removeHeader` | +| `traefik..frontend.entryPoints=https` | Same as `traefik.frontend.entryPoints` | +| `traefik..frontend.errors..backend=NAME` | Same as `traefik.frontend.errors..backend` | +| `traefik..frontend.errors..query=PATH` | Same as `traefik.frontend.errors..query` | +| `traefik..frontend.errors..status=RANGE` | Same as `traefik.frontend.errors..status` | +| `traefik..frontend.passHostHeader=true` | Same as `traefik.frontend.passHostHeader` | +| `traefik..frontend.passTLSCert=true` | Same as `traefik.frontend.passTLSCert` | +| `traefik..frontend.priority=10` | Same as `traefik.frontend.priority` | +| `traefik..frontend.rateLimit.extractorFunc=EXP` | Same as `traefik.frontend.rateLimit.extractorFunc` | +| `traefik..frontend.rateLimit.rateSet..period=6` | Same as `traefik.frontend.rateLimit.rateSet..period` | +| `traefik..frontend.rateLimit.rateSet..average=6` | Same as `traefik.frontend.rateLimit.rateSet..average` | +| `traefik..frontend.rateLimit.rateSet..burst=6` | Same as `traefik.frontend.rateLimit.rateSet..burst` | +| `traefik..frontend.redirect.entryPoint=https` | Same as `traefik.frontend.redirect.entryPoint` | +| `traefik..frontend.redirect.regex=^http://localhost/(.*)` | Same as `traefik.frontend.redirect.regex` | +| `traefik..frontend.redirect.replacement=http://mydomain/$1` | Same as `traefik.frontend.redirect.replacement` | +| `traefik..frontend.redirect.permanent=true` | Same as `traefik.frontend.redirect.permanent` | +| `traefik..frontend.rule=EXP` | Same as `traefik.frontend.rule` | +| `traefik..frontend.whiteList.sourceRange=RANGE` | Same as `traefik.frontend.whiteList.sourceRange` | +| `traefik..frontend.whiteList.useXForwardedFor=true` | Same as `traefik.frontend.whiteList.useXForwardedFor` | #### Custom Headers diff --git a/docs/configuration/backends/rancher.md b/docs/configuration/backends/rancher.md index 74e8266fe..23d925ea6 100644 --- a/docs/configuration/backends/rancher.md +++ b/docs/configuration/backends/rancher.md @@ -142,7 +142,7 @@ Labels can be used on task containers to override default behavior: |------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `traefik.domain` | Sets the default domain for the frontend rules. | | `traefik.enable=false` | Disables this container in Træfik. | -| `traefik.port=80` | Registers this port. Useful when the container exposes multiple ports. | +| `traefik.port=80` | Registers this port. Useful when the container exposes multiple ports. | | `traefik.protocol=https` | Overrides the default `http` protocol. | | `traefik.weight=10` | Assigns this weight to the container. | | `traefik.backend=foo` | Gives the name `foo` to the generated backend for this container. | @@ -165,8 +165,10 @@ Labels can be used on task containers to override default behavior: | `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.
Must be used in conjunction with the below label to take effect. | | `traefik.backend.maxconn.extractorfunc=client.ip` | Sets the function to be used against the request to determine what to limit maximum connections to the backend by.
Must be used in conjunction with the above label to take effect. | | `traefik.frontend.auth.basic=EXPR` | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` (DEPRECATED). | +| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.basic.users=EXPR` | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` . | | `traefik.frontend.auth.basic.usersfile=/path/.htpasswd` | Sets the basic authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | +| `traefik.frontend.auth.digest.removeHeader=true` | If set to `true`, removes the `Authorization` header. | | `traefik.frontend.auth.digest.users=EXPR` | Sets the digest authentication to this frontend in CSV format: `User:Realm:Hash,User:Realm:Hash`. | | `traefik.frontend.auth.digest.usersfile=/path/.htdigest` | Sets the digest authentication with an external file; if users and usersFile are provided, both are merged, with external file contents having precedence. | | `traefik.frontend.auth.forward.address=https://example.com`| Sets the URL of the authentication server. | @@ -244,8 +246,10 @@ Segment labels override the default behavior. | `traefik..protocol=http` | Same as `traefik.protocol` | | `traefik..weight=10` | Same as `traefik.weight` | | `traefik..frontend.auth.basic=EXPR` | Same as `traefik.frontend.auth.basic` | +| `traefik..frontend.auth.basic.removeHeader=true` | Same as `traefik.frontend.auth.basic.removeHeader` | | `traefik..frontend.auth.basic.users=EXPR` | Same as `traefik.frontend.auth.basic.users` | | `traefik..frontend.auth.basic.usersfile=/path/.htpasswd` | Same as `traefik.frontend.auth.basic.usersfile` | +| `traefik..frontend.auth.digest.removeHeader=true` | Same as `traefik.frontend.auth.digest.removeHeader` | | `traefik..frontend.auth.digest.users=EXPR` | Same as `traefik.frontend.auth.digest.users` | | `traefik..frontend.auth.digest.usersfile=/path/.htdigest` | Same as `traefik.frontend.auth.digest.usersfile` | | `traefik..frontend.auth.forward.address=https://example.com`| Same as `traefik.frontend.auth.forward.address` | diff --git a/docs/configuration/entrypoints.md b/docs/configuration/entrypoints.md index 5704c27d2..1aa81b454 100644 --- a/docs/configuration/entrypoints.md +++ b/docs/configuration/entrypoints.md @@ -5,6 +5,11 @@ ### TOML ```toml +defaultEntryPoints = ["http", "https"] + +# ... +# ... + [entryPoints] [entryPoints.http] address = ":80" @@ -40,12 +45,14 @@ [entryPoints.http.auth] headerField = "X-WebAuth-User" [entryPoints.http.auth.basic] + removeHeader = true users = [ "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", ] usersFile = "/path/to/.htpasswd" [entryPoints.http.auth.digest] + removeHeader = true users = [ "test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e", @@ -127,7 +134,9 @@ ProxyProtocol.TrustedIPs:192.168.0.1 ProxyProtocol.Insecure:true ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 +Auth.Basic.Removeheader:true Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e +Auth.Digest.Removeheader:true Auth.HeaderField:X-WebAuth-User Auth.Forward.Address:https://authserver.com/auth Auth.Forward.AuthResponseHeaders:X-Auth,X-Test,X-Secret @@ -275,18 +284,32 @@ Users can be specified directly in the TOML file, or indirectly by referencing a usersFile = "/path/to/.htpasswd" ``` -Optionally, you can pass authenticated user to application via headers +Optionally, you can: + +- pass authenticated user to application via headers ```toml [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.auth] - headerField = "X-WebAuth-User" # <-- + headerField = "X-WebAuth-User" # <-- header for the authenticated user [entryPoints.http.auth.basic] users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] ``` +- remove the Authorization header + +```toml +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.auth] + [entryPoints.http.auth.basic] + removeHeader = true # <-- remove the Authorization header + users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"] +``` + ### Digest Authentication You can use `htdigest` to generate them. @@ -304,18 +327,32 @@ Users can be specified directly in the TOML file, or indirectly by referencing a usersFile = "/path/to/.htdigest" ``` -Optionally, you can pass authenticated user to application via headers +Optionally, you can! + +- pass authenticated user to application via headers. ```toml [entryPoints] [entryPoints.http] address = ":80" [entryPoints.http.auth] - headerField = "X-WebAuth-User" # <-- + headerField = "X-WebAuth-User" # <-- header for the authenticated user [entryPoints.http.auth.digest] users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] ``` +- remove the Authorization header. + +```toml +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.auth] + [entryPoints.http.auth.digest] + removeHeader = true # <-- remove the Authorization header + users = ["test:traefik:a2688e031edb4be6a3797f3882655c05", "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"] +``` + ### Forward Authentication This configuration will first forward the request to `http://authserver.com/auth`. diff --git a/middlewares/auth/authenticator.go b/middlewares/auth/authenticator.go index 20e29635c..ea223049e 100644 --- a/middlewares/auth/authenticator.go +++ b/middlewares/auth/authenticator.go @@ -26,6 +26,10 @@ type tracingAuthenticator struct { clientSpanKind bool } +const ( + authorizationHeader = "Authorization" +) + // NewAuthenticator builds a new Authenticator given a config func NewAuthenticator(authConfig *types.Auth, tracingMiddleware *tracing.Tracing) (*Authenticator, error) { if authConfig == nil { @@ -86,6 +90,10 @@ func createAuthDigestHandler(digestAuth *goauth.DigestAuth, authConfig *types.Au if authConfig.HeaderField != "" { r.Header[authConfig.HeaderField] = []string{username} } + if authConfig.Digest.RemoveHeader { + log.Debugf("Remove the Authorization header from the Digest auth") + r.Header.Del(authorizationHeader) + } next.ServeHTTP(w, r) } }) @@ -101,6 +109,10 @@ func createAuthBasicHandler(basicAuth *goauth.BasicAuth, authConfig *types.Auth) if authConfig.HeaderField != "" { r.Header[authConfig.HeaderField] = []string{username} } + if authConfig.Basic.RemoveHeader { + log.Debugf("Remove the Authorization header from the Basic auth") + r.Header.Del(authorizationHeader) + } next.ServeHTTP(w, r) } }) diff --git a/middlewares/auth/authenticator_test.go b/middlewares/auth/authenticator_test.go index 0de79dfb2..360148600 100644 --- a/middlewares/auth/authenticator_test.go +++ b/middlewares/auth/authenticator_test.go @@ -12,6 +12,7 @@ import ( "github.com/containous/traefik/testhelpers" "github.com/containous/traefik/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/urfave/negroni" ) @@ -51,13 +52,16 @@ func TestAuthUsersFromFile(t *testing.T) { t.Run(test.authType, func(t *testing.T) { t.Parallel() usersFile, err := ioutil.TempFile("", "auth-users") - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) defer os.Remove(usersFile.Name()) + _, err = usersFile.Write([]byte(test.usersStr)) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) + users, err := test.parserFunc(usersFile.Name()) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, 2, len(users), "they should be equal") + _, ok := users[test.userKeys[0]] assert.True(t, ok, "user test should be found") _, ok = users[test.userKeys[1]] @@ -79,7 +83,7 @@ func TestBasicAuthFail(t *testing.T) { Users: []string{"test:test"}, }, }, &tracing.Tracing{}) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "traefik") @@ -93,7 +97,7 @@ func TestBasicAuthFail(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) req.SetBasicAuth("test", "test") res, err := client.Do(req) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, res.StatusCode, "they should be equal") } @@ -103,7 +107,7 @@ func TestBasicAuthSuccess(t *testing.T) { Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"}, }, }, &tracing.Tracing{}) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "traefik") @@ -117,11 +121,11 @@ func TestBasicAuthSuccess(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) req.SetBasicAuth("test", "test") res, err := client.Do(req) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") body, err := ioutil.ReadAll(res.Body) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, "traefik\n", string(body), "they should be equal") } @@ -138,7 +142,7 @@ func TestDigestAuthFail(t *testing.T) { Users: []string{"test:traefik:test"}, }, }, &tracing.Tracing{}) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.NotNil(t, authMiddleware, "this should not be nil") handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -153,7 +157,7 @@ func TestDigestAuthFail(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) req.SetBasicAuth("test", "test") res, err := client.Do(req) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, res.StatusCode, "they should be equal") } @@ -164,7 +168,7 @@ func TestBasicAuthUserHeader(t *testing.T) { }, HeaderField: "X-Webauth-User", }, &tracing.Tracing{}) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "test", r.Header["X-Webauth-User"][0], "auth user should be set") @@ -179,11 +183,72 @@ func TestBasicAuthUserHeader(t *testing.T) { req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) req.SetBasicAuth("test", "test") res, err := client.Do(req) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") body, err := ioutil.ReadAll(res.Body) - assert.NoError(t, err, "there should be no error") + require.NoError(t, err) + assert.Equal(t, "traefik\n", string(body), "they should be equal") +} + +func TestBasicAuthHeaderRemoved(t *testing.T) { + middleware, err := NewAuthenticator(&types.Auth{ + Basic: &types.Basic{ + RemoveHeader: true, + Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"}, + }, + }, &tracing.Tracing{}) + require.NoError(t, err) + + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Empty(t, r.Header.Get(authorizationHeader)) + fmt.Fprintln(w, "traefik") + }) + n := negroni.New(middleware) + n.UseHandler(handler) + ts := httptest.NewServer(n) + defer ts.Close() + + client := &http.Client{} + req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) + req.SetBasicAuth("test", "test") + res, err := client.Do(req) + require.NoError(t, err) + + assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") + + body, err := ioutil.ReadAll(res.Body) + require.NoError(t, err) + assert.Equal(t, "traefik\n", string(body), "they should be equal") +} + +func TestBasicAuthHeaderPresent(t *testing.T) { + middleware, err := NewAuthenticator(&types.Auth{ + Basic: &types.Basic{ + Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"}, + }, + }, &tracing.Tracing{}) + require.NoError(t, err) + + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.NotEmpty(t, r.Header.Get(authorizationHeader)) + fmt.Fprintln(w, "traefik") + }) + n := negroni.New(middleware) + n.UseHandler(handler) + ts := httptest.NewServer(n) + defer ts.Close() + + client := &http.Client{} + req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil) + req.SetBasicAuth("test", "test") + res, err := client.Do(req) + require.NoError(t, err) + + assert.Equal(t, http.StatusOK, res.StatusCode, "they should be equal") + + body, err := ioutil.ReadAll(res.Body) + require.NoError(t, err) assert.Equal(t, "traefik\n", string(body), "they should be equal") } diff --git a/provider/consulcatalog/config_test.go b/provider/consulcatalog/config_test.go index 70bc96f5d..332a14dee 100644 --- a/provider/consulcatalog/config_test.go +++ b/provider/consulcatalog/config_test.go @@ -188,6 +188,7 @@ func TestProviderBuildConfiguration(t *testing.T) { ServiceName: "test", Attributes: []string{ "random.foo=bar", + label.TraefikFrontendAuthDigestRemoveHeader + "=true", label.TraefikFrontendAuthDigestUsers + "=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthDigestUsersFile + "=.htpasswd", }, @@ -224,6 +225,7 @@ func TestProviderBuildConfiguration(t *testing.T) { }, Auth: &types.Auth{ Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -348,8 +350,10 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackendBufferingRetryExpression + "=IsNetworkError() && Attempts() <= 2", label.TraefikFrontendAuthBasic + "=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthBasicRemoveHeader + "=true", label.TraefikFrontendAuthBasicUsers + "=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthBasicUsersFile + "=.htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader + "=true", label.TraefikFrontendAuthDigestUsers + "=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthDigestUsersFile + "=.htpasswd", label.TraefikFrontendAuthForwardAddress + "=auth.server", @@ -464,6 +468,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/docker/config_container_docker_test.go b/provider/docker/config_container_docker_test.go index 7d284d579..457a195ce 100644 --- a/provider/docker/config_container_docker_test.go +++ b/provider/docker/config_container_docker_test.go @@ -69,8 +69,9 @@ func TestDockerBuildConfiguration(t *testing.T) { containerJSON( name("test"), labels(map[string]string{ - label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthBasicRemoveHeader: "true", }), ports(nat.PortMap{ "80/tcp": {}, @@ -85,6 +86,7 @@ func TestDockerBuildConfiguration(t *testing.T) { EntryPoints: []string{}, Auth: &types.Auth{ Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -159,8 +161,9 @@ func TestDockerBuildConfiguration(t *testing.T) { containerJSON( name("test"), labels(map[string]string{ - label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", + label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", }), ports(nat.PortMap{ "80/tcp": {}, @@ -175,6 +178,7 @@ func TestDockerBuildConfiguration(t *testing.T) { EntryPoints: []string{}, Auth: &types.Auth{ Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -385,8 +389,10 @@ func TestDockerBuildConfiguration(t *testing.T) { label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2", label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthBasicRemoveHeader: "true", label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", label.TraefikFrontendAuthForwardAddress: "auth.server", @@ -472,6 +478,7 @@ func TestDockerBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/docker/config_container_swarm_test.go b/provider/docker/config_container_swarm_test.go index 4c9676951..ced5b0dc2 100644 --- a/provider/docker/config_container_swarm_test.go +++ b/provider/docker/config_container_swarm_test.go @@ -99,9 +99,10 @@ func TestSwarmBuildConfiguration(t *testing.T) { swarmService( serviceName("test"), serviceLabels(map[string]string{ - label.TraefikPort: "80", - label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikPort: "80", + label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthBasicRemoveHeader: "true", }), withEndpointSpec(modeVIP), withEndpoint(virtualIP("1", "127.0.0.1/24")), @@ -114,6 +115,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { EntryPoints: []string{}, Auth: &types.Auth{ Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -195,9 +197,10 @@ func TestSwarmBuildConfiguration(t *testing.T) { swarmService( serviceName("test"), serviceLabels(map[string]string{ - label.TraefikPort: "80", - label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", + label.TraefikPort: "80", + label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", }), withEndpointSpec(modeVIP), withEndpoint(virtualIP("1", "127.0.0.1/24")), @@ -210,6 +213,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { EntryPoints: []string{}, Auth: &types.Auth{ Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -329,8 +333,10 @@ func TestSwarmBuildConfiguration(t *testing.T) { label.TraefikBackendBufferingMemRequestBodyBytes: "2097152", label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2", + label.TraefikFrontendAuthBasicRemoveHeader: "true", label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", label.TraefikFrontendAuthForwardAddress: "auth.server", @@ -414,6 +420,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/docker/config_segment_test.go b/provider/docker/config_segment_test.go index 210663e9e..1452b5fb3 100644 --- a/provider/docker/config_segment_test.go +++ b/provider/docker/config_segment_test.go @@ -71,11 +71,12 @@ func TestSegmentBuildConfiguration(t *testing.T) { containerJSON( name("foo"), labels(map[string]string{ - "traefik.sauternes.port": "2503", - "traefik.sauternes.frontend.entryPoints": "http,https", - label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User", - label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd", + "traefik.sauternes.port": "2503", + "traefik.sauternes.frontend.entryPoints": "http,https", + label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User", + label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd", + label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true", }), ports(nat.PortMap{ "80/tcp": {}, @@ -96,6 +97,7 @@ func TestSegmentBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -167,11 +169,12 @@ func TestSegmentBuildConfiguration(t *testing.T) { containerJSON( name("foo"), labels(map[string]string{ - "traefik.sauternes.port": "2503", - "traefik.sauternes.frontend.entryPoints": "http,https", - label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User", - label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsersFile: ".htpasswd", + "traefik.sauternes.port": "2503", + "traefik.sauternes.frontend.entryPoints": "http,https", + label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User", + label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsersFile: ".htpasswd", + label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestRemoveHeader: "true", }), ports(nat.PortMap{ "80/tcp": {}, @@ -192,6 +195,7 @@ func TestSegmentBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -282,8 +286,10 @@ func TestSegmentBuildConfiguration(t *testing.T) { label.Prefix + "sauternes." + label.SuffixProtocol: "https", label.Prefix + "sauternes." + label.SuffixWeight: "12", + label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true", label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd", + label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestRemoveHeader: "true", label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsersFile: ".htpasswd", label.Prefix + "sauternes." + label.SuffixFrontendAuthForwardAddress: "auth.server", @@ -364,6 +370,7 @@ func TestSegmentBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/ecs/config_test.go b/provider/ecs/config_test.go index 57c0ecd85..2e0b620c7 100644 --- a/provider/ecs/config_test.go +++ b/provider/ecs/config_test.go @@ -114,9 +114,10 @@ func TestBuildConfiguration(t *testing.T) { ID: "1", containerDefinition: &ecs.ContainerDefinition{ DockerLabels: map[string]*string{ - label.TraefikFrontendAuthBasicUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - label.TraefikFrontendAuthBasicUsersFile: aws.String(".htpasswd"), - label.TraefikFrontendAuthHeaderField: aws.String("X-WebAuth-User"), + label.TraefikFrontendAuthBasicUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + label.TraefikFrontendAuthBasicUsersFile: aws.String(".htpasswd"), + label.TraefikFrontendAuthBasicRemoveHeader: aws.String("true"), + label.TraefikFrontendAuthHeaderField: aws.String("X-WebAuth-User"), }}, machine: &machine{ state: ec2.InstanceStateNameRunning, @@ -147,6 +148,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -212,9 +214,10 @@ func TestBuildConfiguration(t *testing.T) { ID: "1", containerDefinition: &ecs.ContainerDefinition{ DockerLabels: map[string]*string{ - label.TraefikFrontendAuthDigestUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), - label.TraefikFrontendAuthDigestUsersFile: aws.String(".htpasswd"), - label.TraefikFrontendAuthHeaderField: aws.String("X-WebAuth-User"), + label.TraefikFrontendAuthDigestRemoveHeader: aws.String("true"), + label.TraefikFrontendAuthDigestUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + label.TraefikFrontendAuthDigestUsersFile: aws.String(".htpasswd"), + label.TraefikFrontendAuthHeaderField: aws.String("X-WebAuth-User"), }}, machine: &machine{ state: ec2.InstanceStateNameRunning, @@ -245,6 +248,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -350,8 +354,10 @@ func TestBuildConfiguration(t *testing.T) { label.TraefikBackendBufferingRetryExpression: aws.String("IsNetworkError() && Attempts() <= 2"), label.TraefikFrontendAuthBasic: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + label.TraefikFrontendAuthBasicRemoveHeader: aws.String("true"), label.TraefikFrontendAuthBasicUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), label.TraefikFrontendAuthBasicUsersFile: aws.String(".htpasswd"), + label.TraefikFrontendAuthDigestRemoveHeader: aws.String("true"), label.TraefikFrontendAuthDigestUsers: aws.String("test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), label.TraefikFrontendAuthDigestUsersFile: aws.String(".htpasswd"), label.TraefikFrontendAuthForwardAddress: aws.String("auth.server"), @@ -481,6 +487,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/kubernetes/annotations.go b/provider/kubernetes/annotations.go index f56213704..4b716e395 100644 --- a/provider/kubernetes/annotations.go +++ b/provider/kubernetes/annotations.go @@ -11,6 +11,7 @@ const ( annotationKubernetesAuthSecret = "ingress.kubernetes.io/auth-secret" annotationKubernetesAuthHeaderField = "ingress.kubernetes.io/auth-header-field" annotationKubernetesAuthForwardResponseHeaders = "ingress.kubernetes.io/auth-response-headers" + annotationKubernetesAuthRemoveHeader = "ingress.kubernetes.io/auth-remove-header" annotationKubernetesAuthForwardURL = "ingress.kubernetes.io/auth-url" annotationKubernetesAuthForwardTrustHeaders = "ingress.kubernetes.io/auth-trust-headers" annotationKubernetesAuthForwardTLSSecret = "ingress.kubernetes.io/auth-tls-secret" diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index 085131488..d29e52309 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -737,7 +737,10 @@ func getBasicAuthConfig(i *extensionsv1beta1.Ingress, k8sClient Client) (*types. return nil, err } - return &types.Basic{Users: credentials}, nil + return &types.Basic{ + Users: credentials, + RemoveHeader: getBoolValue(i.Annotations, annotationKubernetesAuthRemoveHeader, false), + }, nil } func getDigestAuthConfig(i *extensionsv1beta1.Ingress, k8sClient Client) (*types.Digest, error) { @@ -746,7 +749,9 @@ func getDigestAuthConfig(i *extensionsv1beta1.Ingress, k8sClient Client) (*types return nil, err } - return &types.Digest{Users: credentials}, nil + return &types.Digest{Users: credentials, + RemoveHeader: getBoolValue(i.Annotations, annotationKubernetesAuthRemoveHeader, false), + }, nil } func getAuthCredentials(i *extensionsv1beta1.Ingress, k8sClient Client) ([]string, error) { diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index 2f473d91e..df1cc5953 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -2048,6 +2048,7 @@ func TestLoadIngressesBasicAuth(t *testing.T) { iNamespace("testing"), iAnnotation(annotationKubernetesAuthType, "basic"), iAnnotation(annotationKubernetesAuthSecret, "mySecret"), + iAnnotation(annotationKubernetesAuthRemoveHeader, "true"), iRules( iRule( iHost("basic"), @@ -2096,8 +2097,9 @@ func TestLoadIngressesBasicAuth(t *testing.T) { actual = provider.loadConfig(*actual) require.NotNil(t, actual) - got := actual.Frontends["basic/auth"].Auth.Basic.Users - assert.Equal(t, types.Users{"myUser:myEncodedPW"}, got) + actualBasicAuth := actual.Frontends["basic/auth"].Auth.Basic + assert.Equal(t, types.Users{"myUser:myEncodedPW"}, actualBasicAuth.Users) + assert.True(t, actualBasicAuth.RemoveHeader, "Bad RemoveHeader flag") } func TestLoadIngressesForwardAuth(t *testing.T) { diff --git a/provider/kv/keynames.go b/provider/kv/keynames.go index 7dfb292c2..27c1bdb4e 100644 --- a/provider/kv/keynames.go +++ b/provider/kv/keynames.go @@ -37,9 +37,11 @@ const ( pathFrontendBasicAuth = "/basicauth" // Deprecated pathFrontendAuth = "/auth/" pathFrontendAuthBasic = pathFrontendAuth + "basic/" + pathFrontendAuthBasicRemoveHeader = pathFrontendAuthBasic + "removeheader" pathFrontendAuthBasicUsers = pathFrontendAuthBasic + "users" pathFrontendAuthBasicUsersFile = pathFrontendAuthBasic + "usersfile" pathFrontendAuthDigest = pathFrontendAuth + "digest/" + pathFrontendAuthDigestRemoveHeader = pathFrontendAuthDigest + "removeheader" pathFrontendAuthDigestUsers = pathFrontendAuthDigest + "users" pathFrontendAuthDigestUsersFile = pathFrontendAuthDigest + "usersfile" pathFrontendAuthForward = pathFrontendAuth + "forward/" diff --git a/provider/kv/kv_config.go b/provider/kv/kv_config.go index d08878318..ed7680780 100644 --- a/provider/kv/kv_config.go +++ b/provider/kv/kv_config.go @@ -398,7 +398,8 @@ func (p *Provider) getAuth(rootPath string) *types.Auth { // getAuthBasic Create Basic Auth from path func (p *Provider) getAuthBasic(rootPath string) *types.Basic { basicAuth := &types.Basic{ - UsersFile: p.get("", rootPath, pathFrontendAuthBasicUsersFile), + UsersFile: p.get("", rootPath, pathFrontendAuthBasicUsersFile), + RemoveHeader: p.getBool(false, rootPath, pathFrontendAuthBasicRemoveHeader), } // backward compatibility @@ -415,8 +416,9 @@ func (p *Provider) getAuthBasic(rootPath string) *types.Basic { // getAuthDigest Create Digest Auth from path func (p *Provider) getAuthDigest(rootPath string) *types.Digest { return &types.Digest{ - Users: p.getList(rootPath, pathFrontendAuthDigestUsers), - UsersFile: p.get("", rootPath, pathFrontendAuthDigestUsersFile), + Users: p.getList(rootPath, pathFrontendAuthDigestUsers), + UsersFile: p.get("", rootPath, pathFrontendAuthDigestUsersFile), + RemoveHeader: p.getBool(false, rootPath, pathFrontendAuthDigestRemoveHeader), } } diff --git a/provider/kv/kv_config_test.go b/provider/kv/kv_config_test.go index b259ec5b7..e1f604d24 100644 --- a/provider/kv/kv_config_test.go +++ b/provider/kv/kv_config_test.go @@ -67,6 +67,7 @@ func TestProviderBuildConfiguration(t *testing.T) { frontend("frontend", withPair(pathFrontendBackend, "backend"), withPair(pathFrontendAuthHeaderField, "X-WebAuth-User"), + withPair(pathFrontendAuthBasicRemoveHeader, "true"), withList(pathFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), ), backend("backend"), @@ -87,6 +88,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, }, @@ -166,6 +168,7 @@ func TestProviderBuildConfiguration(t *testing.T) { frontend("frontend", withPair(pathFrontendBackend, "backend"), withPair(pathFrontendAuthHeaderField, "X-WebAuth-User"), + withPair(pathFrontendAuthDigestRemoveHeader, "true"), withList(pathFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withPair(pathFrontendAuthDigestUsersFile, ".htpasswd"), ), @@ -187,6 +190,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -279,8 +283,10 @@ func TestProviderBuildConfiguration(t *testing.T) { withPair(pathFrontendWhiteListUseXForwardedFor, "true"), withList(pathFrontendBasicAuth, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + withPair(pathFrontendAuthBasicRemoveHeader, "true"), withList(pathFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withPair(pathFrontendAuthBasicUsersFile, ".htpasswd"), + withPair(pathFrontendAuthDigestRemoveHeader, "true"), withList(pathFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withPair(pathFrontendAuthDigestUsersFile, ".htpasswd"), withPair(pathFrontendAuthForwardAddress, "auth.server"), @@ -398,6 +404,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -2157,12 +2164,14 @@ func TestProviderGetAuth(t *testing.T) { rootPath: "traefik/frontends/foo", kvPairs: filler("traefik", frontend("foo", + withPair(pathFrontendAuthBasicRemoveHeader, "true"), withList(pathFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withPair(pathFrontendAuthBasicUsersFile, ".htpasswd"), withPair(pathFrontendAuthHeaderField, "X-WebAuth-User"))), expected: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/label/names.go b/provider/label/names.go index ddb1aacaa..bafa49c61 100644 --- a/provider/label/names.go +++ b/provider/label/names.go @@ -37,9 +37,11 @@ const ( SuffixFrontend = "frontend" SuffixFrontendAuth = SuffixFrontend + ".auth" SuffixFrontendAuthBasic = SuffixFrontendAuth + ".basic" + SuffixFrontendAuthBasicRemoveHeader = SuffixFrontendAuthBasic + ".removeHeader" SuffixFrontendAuthBasicUsers = SuffixFrontendAuthBasic + ".users" SuffixFrontendAuthBasicUsersFile = SuffixFrontendAuthBasic + ".usersFile" SuffixFrontendAuthDigest = SuffixFrontendAuth + ".digest" + SuffixFrontendAuthDigestRemoveHeader = SuffixFrontendAuthDigest + ".removeHeader" SuffixFrontendAuthDigestUsers = SuffixFrontendAuthDigest + ".users" SuffixFrontendAuthDigestUsersFile = SuffixFrontendAuthDigest + ".usersFile" SuffixFrontendAuthForward = SuffixFrontendAuth + ".forward" @@ -123,9 +125,11 @@ const ( TraefikFrontend = Prefix + SuffixFrontend TraefikFrontendAuth = Prefix + SuffixFrontendAuth TraefikFrontendAuthBasic = Prefix + SuffixFrontendAuthBasic + TraefikFrontendAuthBasicRemoveHeader = Prefix + SuffixFrontendAuthBasicRemoveHeader TraefikFrontendAuthBasicUsers = Prefix + SuffixFrontendAuthBasicUsers TraefikFrontendAuthBasicUsersFile = Prefix + SuffixFrontendAuthBasicUsersFile TraefikFrontendAuthDigest = Prefix + SuffixFrontendAuthDigest + TraefikFrontendAuthDigestRemoveHeader = Prefix + SuffixFrontendAuthDigestRemoveHeader TraefikFrontendAuthDigestUsers = Prefix + SuffixFrontendAuthDigestUsers TraefikFrontendAuthDigestUsersFile = Prefix + SuffixFrontendAuthDigestUsersFile TraefikFrontendAuthForward = Prefix + SuffixFrontendAuthForward diff --git a/provider/label/partial.go b/provider/label/partial.go index 0723e6c57..aec443edd 100644 --- a/provider/label/partial.go +++ b/provider/label/partial.go @@ -84,7 +84,8 @@ func GetAuth(labels map[string]string) *types.Auth { // getAuthBasic Create Basic Auth from labels func getAuthBasic(labels map[string]string) *types.Basic { basicAuth := &types.Basic{ - UsersFile: GetStringValue(labels, TraefikFrontendAuthBasicUsersFile, ""), + UsersFile: GetStringValue(labels, TraefikFrontendAuthBasicUsersFile, ""), + RemoveHeader: GetBoolValue(labels, TraefikFrontendAuthBasicRemoveHeader, false), } // backward compatibility @@ -101,8 +102,9 @@ func getAuthBasic(labels map[string]string) *types.Basic { // getAuthDigest Create Digest Auth from labels func getAuthDigest(labels map[string]string) *types.Digest { return &types.Digest{ - Users: GetSliceStringValue(labels, TraefikFrontendAuthDigestUsers), - UsersFile: GetStringValue(labels, TraefikFrontendAuthDigestUsersFile, ""), + Users: GetSliceStringValue(labels, TraefikFrontendAuthDigestUsers), + UsersFile: GetStringValue(labels, TraefikFrontendAuthDigestUsersFile, ""), + RemoveHeader: GetBoolValue(labels, TraefikFrontendAuthDigestRemoveHeader, false), } } diff --git a/provider/label/partial_test.go b/provider/label/partial_test.go index f6d3f9998..796acfe15 100644 --- a/provider/label/partial_test.go +++ b/provider/label/partial_test.go @@ -735,25 +735,27 @@ func TestGetAuth(t *testing.T) { { desc: "should return a basic auth", labels: map[string]string{ - TraefikFrontendAuthHeaderField: "myHeaderField", - TraefikFrontendAuthBasicUsers: "user:pwd,user2:pwd2", - TraefikFrontendAuthBasicUsersFile: "myUsersFile", + TraefikFrontendAuthHeaderField: "myHeaderField", + TraefikFrontendAuthBasicUsers: "user:pwd,user2:pwd2", + TraefikFrontendAuthBasicUsersFile: "myUsersFile", + TraefikFrontendAuthBasicRemoveHeader: "true", }, expected: &types.Auth{ HeaderField: "myHeaderField", - Basic: &types.Basic{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}}, + Basic: &types.Basic{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}, RemoveHeader: true}, }, }, { desc: "should return a digest auth", labels: map[string]string{ - TraefikFrontendAuthHeaderField: "myHeaderField", - TraefikFrontendAuthDigestUsers: "user:pwd,user2:pwd2", - TraefikFrontendAuthDigestUsersFile: "myUsersFile", + TraefikFrontendAuthDigestRemoveHeader: "true", + TraefikFrontendAuthHeaderField: "myHeaderField", + TraefikFrontendAuthDigestUsers: "user:pwd,user2:pwd2", + TraefikFrontendAuthDigestUsersFile: "myUsersFile", }, expected: &types.Auth{ HeaderField: "myHeaderField", - Digest: &types.Digest{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}}, + Digest: &types.Digest{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}, RemoveHeader: true}, }, }, { diff --git a/provider/marathon/config_test.go b/provider/marathon/config_test.go index ae9ec6d2e..f6a5d3c9a 100644 --- a/provider/marathon/config_test.go +++ b/provider/marathon/config_test.go @@ -161,6 +161,7 @@ func TestBuildConfiguration(t *testing.T) { appID("/app"), appPorts(80), withLabel(label.TraefikFrontendAuthHeaderField, "X-WebAuth-User"), + withLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd"), withTasks(localhostTask(taskPorts(80))), @@ -176,6 +177,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -245,6 +247,7 @@ func TestBuildConfiguration(t *testing.T) { appID("/app"), appPorts(80), withLabel(label.TraefikFrontendAuthHeaderField, "X-WebAuth-User"), + withLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd"), withTasks(localhostTask(taskPorts(80))), @@ -260,6 +263,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -371,8 +375,10 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackendBufferingRetryExpression, "IsNetworkError() && Attempts() <= 2"), withLabel(label.TraefikFrontendAuthBasic, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + withLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd"), + withLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd"), withLabel(label.TraefikFrontendAuthForwardAddress, "auth.server"), @@ -452,6 +458,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -760,6 +767,21 @@ func TestBuildConfigurationSegments(t *testing.T) { withSegmentLabel(label.TraefikWeight, "12", "containous"), withSegmentLabel(label.TraefikFrontendAuthBasic, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), + withSegmentLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true", "containous"), + withSegmentLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), + withSegmentLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd", "containous"), + withSegmentLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true", "containous"), + withSegmentLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), + withSegmentLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardAddress, "auth.server", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTrustForwardHeader, "true", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTLSCa, "ca.crt", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTLSCaOptional, "true", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTLSCert, "server.crt", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTLSKey, "server.key", "containous"), + withSegmentLabel(label.TraefikFrontendAuthForwardTLSInsecureSkipVerify, "true", "containous"), + withSegmentLabel(label.TraefikFrontendAuthHeaderField, "X-WebAuth-User", "containous"), + withSegmentLabel(label.TraefikFrontendEntryPoints, "http,https", "containous"), withSegmentLabel(label.TraefikFrontendPassHostHeader, "true", "containous"), withSegmentLabel(label.TraefikFrontendPassTLSCert, "true", "containous"), @@ -826,9 +848,12 @@ func TestBuildConfigurationSegments(t *testing.T) { PassTLSCert: true, Priority: 666, Auth: &types.Auth{ + HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, + UsersFile: ".htpasswd", }, }, WhiteList: &types.WhiteList{ diff --git a/provider/mesos/config_test.go b/provider/mesos/config_test.go index 8f52baeab..6b5af71d7 100644 --- a/provider/mesos/config_test.go +++ b/provider/mesos/config_test.go @@ -121,6 +121,7 @@ func TestBuildConfiguration(t *testing.T) { withStatus(withHealthy(true), withState("TASK_RUNNING")), withLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd"), + withLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthHeaderField, "X-WebAuth-User"), ), }, @@ -137,6 +138,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -205,6 +207,7 @@ func TestBuildConfiguration(t *testing.T) { withInfo("name1", withPorts(withPort("TCP", 80, "WEB"))), withStatus(withHealthy(true), withState("TASK_RUNNING")), + withLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd"), withLabel(label.TraefikFrontendAuthHeaderField, "X-WebAuth-User"), @@ -223,6 +226,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -327,8 +331,10 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackendBufferingRetryExpression, "IsNetworkError() && Attempts() <= 2"), withLabel(label.TraefikFrontendAuthBasic, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), + withLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd"), + withLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true"), withLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"), withLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd"), withLabel(label.TraefikFrontendAuthForwardAddress, "auth.server"), @@ -414,6 +420,7 @@ func TestBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -678,8 +685,10 @@ func TestBuildConfigurationSegments(t *testing.T) { withSegmentLabel(label.TraefikWeight, "12", "containous"), withSegmentLabel(label.TraefikFrontendAuthBasic, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), + withSegmentLabel(label.TraefikFrontendAuthBasicRemoveHeader, "true", "containous"), withSegmentLabel(label.TraefikFrontendAuthBasicUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), withSegmentLabel(label.TraefikFrontendAuthBasicUsersFile, ".htpasswd", "containous"), + withSegmentLabel(label.TraefikFrontendAuthDigestRemoveHeader, "true", "containous"), withSegmentLabel(label.TraefikFrontendAuthDigestUsers, "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "containous"), withSegmentLabel(label.TraefikFrontendAuthDigestUsersFile, ".htpasswd", "containous"), withSegmentLabel(label.TraefikFrontendAuthForwardAddress, "auth.server", "containous"), @@ -760,6 +769,7 @@ func TestBuildConfigurationSegments(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/provider/rancher/config_test.go b/provider/rancher/config_test.go index 57c67ea81..600813e19 100644 --- a/provider/rancher/config_test.go +++ b/provider/rancher/config_test.go @@ -60,8 +60,10 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2", label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthBasicRemoveHeader: "true", label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthBasicUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", label.TraefikFrontendAuthForwardAddress: "auth.server", @@ -145,6 +147,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -289,8 +292,10 @@ func TestProviderBuildConfiguration(t *testing.T) { label.Prefix + "sauternes." + label.SuffixWeight: "12", label.Prefix + "sauternes." + label.SuffixFrontendRule: "Host:traefik.wtf", + label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true", label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd", + label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestRemoveHeader: "true", label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestUsersFile: ".htpasswd", label.Prefix + "sauternes." + label.SuffixFrontendAuthForwardAddress: "auth.server", @@ -370,6 +375,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Auth: &types.Auth{ HeaderField: "X-WebAuth-User", Basic: &types.Basic{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", @@ -564,9 +570,10 @@ func TestProviderBuildConfiguration(t *testing.T) { { Name: "test/service", Labels: map[string]string{ - label.TraefikPort: "80", - label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", - label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", + label.TraefikPort: "80", + label.TraefikFrontendAuthDigestUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", + label.TraefikFrontendAuthDigestUsersFile: ".htpasswd", + label.TraefikFrontendAuthDigestRemoveHeader: "true", }, Health: "healthy", Containers: []string{"127.0.0.1"}, @@ -579,6 +586,7 @@ func TestProviderBuildConfiguration(t *testing.T) { EntryPoints: []string{}, Auth: &types.Auth{ Digest: &types.Digest{ + RemoveHeader: true, Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, UsersFile: ".htpasswd", diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index 72ebb2357..c7105d55e 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -97,6 +97,7 @@ {{if $auth.Basic }} [frontends."frontend-{{ $service.ServiceName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -107,6 +108,7 @@ {{if $auth.Digest }} [frontends."frontend-{{ $service.ServiceName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/docker.tmpl b/templates/docker.tmpl index 0161ac058..ae01d9efe 100644 --- a/templates/docker.tmpl +++ b/templates/docker.tmpl @@ -97,6 +97,7 @@ {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -107,6 +108,7 @@ {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/ecs.tmpl b/templates/ecs.tmpl index 0e13c31f6..f230b120e 100644 --- a/templates/ecs.tmpl +++ b/templates/ecs.tmpl @@ -96,6 +96,7 @@ {{if $auth.Basic }} [frontends."frontend-{{ $serviceName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -106,6 +107,7 @@ {{if $auth.Digest }} [frontends."frontend-{{ $serviceName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/kubernetes.tmpl b/templates/kubernetes.tmpl index 011e3e25c..51c03a748 100644 --- a/templates/kubernetes.tmpl +++ b/templates/kubernetes.tmpl @@ -58,6 +58,7 @@ {{if $frontend.Auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{$frontend.Auth.Basic.RemoveHeader}} users = [{{range $frontend.Auth.Basic.Users }} "{{.}}", {{end}}] @@ -65,6 +66,7 @@ {{if $frontend.Auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{$frontend.Auth.Digest.RemoveHeader}} users = [{{range $frontend.Auth.Digest.Users }} "{{.}}", {{end}}] diff --git a/templates/kv.tmpl b/templates/kv.tmpl index 733a9cba2..03a5dd6e1 100644 --- a/templates/kv.tmpl +++ b/templates/kv.tmpl @@ -96,6 +96,7 @@ {{if $auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -106,6 +107,7 @@ {{if $auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index 379495ede..6b42630cb 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -99,6 +99,7 @@ {{if $auth.Basic }} [frontends."{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -109,6 +110,7 @@ {{if $auth.Digest }} [frontends."{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/mesos.tmpl b/templates/mesos.tmpl index 79b3af440..6337cee30 100644 --- a/templates/mesos.tmpl +++ b/templates/mesos.tmpl @@ -99,6 +99,7 @@ {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader}} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -109,6 +110,7 @@ {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader}} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/templates/rancher.tmpl b/templates/rancher.tmpl index 13384296b..0b4d38ecb 100644 --- a/templates/rancher.tmpl +++ b/templates/rancher.tmpl @@ -97,6 +97,7 @@ {{if $auth.Basic }} [frontends."frontend-{{ $frontendName }}".auth.basic] + removeHeader = {{ $auth.Basic.RemoveHeader }} {{if $auth.Basic.Users }} users = [{{range $auth.Basic.Users }} "{{.}}", @@ -107,6 +108,7 @@ {{if $auth.Digest }} [frontends."frontend-{{ $frontendName }}".auth.digest] + removeHeader = {{ $auth.Digest.RemoveHeader }} {{if $auth.Digest.Users }} users = [{{range $auth.Digest.Users }} "{{.}}", diff --git a/types/types.go b/types/types.go index 9c7e076d7..1b3c7b333 100644 --- a/types/types.go +++ b/types/types.go @@ -401,14 +401,16 @@ type Users []string // Basic HTTP basic authentication type Basic struct { - Users `mapstructure:","` - UsersFile string + Users `mapstructure:","` + UsersFile string + RemoveHeader bool } // Digest HTTP authentication type Digest struct { - Users `mapstructure:","` - UsersFile string + Users `mapstructure:","` + UsersFile string + RemoveHeader bool } // Forward authentication