From bd93e224deb434b4cd8ffe5c85e52c8b0f54f57a Mon Sep 17 00:00:00 2001 From: July <985492783@qq.com> Date: Thu, 1 Aug 2024 20:26:04 +0800 Subject: [PATCH] Support HTTP BasicAuth for docker and swarm endpoint --- docs/content/providers/docker.md | 95 +++++++++++++++++++ docs/content/providers/swarm.md | 95 +++++++++++++++++++ .../reference/static-configuration/cli-ref.md | 12 +++ .../reference/static-configuration/env-ref.md | 12 +++ .../reference/static-configuration/file.toml | 4 + .../reference/static-configuration/file.yaml | 4 + pkg/provider/docker/shared.go | 6 ++ 7 files changed, 228 insertions(+) diff --git a/docs/content/providers/docker.md b/docs/content/providers/docker.md index e9cf20a09..f5d9a737b 100644 --- a/docs/content/providers/docker.md +++ b/docs/content/providers/docker.md @@ -134,6 +134,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`] - Accounting at container level, by exposing the socket on a another container than Traefik's. - Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process). - SSH public key authentication (SSH is supported with Docker > 18.09) + - Authentication using HTTP Basic authentication through an HTTP proxy that exposes the Docker daemon socket. ??? info "More Resources and Examples" @@ -216,6 +217,50 @@ See the [Docker API Access](#docker-api-access) section for more information. # ... ``` +??? example "Using HTTP" + + Using Docker Engine API you can connect Traefik to remote daemon using HTTP. + + ```yaml tab="File (YAML)" + providers: + docker: + endpoint: "http://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "http://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.endpoint=http://127.0.0.1:2375 + # ... + ``` + +??? example "Using TCP" + + Using Docker Engine API you can connect Traefik to remote daemon using TCP. + + ```yaml tab="File (YAML)" + providers: + docker: + endpoint: "tcp://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.docker] + endpoint = "tcp://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.docker.endpoint=tcp://127.0.0.1:2375 + # ... + ``` + ```yaml tab="File (YAML)" providers: docker: @@ -231,6 +276,56 @@ providers: --providers.docker.endpoint=unix:///var/run/docker.sock ``` +### `username` + +_Optional, Default=""_ + +Defines the username for Basic HTTP authentication. +This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. + +```yaml tab="File (YAML)" +providers: + docker: + username: foo + # ... +``` + +```toml tab="File (TOML)" +[providers.docker] + username = "foo" + # ... +``` + +```bash tab="CLI" +--providers.docker.username="foo" +# ... +``` + +### `password` + +_Optional, Default=""_ + +Defines the password for Basic HTTP authentication. +This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. + +```yaml tab="File (YAML)" +providers: + docker: + password: foo + # ... +``` + +```toml tab="File (TOML)" +[providers.docker] + password = "foo" + # ... +``` + +```bash tab="CLI" +--providers.docker.password="foo" +# ... +``` + ### `useBindPortIP` _Optional, Default=false_ diff --git a/docs/content/providers/swarm.md b/docs/content/providers/swarm.md index 8e790c203..427e54af9 100644 --- a/docs/content/providers/swarm.md +++ b/docs/content/providers/swarm.md @@ -151,6 +151,7 @@ You can specify which Docker API Endpoint to use with the directive [`endpoint`] It allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes. - Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process). - SSH public key authentication (SSH is supported with Docker > 18.09) + - Authentication using HTTP Basic authentication through an HTTP proxy that exposes the Docker daemon socket. ??? info "More Resources and Examples" @@ -262,6 +263,50 @@ See the [Docker Swarm API Access](#docker-api-access) section for more informati # ... ``` +??? example "Using HTTP" + + Using Docker Engine API you can connect Traefik to remote daemon using HTTP. + + ```yaml tab="File (YAML)" + providers: + swarm: + endpoint: "http://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.swarm] + swarm = "http://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.swarm.endpoint=http://127.0.0.1:2375 + # ... + ``` + +??? example "Using TCP" + + Using Docker Engine API you can connect Traefik to remote daemon using TCP. + + ```yaml tab="File (YAML)" + providers: + swarm: + endpoint: "tcp://127.0.0.1:2375" + # ... + ``` + + ```toml tab="File (TOML)" + [providers.swarm] + swarm = "tcp://127.0.0.1:2375" + # ... + ``` + + ```bash tab="CLI" + --providers.swarm.endpoint=tcp://127.0.0.1:2375 + # ... + ``` + ```yaml tab="File (YAML)" providers: swarm: @@ -277,6 +322,56 @@ providers: --providers.swarm.endpoint=unix:///var/run/docker.sock ``` +### `username` + +_Optional, Default=""_ + +Defines the username for Basic HTTP authentication. +This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. + +```yaml tab="File (YAML)" +providers: + swarm: + username: foo + # ... +``` + +```toml tab="File (TOML)" +[providers.swarm] + username = "foo" + # ... +``` + +```bash tab="CLI" +--providers.swarm.username="foo" +# ... +``` + +### `password` + +_Optional, Default=""_ + +Defines the password for Basic HTTP authentication. +This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. + +```yaml tab="File (YAML)" +providers: + swarm: + password: foo + # ... +``` + +```toml tab="File (TOML)" +[providers.swarm] + password = "foo" + # ... +``` + +```bash tab="CLI" +--providers.swarm.password="foo" +# ... +``` + ### `useBindPortIP` _Optional, Default=false_ diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index a261ffa27..ed7730922 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -591,6 +591,9 @@ Client timeout for HTTP connections. (Default: ```0```) `--providers.docker.network`: Default Docker network used. +`--providers.docker.password`: +Password for Basic HTTP authentication. + `--providers.docker.tls.ca`: TLS CA @@ -606,6 +609,9 @@ TLS key `--providers.docker.usebindportip`: Use the ip address from the bound port, rather than from the inner network. (Default: ```false```) +`--providers.docker.username`: +Username for Basic HTTP authentication. + `--providers.docker.watch`: Watch Docker events. (Default: ```true```) @@ -969,6 +975,9 @@ Client timeout for HTTP connections. (Default: ```0```) `--providers.swarm.network`: Default Docker network used. +`--providers.swarm.password`: +Password for Basic HTTP authentication. + `--providers.swarm.refreshseconds`: Polling interval for swarm mode. (Default: ```15```) @@ -987,6 +996,9 @@ TLS key `--providers.swarm.usebindportip`: Use the ip address from the bound port, rather than from the inner network. (Default: ```false```) +`--providers.swarm.username`: +Username for Basic HTTP authentication. + `--providers.swarm.watch`: Watch Docker events. (Default: ```true```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 43882e52f..e8ca837f3 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -591,6 +591,9 @@ Client timeout for HTTP connections. (Default: ```0```) `TRAEFIK_PROVIDERS_DOCKER_NETWORK`: Default Docker network used. +`TRAEFIK_PROVIDERS_DOCKER_PASSWORD`: +Password for Basic HTTP authentication. + `TRAEFIK_PROVIDERS_DOCKER_TLS_CA`: TLS CA @@ -606,6 +609,9 @@ TLS key `TRAEFIK_PROVIDERS_DOCKER_USEBINDPORTIP`: Use the ip address from the bound port, rather than from the inner network. (Default: ```false```) +`TRAEFIK_PROVIDERS_DOCKER_USERNAME`: +Username for Basic HTTP authentication. + `TRAEFIK_PROVIDERS_DOCKER_WATCH`: Watch Docker events. (Default: ```true```) @@ -969,6 +975,9 @@ Client timeout for HTTP connections. (Default: ```0```) `TRAEFIK_PROVIDERS_SWARM_NETWORK`: Default Docker network used. +`TRAEFIK_PROVIDERS_SWARM_PASSWORD`: +Password for Basic HTTP authentication. + `TRAEFIK_PROVIDERS_SWARM_REFRESHSECONDS`: Polling interval for swarm mode. (Default: ```15```) @@ -987,6 +996,9 @@ TLS key `TRAEFIK_PROVIDERS_SWARM_USEBINDPORTIP`: Use the ip address from the bound port, rather than from the inner network. (Default: ```false```) +`TRAEFIK_PROVIDERS_SWARM_USERNAME`: +Username for Basic HTTP authentication. + `TRAEFIK_PROVIDERS_SWARM_WATCH`: Watch Docker events. (Default: ```true```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index f171b9e86..13b5db3b9 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -85,6 +85,8 @@ useBindPortIP = true watch = true defaultRule = "foobar" + username = "foobar" + password = "foobar" endpoint = "foobar" httpClientTimeout = "42s" [providers.docker.tls] @@ -100,6 +102,8 @@ useBindPortIP = true watch = true defaultRule = "foobar" + username = "foobar" + password = "foobar" endpoint = "foobar" httpClientTimeout = "42s" refreshSeconds = "42s" diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 1c053dfaf..8fa68dada 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -96,6 +96,8 @@ providers: useBindPortIP: true watch: true defaultRule: foobar + username: foobar + password: foobar endpoint: foobar tls: ca: foobar @@ -111,6 +113,8 @@ providers: useBindPortIP: true watch: true defaultRule: foobar + username: foobar + password: foobar endpoint: foobar tls: ca: foobar diff --git a/pkg/provider/docker/shared.go b/pkg/provider/docker/shared.go index 74bcc62a1..98885b7c3 100644 --- a/pkg/provider/docker/shared.go +++ b/pkg/provider/docker/shared.go @@ -2,6 +2,7 @@ package docker import ( "context" + "encoding/base64" "fmt" "net/http" "text/template" @@ -101,6 +102,8 @@ func parseContainer(container dockertypes.ContainerJSON) dockerData { type ClientConfig struct { apiVersion string + Username string `description:"Username for Basic HTTP authentication." json:"username,omitempty" toml:"username,omitempty" yaml:"username,omitempty"` + Password string `description:"Password for Basic HTTP authentication." json:"password,omitempty" toml:"password,omitempty" yaml:"password,omitempty"` Endpoint string `description:"Docker server endpoint. Can be a TCP or a Unix socket endpoint." json:"endpoint,omitempty" toml:"endpoint,omitempty" yaml:"endpoint,omitempty"` TLS *types.ClientTLS `description:"Enable Docker TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"` HTTPClientTimeout ptypes.Duration `description:"Client timeout for HTTP connections." json:"httpClientTimeout,omitempty" toml:"httpClientTimeout,omitempty" yaml:"httpClientTimeout,omitempty" export:"true"` @@ -115,6 +118,9 @@ func createClient(ctx context.Context, cfg ClientConfig) (*client.Client, error) httpHeaders := map[string]string{ "User-Agent": "Traefik " + version.Version, } + if cfg.Username != "" && cfg.Password != "" { + httpHeaders["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte(cfg.Username+":"+cfg.Password)) + } opts = append(opts, client.WithHTTPHeaders(httpHeaders),