diff --git a/docs/toml.md b/docs/toml.md index 189eea033..bda0cf8b6 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -607,7 +607,6 @@ If you want Træfik to watch file changes automatically, just add: watch = true ``` - ## API backend Træfik can be configured using a RESTful api. @@ -912,8 +911,9 @@ Labels can be used on containers to override default behaviour: - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.priority=10`: override default frontend priority - `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. -- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets a Basic Auth for that frontend with the users test:test and test2:test2 -- `traefik.frontend.whitelistSourceRange: "1.2.3.0/24, fe80::/16"`: List of IP-Ranges which are allowed to access. An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access.- `traefik.docker.network`: Set the docker network to use for connections to this container. If a container is linked to several networks, be sure to set the proper network name (you can check with docker inspect ) otherwise it will randomly pick one (depending on how docker is returning them). For instance when deploying docker `stack` from compose files, the compose defined networks will be prefixed with the `stack` name. +- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets basic authentication for that frontend with the usernames and passwords test:test and test2:test2, respectively +- `traefik.frontend.whitelistSourceRange: "1.2.3.0/24, fe80::/16"`: List of IP-Ranges which are allowed to access. An unset or empty list allows all Source-IPs to access. If one of the Net-Specifications are invalid, the whole list is invalid and allows all Source-IPs to access. +- `traefik.docker.network`: Set the docker network to use for connections to this container. If a container is linked to several networks, be sure to set the proper network name (you can check with docker inspect ) otherwise it will randomly pick one (depending on how docker is returning them). For instance when deploying docker `stack` from compose files, the compose defined networks will be prefixed with the `stack` name. If several ports need to be exposed from a container, the services labels can be used - `traefik..port=443`: create a service binding with frontend/backend using this port. Overrides `traefik.port`. @@ -1068,6 +1068,7 @@ Labels can be used on containers to override default behaviour: - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.priority=10`: override default frontend priority - `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. +- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets basic authentication for that frontend with the usernames and passwords test:test and test2:test2, respectively ## Mesos generic backend @@ -1768,7 +1769,7 @@ Labels can be used on task containers to override default behaviour: - `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. - `traefik.frontend.priority=10`: override default frontend priority - `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. -- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets a Basic Auth for that frontend with the users test:test and test2:test2 +- `traefik.frontend.auth.basic=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0`: Sets basic authentication for that frontend with the usernames and passwords test:test and test2:test2, respectively ## DynamoDB backend diff --git a/provider/marathon/marathon.go b/provider/marathon/marathon.go index 1bed45298..271209484 100644 --- a/provider/marathon/marathon.go +++ b/provider/marathon/marathon.go @@ -163,6 +163,7 @@ func (p *Provider) loadMarathonConfig() *types.Configuration { "hasHealthCheckLabels": p.hasHealthCheckLabels, "getHealthCheckPath": p.getHealthCheckPath, "getHealthCheckInterval": p.getHealthCheckInterval, + "getBasicAuth": p.getBasicAuth, } applications, err := p.marathonClient.Applications(nil) @@ -485,6 +486,14 @@ func (p *Provider) getHealthCheckInterval(application marathon.Application) stri return "" } +func (p *Provider) getBasicAuth(application marathon.Application) []string { + if basicAuth, ok := p.getLabel(application, "traefik.frontend.auth.basic"); ok { + return strings.Split(basicAuth, ",") + } + + return []string{} +} + func processPorts(application marathon.Application, task marathon.Task) (int, error) { if portLabel, ok := (*application.Labels)[labelPort]; ok { port, err := strconv.Atoi(portLabel) diff --git a/provider/marathon/marathon_test.go b/provider/marathon/marathon_test.go index f5fa363a8..2d6be08fa 100644 --- a/provider/marathon/marathon_test.go +++ b/provider/marathon/marathon_test.go @@ -98,6 +98,7 @@ func TestMarathonLoadConfig(t *testing.T) { `frontend-test`: { Backend: "backend-test", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-test`: { @@ -151,6 +152,7 @@ func TestMarathonLoadConfig(t *testing.T) { `frontend-testLoadBalancerAndCircuitBreaker.dot`: { Backend: "backend-testLoadBalancerAndCircuitBreaker.dot", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-testLoadBalancerAndCircuitBreaker.dot`: { @@ -209,6 +211,7 @@ func TestMarathonLoadConfig(t *testing.T) { `frontend-testMaxConn`: { Backend: "backend-testMaxConn", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-testMaxConn`: { @@ -264,6 +267,7 @@ func TestMarathonLoadConfig(t *testing.T) { `frontend-testMaxConnOnlySpecifyAmount`: { Backend: "backend-testMaxConnOnlySpecifyAmount", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-testMaxConnOnlySpecifyAmount`: { @@ -316,6 +320,7 @@ func TestMarathonLoadConfig(t *testing.T) { `frontend-testMaxConnOnlyExtractorFunc`: { Backend: "backend-testMaxConnOnlyExtractorFunc", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ `route-host-testMaxConnOnlyExtractorFunc`: { @@ -369,6 +374,7 @@ func TestMarathonLoadConfig(t *testing.T) { "frontend-testHealthCheck": { Backend: "backend-testHealthCheck", PassHostHeader: true, + BasicAuth: []string{}, EntryPoints: []string{}, Routes: map[string]types.Route{ "route-host-testHealthCheck": { @@ -1368,7 +1374,7 @@ func TestMarathonGetEntryPoints(t *testing.T) { for _, a := range applications { actual := provider.getEntryPoints(a.application) - if !reflect.DeepEqual(actual, a.expected) { + if !reflect.DeepEqual(a.expected, actual) { t.Fatalf("expected %#v, got %#v", a.expected, actual) } } @@ -1800,3 +1806,41 @@ func TestParseIndex(t *testing.T) { }) } } + +func TestMarathonGetBasicAuth(t *testing.T) { + provider := &Provider{} + + cases := []struct { + desc string + application marathon.Application + expected []string + }{ + { + desc: "basic auth label is empty", + application: marathon.Application{ + Labels: &map[string]string{}}, + expected: []string{}, + }, + { + desc: "basic auth label is set with user:password", + application: marathon.Application{ + Labels: &map[string]string{ + "traefik.frontend.auth.basic": "user:password", + }, + }, + expected: []string{"user:password"}, + }, + } + + for _, c := range cases { + c := c + t.Run(c.desc, func(t *testing.T) { + t.Parallel() + + actual := provider.getBasicAuth(c.application) + if !reflect.DeepEqual(c.expected, actual) { + t.Errorf("expected %q, got %q", c.expected, actual) + } + }) + } +} diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index 97243b284..6143b6ed4 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -34,6 +34,9 @@ priority = {{getPriority .}} entryPoints = [{{range getEntryPoints .}} "{{.}}", + {{end}}] + basicAuth = [{{range getBasicAuth .}} + "{{.}}", {{end}}] [frontends."frontend{{.ID | replace "/" "-"}}".routes."route-host{{.ID | replace "/" "-"}}"] rule = "{{getFrontendRule .}}"