Basic Auth custom realm
This commit is contained in:
parent
f9689d1562
commit
1431ac5751
15 changed files with 90 additions and 3 deletions
|
@ -444,6 +444,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}}
|
||||||
|
|
||||||
{{if $auth.Basic }}
|
{{if $auth.Basic }}
|
||||||
[frontends."frontend-{{ $frontendName }}".auth.basic]
|
[frontends."frontend-{{ $frontendName }}".auth.basic]
|
||||||
|
realm = "{{ $auth.Basic.Realm }}"
|
||||||
removeHeader = {{ $auth.Basic.RemoveHeader }}
|
removeHeader = {{ $auth.Basic.RemoveHeader }}
|
||||||
{{if $auth.Basic.Users }}
|
{{if $auth.Basic.Users }}
|
||||||
users = [{{range $auth.Basic.Users }}
|
users = [{{range $auth.Basic.Users }}
|
||||||
|
|
|
@ -121,6 +121,7 @@ func makeEntryPointAuth(result map[string]string) *types.Auth {
|
||||||
var basic *types.Basic
|
var basic *types.Basic
|
||||||
if v, ok := result["auth_basic_users"]; ok {
|
if v, ok := result["auth_basic_users"]; ok {
|
||||||
basic = &types.Basic{
|
basic = &types.Basic{
|
||||||
|
Realm: result["auth_basic_realm"],
|
||||||
Users: strings.Split(v, ","),
|
Users: strings.Split(v, ","),
|
||||||
RemoveHeader: toBool(result, "auth_basic_removeheader"),
|
RemoveHeader: toBool(result, "auth_basic_removeheader"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
|
||||||
"Compress:true " +
|
"Compress:true " +
|
||||||
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
|
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
|
||||||
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
||||||
|
"Auth.Basic.Realm:myRealm " +
|
||||||
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
||||||
"Auth.Basic.RemoveHeader:true " +
|
"Auth.Basic.RemoveHeader:true " +
|
||||||
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
||||||
|
@ -52,6 +53,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
|
||||||
"ClientIPStrategy.ExcludedIPs:10.0.0.3/24,20.0.0.3/24 ",
|
"ClientIPStrategy.ExcludedIPs:10.0.0.3/24,20.0.0.3/24 ",
|
||||||
expectedResult: map[string]string{
|
expectedResult: map[string]string{
|
||||||
"address": ":8000",
|
"address": ":8000",
|
||||||
|
"auth_basic_realm": "myRealm",
|
||||||
"auth_basic_users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
"auth_basic_users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
"auth_basic_removeheader": "true",
|
"auth_basic_removeheader": "true",
|
||||||
"auth_digest_users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
|
"auth_digest_users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
|
||||||
|
@ -197,6 +199,7 @@ func TestEntryPoints_Set(t *testing.T) {
|
||||||
"Compress:true " +
|
"Compress:true " +
|
||||||
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
|
"ProxyProtocol.TrustedIPs:192.168.0.1 " +
|
||||||
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
"ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
||||||
|
"Auth.Basic.Realm:myRealm " +
|
||||||
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
"Auth.Basic.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
||||||
"Auth.Basic.RemoveHeader:true " +
|
"Auth.Basic.RemoveHeader:true " +
|
||||||
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
"Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
||||||
|
@ -244,6 +247,7 @@ func TestEntryPoints_Set(t *testing.T) {
|
||||||
},
|
},
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
|
Realm: "myRealm",
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
Users: types.Users{
|
Users: types.Users{
|
||||||
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
|
@ -324,6 +328,7 @@ func TestEntryPoints_Set(t *testing.T) {
|
||||||
"whiteList.sourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
|
"whiteList.sourceRange:10.42.0.0/16,152.89.1.33/32,afed:be44::/16 " +
|
||||||
"proxyProtocol.TrustedIPs:192.168.0.1 " +
|
"proxyProtocol.TrustedIPs:192.168.0.1 " +
|
||||||
"forwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
"forwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24 " +
|
||||||
|
"auth.basic.realm:myRealm " +
|
||||||
"auth.basic.users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
"auth.basic.users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 " +
|
||||||
"auth.digest.users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
"auth.digest.users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e " +
|
||||||
"auth.headerField:X-WebAuth-User " +
|
"auth.headerField:X-WebAuth-User " +
|
||||||
|
@ -364,6 +369,7 @@ func TestEntryPoints_Set(t *testing.T) {
|
||||||
},
|
},
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
|
Realm: "myRealm",
|
||||||
Users: types.Users{
|
Users: types.Users{
|
||||||
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
|
|
|
@ -236,6 +236,7 @@ Labels can be used on containers to override default behavior.
|
||||||
| `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.<br>Must be used in conjunction with the below label to take effect. |
|
| `traefik.backend.maxconn.amount=10` | Sets a maximum number of connections to the backend.<br>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.<br>Must be used in conjunction with the above 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.<br>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=EXPR` | Sets the basic authentication to this frontend in CSV format: `User:Hash,User:Hash` [2] (DEPRECATED). |
|
||||||
|
| `traefik.frontend.auth.basic.realm=REALM` | Sets the realm of basic authentication to this frontend. |
|
||||||
| `traefik.frontend.auth.basic.removeHeader=true` | If set to `true`, removes the `Authorization` header. |
|
| `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.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.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. |
|
||||||
|
|
|
@ -52,6 +52,7 @@ defaultEntryPoints = ["http", "https"]
|
||||||
headerField = "X-WebAuth-User"
|
headerField = "X-WebAuth-User"
|
||||||
[entryPoints.http.auth.basic]
|
[entryPoints.http.auth.basic]
|
||||||
removeHeader = true
|
removeHeader = true
|
||||||
|
realm = "Your realm"
|
||||||
users = [
|
users = [
|
||||||
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
|
@ -143,6 +144,7 @@ ProxyProtocol.Insecure:true
|
||||||
ForwardedHeaders.TrustedIPs:10.0.0.3/24,20.0.0.3/24
|
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.Users:test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
|
||||||
Auth.Basic.Removeheader:true
|
Auth.Basic.Removeheader:true
|
||||||
|
Auth.Basic.Realm:traefik
|
||||||
Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
Auth.Digest.Users:test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
||||||
Auth.Digest.Removeheader:true
|
Auth.Digest.Removeheader:true
|
||||||
Auth.HeaderField:X-WebAuth-User
|
Auth.HeaderField:X-WebAuth-User
|
||||||
|
@ -290,6 +292,18 @@ Users can be specified directly in the TOML file, or indirectly by referencing a
|
||||||
|
|
||||||
Optionally, you can:
|
Optionally, you can:
|
||||||
|
|
||||||
|
- customize the realm
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":80"
|
||||||
|
[entryPoints.http.auth]
|
||||||
|
[entryPoints.http.auth.basic]
|
||||||
|
realm = "Your realm"
|
||||||
|
users = ["test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"]
|
||||||
|
```
|
||||||
|
|
||||||
- pass authenticated user to application via headers
|
- pass authenticated user to application via headers
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
|
@ -45,8 +45,11 @@ func NewAuthenticator(authConfig *types.Auth, tracingMiddleware *tracing.Tracing
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
realm := "traefik"
|
||||||
basicAuth := goauth.NewBasicAuthenticator("traefik", authenticator.secretBasic)
|
if authConfig.Basic.Realm != "" {
|
||||||
|
realm = authConfig.Basic.Realm
|
||||||
|
}
|
||||||
|
basicAuth := goauth.NewBasicAuthenticator(realm, authenticator.secretBasic)
|
||||||
tracingAuth.handler = createAuthBasicHandler(basicAuth, authConfig)
|
tracingAuth.handler = createAuthBasicHandler(basicAuth, authConfig)
|
||||||
tracingAuth.name = "Auth Basic"
|
tracingAuth.name = "Auth Basic"
|
||||||
tracingAuth.clientSpanKind = false
|
tracingAuth.clientSpanKind = false
|
||||||
|
|
|
@ -129,6 +129,49 @@ func TestBasicAuthSuccess(t *testing.T) {
|
||||||
assert.Equal(t, "traefik\n", string(body), "they should be equal")
|
assert.Equal(t, "traefik\n", string(body), "they should be equal")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBasicRealm(t *testing.T) {
|
||||||
|
authMiddlewareDefaultRealm, errdefault := NewAuthenticator(&types.Auth{
|
||||||
|
Basic: &types.Basic{
|
||||||
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"},
|
||||||
|
},
|
||||||
|
}, &tracing.Tracing{})
|
||||||
|
require.NoError(t, errdefault)
|
||||||
|
|
||||||
|
authMiddlewareCustomRealm, errcustom := NewAuthenticator(&types.Auth{
|
||||||
|
Basic: &types.Basic{
|
||||||
|
Realm: "foobar",
|
||||||
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"},
|
||||||
|
},
|
||||||
|
}, &tracing.Tracing{})
|
||||||
|
require.NoError(t, errcustom)
|
||||||
|
|
||||||
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintln(w, "traefik")
|
||||||
|
})
|
||||||
|
|
||||||
|
n := negroni.New(authMiddlewareDefaultRealm)
|
||||||
|
n.UseHandler(handler)
|
||||||
|
ts := httptest.NewServer(n)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
req := testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil)
|
||||||
|
res, err := client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "Basic realm=\"traefik\"", res.Header.Get("Www-Authenticate"), "they should be equal")
|
||||||
|
|
||||||
|
n = negroni.New(authMiddlewareCustomRealm)
|
||||||
|
n.UseHandler(handler)
|
||||||
|
ts = httptest.NewServer(n)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
client = &http.Client{}
|
||||||
|
req = testhelpers.MustNewRequest(http.MethodGet, ts.URL, nil)
|
||||||
|
res, err = client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "Basic realm=\"foobar\"", res.Header.Get("Www-Authenticate"), "they should be equal")
|
||||||
|
}
|
||||||
|
|
||||||
func TestDigestAuthFail(t *testing.T) {
|
func TestDigestAuthFail(t *testing.T) {
|
||||||
_, err := NewAuthenticator(&types.Auth{
|
_, err := NewAuthenticator(&types.Auth{
|
||||||
Digest: &types.Digest{
|
Digest: &types.Digest{
|
||||||
|
|
|
@ -72,6 +72,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
|
||||||
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
||||||
|
label.TraefikFrontendAuthBasicRealm: "myRealm",
|
||||||
}),
|
}),
|
||||||
ports(nat.PortMap{
|
ports(nat.PortMap{
|
||||||
"80/tcp": {},
|
"80/tcp": {},
|
||||||
|
@ -87,6 +88,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
|
Realm: "myRealm",
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
UsersFile: ".htpasswd",
|
UsersFile: ".htpasswd",
|
||||||
|
@ -463,6 +465,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
|
||||||
label.TraefikFrontendPassTLSClientCertInfosSubjectSerialNumber: "true",
|
label.TraefikFrontendPassTLSClientCertInfosSubjectSerialNumber: "true",
|
||||||
|
|
||||||
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.TraefikFrontendAuthBasic: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
|
label.TraefikFrontendAuthBasicRealm: "myRealm",
|
||||||
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
||||||
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
|
@ -569,6 +572,7 @@ func TestDockerBuildConfiguration(t *testing.T) {
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
HeaderField: "X-WebAuth-User",
|
HeaderField: "X-WebAuth-User",
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
|
Realm: "myRealm",
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
|
|
|
@ -167,6 +167,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
|
||||||
serviceLabels(map[string]string{
|
serviceLabels(map[string]string{
|
||||||
label.TraefikPort: "80",
|
label.TraefikPort: "80",
|
||||||
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
|
label.TraefikFrontendAuthBasicRealm: "myRealm",
|
||||||
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
||||||
}),
|
}),
|
||||||
|
@ -181,6 +182,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
|
||||||
EntryPoints: []string{},
|
EntryPoints: []string{},
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
|
Realm: "myRealm",
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
|
@ -400,6 +402,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
|
||||||
label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2",
|
label.TraefikBackendBufferingRetryExpression: "IsNetworkError() && Attempts() <= 2",
|
||||||
|
|
||||||
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
label.TraefikFrontendAuthBasicRemoveHeader: "true",
|
||||||
|
label.TraefikFrontendAuthBasicRealm: "myRealm",
|
||||||
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.TraefikFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
label.TraefikFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
label.TraefikFrontendAuthDigestRemoveHeader: "true",
|
label.TraefikFrontendAuthDigestRemoveHeader: "true",
|
||||||
|
@ -487,6 +490,7 @@ func TestSwarmBuildConfiguration(t *testing.T) {
|
||||||
Auth: &types.Auth{
|
Auth: &types.Auth{
|
||||||
HeaderField: "X-WebAuth-User",
|
HeaderField: "X-WebAuth-User",
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
|
Realm: "myRealm",
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
|
|
|
@ -139,6 +139,7 @@ func TestSegmentBuildConfiguration(t *testing.T) {
|
||||||
"traefik.sauternes.port": "2503",
|
"traefik.sauternes.port": "2503",
|
||||||
"traefik.sauternes.frontend.entryPoints": "http,https",
|
"traefik.sauternes.frontend.entryPoints": "http,https",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthHeaderField: "X-WebAuth-User",
|
||||||
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRealm: "myRealm",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true",
|
||||||
|
@ -163,6 +164,7 @@ func TestSegmentBuildConfiguration(t *testing.T) {
|
||||||
HeaderField: "X-WebAuth-User",
|
HeaderField: "X-WebAuth-User",
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
|
Realm: "myRealm",
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
UsersFile: ".htpasswd",
|
UsersFile: ".htpasswd",
|
||||||
|
@ -363,6 +365,7 @@ func TestSegmentBuildConfiguration(t *testing.T) {
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendPassTLSClientCertInfosSubjectSerialNumber: "true",
|
label.Prefix + "sauternes." + label.SuffixFrontendPassTLSClientCertInfosSubjectSerialNumber: "true",
|
||||||
|
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRemoveHeader: "true",
|
||||||
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicRealm: "myRealm",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsers: "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthBasicUsersFile: ".htpasswd",
|
||||||
label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestRemoveHeader: "true",
|
label.Prefix + "sauternes." + label.SuffixFrontendAuthDigestRemoveHeader: "true",
|
||||||
|
@ -464,6 +467,7 @@ func TestSegmentBuildConfiguration(t *testing.T) {
|
||||||
HeaderField: "X-WebAuth-User",
|
HeaderField: "X-WebAuth-User",
|
||||||
Basic: &types.Basic{
|
Basic: &types.Basic{
|
||||||
RemoveHeader: true,
|
RemoveHeader: true,
|
||||||
|
Realm: "myRealm",
|
||||||
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
Users: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
|
||||||
UsersFile: ".htpasswd",
|
UsersFile: ".htpasswd",
|
||||||
|
|
|
@ -37,6 +37,7 @@ const (
|
||||||
SuffixFrontend = "frontend"
|
SuffixFrontend = "frontend"
|
||||||
SuffixFrontendAuth = SuffixFrontend + ".auth"
|
SuffixFrontendAuth = SuffixFrontend + ".auth"
|
||||||
SuffixFrontendAuthBasic = SuffixFrontendAuth + ".basic"
|
SuffixFrontendAuthBasic = SuffixFrontendAuth + ".basic"
|
||||||
|
SuffixFrontendAuthBasicRealm = SuffixFrontendAuthBasic + ".realm"
|
||||||
SuffixFrontendAuthBasicRemoveHeader = SuffixFrontendAuthBasic + ".removeHeader"
|
SuffixFrontendAuthBasicRemoveHeader = SuffixFrontendAuthBasic + ".removeHeader"
|
||||||
SuffixFrontendAuthBasicUsers = SuffixFrontendAuthBasic + ".users"
|
SuffixFrontendAuthBasicUsers = SuffixFrontendAuthBasic + ".users"
|
||||||
SuffixFrontendAuthBasicUsersFile = SuffixFrontendAuthBasic + ".usersFile"
|
SuffixFrontendAuthBasicUsersFile = SuffixFrontendAuthBasic + ".usersFile"
|
||||||
|
@ -139,6 +140,7 @@ const (
|
||||||
TraefikFrontend = Prefix + SuffixFrontend
|
TraefikFrontend = Prefix + SuffixFrontend
|
||||||
TraefikFrontendAuth = Prefix + SuffixFrontendAuth
|
TraefikFrontendAuth = Prefix + SuffixFrontendAuth
|
||||||
TraefikFrontendAuthBasic = Prefix + SuffixFrontendAuthBasic
|
TraefikFrontendAuthBasic = Prefix + SuffixFrontendAuthBasic
|
||||||
|
TraefikFrontendAuthBasicRealm = Prefix + SuffixFrontendAuthBasicRealm
|
||||||
TraefikFrontendAuthBasicRemoveHeader = Prefix + SuffixFrontendAuthBasicRemoveHeader
|
TraefikFrontendAuthBasicRemoveHeader = Prefix + SuffixFrontendAuthBasicRemoveHeader
|
||||||
TraefikFrontendAuthBasicUsers = Prefix + SuffixFrontendAuthBasicUsers
|
TraefikFrontendAuthBasicUsers = Prefix + SuffixFrontendAuthBasicUsers
|
||||||
TraefikFrontendAuthBasicUsersFile = Prefix + SuffixFrontendAuthBasicUsersFile
|
TraefikFrontendAuthBasicUsersFile = Prefix + SuffixFrontendAuthBasicUsersFile
|
||||||
|
|
|
@ -119,6 +119,7 @@ func GetAuth(labels map[string]string) *types.Auth {
|
||||||
// getAuthBasic Create Basic Auth from labels
|
// getAuthBasic Create Basic Auth from labels
|
||||||
func getAuthBasic(labels map[string]string) *types.Basic {
|
func getAuthBasic(labels map[string]string) *types.Basic {
|
||||||
basicAuth := &types.Basic{
|
basicAuth := &types.Basic{
|
||||||
|
Realm: GetStringValue(labels, TraefikFrontendAuthBasicRealm, ""),
|
||||||
UsersFile: GetStringValue(labels, TraefikFrontendAuthBasicUsersFile, ""),
|
UsersFile: GetStringValue(labels, TraefikFrontendAuthBasicUsersFile, ""),
|
||||||
RemoveHeader: GetBoolValue(labels, TraefikFrontendAuthBasicRemoveHeader, false),
|
RemoveHeader: GetBoolValue(labels, TraefikFrontendAuthBasicRemoveHeader, false),
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,13 +756,14 @@ func TestGetAuth(t *testing.T) {
|
||||||
desc: "should return a basic auth",
|
desc: "should return a basic auth",
|
||||||
labels: map[string]string{
|
labels: map[string]string{
|
||||||
TraefikFrontendAuthHeaderField: "myHeaderField",
|
TraefikFrontendAuthHeaderField: "myHeaderField",
|
||||||
|
TraefikFrontendAuthBasicRealm: "myRealm",
|
||||||
TraefikFrontendAuthBasicUsers: "user:pwd,user2:pwd2",
|
TraefikFrontendAuthBasicUsers: "user:pwd,user2:pwd2",
|
||||||
TraefikFrontendAuthBasicUsersFile: "myUsersFile",
|
TraefikFrontendAuthBasicUsersFile: "myUsersFile",
|
||||||
TraefikFrontendAuthBasicRemoveHeader: "true",
|
TraefikFrontendAuthBasicRemoveHeader: "true",
|
||||||
},
|
},
|
||||||
expected: &types.Auth{
|
expected: &types.Auth{
|
||||||
HeaderField: "myHeaderField",
|
HeaderField: "myHeaderField",
|
||||||
Basic: &types.Basic{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}, RemoveHeader: true},
|
Basic: &types.Basic{UsersFile: "myUsersFile", Users: []string{"user:pwd", "user2:pwd2"}, RemoveHeader: true, Realm: "myRealm"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -120,6 +120,7 @@
|
||||||
|
|
||||||
{{if $auth.Basic }}
|
{{if $auth.Basic }}
|
||||||
[frontends."frontend-{{ $frontendName }}".auth.basic]
|
[frontends."frontend-{{ $frontendName }}".auth.basic]
|
||||||
|
realm = "{{ $auth.Basic.Realm }}"
|
||||||
removeHeader = {{ $auth.Basic.RemoveHeader }}
|
removeHeader = {{ $auth.Basic.RemoveHeader }}
|
||||||
{{if $auth.Basic.Users }}
|
{{if $auth.Basic.Users }}
|
||||||
users = [{{range $auth.Basic.Users }}
|
users = [{{range $auth.Basic.Users }}
|
||||||
|
|
|
@ -401,6 +401,7 @@ type Users []string
|
||||||
|
|
||||||
// Basic HTTP basic authentication
|
// Basic HTTP basic authentication
|
||||||
type Basic struct {
|
type Basic struct {
|
||||||
|
Realm string `json:"realm,omitempty"`
|
||||||
Users `json:"users,omitempty" mapstructure:","`
|
Users `json:"users,omitempty" mapstructure:","`
|
||||||
UsersFile string `json:"usersFile,omitempty"`
|
UsersFile string `json:"usersFile,omitempty"`
|
||||||
RemoveHeader bool `json:"removeHeader,omitempty"`
|
RemoveHeader bool `json:"removeHeader,omitempty"`
|
||||||
|
|
Loading…
Reference in a new issue