New API security
This commit is contained in:
parent
1959e1fd44
commit
d044c0f4cc
90 changed files with 538 additions and 132 deletions
|
@ -85,3 +85,34 @@ metrics:
|
|||
```bash tab="CLI"
|
||||
--metrics.prometheus.addServicesLabels=true
|
||||
```
|
||||
|
||||
#### `entryPoint`
|
||||
|
||||
_Optional, Default=traefik_
|
||||
|
||||
Entry point used to expose metrics.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints]
|
||||
[entryPoints.metrics]
|
||||
address = ":8082"
|
||||
|
||||
[metrics]
|
||||
[metrics.prometheus]
|
||||
entryPoint = "metrics"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
metrics:
|
||||
address: ":8082"
|
||||
|
||||
metrics:
|
||||
prometheus:
|
||||
entryPoint: metrics
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entryPoints.metrics.address=":8082"
|
||||
--metrics.prometheus..entryPoint="metrics"
|
||||
```
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
# API
|
||||
|
||||
!!! important
|
||||
In the RC version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the GA version.
|
||||
|
||||
Traefik exposes a number of information through an API handler, such as the configuration of all routers, services, middlewares, etc.
|
||||
|
||||
As with all features of Traefik, this handler can be enabled with the [static configuration](../getting-started/configuration-overview.md#the-static-configuration).
|
||||
|
@ -22,11 +19,10 @@ would be to apply the following protection mechanisms:
|
|||
keeping it restricted to internal networks
|
||||
(as in the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege), applied to networks).
|
||||
|
||||
!!! important
|
||||
In the beta version, you can't configure middlewares (basic authentication or white listing) anymore, but as security is important, this will change before the RC version.
|
||||
|
||||
## Configuration
|
||||
|
||||
If you enable the API, a new special `service` named `api@internal` is created and then can be reference in a router.
|
||||
|
||||
To enable the API handler:
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
|
@ -41,6 +37,83 @@ api: {}
|
|||
--api=true
|
||||
```
|
||||
|
||||
And then you will able to reference it like this.
|
||||
|
||||
```yaml tab="Docker"
|
||||
- "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
|
||||
- "traefik.http.routers.api.service=api@internal"
|
||||
- "traefik.http.routers.api.middlewares=auth"
|
||||
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
"labels": {
|
||||
"traefik.http.routers.api.rule": "PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
|
||||
"traefik.http.routers.api.service": "api@internal"
|
||||
"traefik.http.routers.api.middlewares": "auth"
|
||||
"traefik.http.middlewares.auth.basicauth.users": "test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
# Declaring the user list
|
||||
labels:
|
||||
- "traefik.http.routers.api.rule=PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
|
||||
- "traefik.http.routers.api.service=api@internal"
|
||||
- "traefik.http.routers.api.middlewares=auth"
|
||||
- "traefik.http.middlewares.auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[http.routers.my-api]
|
||||
rule="PathPrefix(`/api`) || PathPrefix(`/dashboard`)"
|
||||
service="api@internal"
|
||||
middlewares=["auth"]
|
||||
|
||||
[http.middlewares.auth.basicAuth]
|
||||
users = [
|
||||
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
|
||||
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
|
||||
]
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
http:
|
||||
routers:
|
||||
api:
|
||||
rule: PathPrefix(`/api`) || PathPrefix(`/dashboard`)
|
||||
service: api@internal
|
||||
middlewares:
|
||||
- auth
|
||||
middlewares:
|
||||
auth:
|
||||
basicAuth:
|
||||
users:
|
||||
- "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
|
||||
- "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
||||
### `insecure`
|
||||
|
||||
Enable the API in `insecure` mode, which means that the API will be available directly on the entryPoint named `traefik`.
|
||||
|
||||
!!! Note
|
||||
If the entryPoint named `traefik` is not configured, it will be automatically created on port 8080.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[api]
|
||||
insecure = true
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
api:
|
||||
insecure: true
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--api.insecure=true
|
||||
```
|
||||
|
||||
### `dashboard`
|
||||
|
||||
_Optional, Default=true_
|
||||
|
|
|
@ -5,7 +5,7 @@ Checking the Health of Your Traefik Instances
|
|||
|
||||
## Configuration Examples
|
||||
|
||||
??? example "Enabling /ping"
|
||||
!!! example "Enabling /ping"
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[ping]
|
||||
|
@ -19,10 +19,39 @@ ping: {}
|
|||
--ping=true
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`.
|
||||
|
||||
You can customize the `entryPoint` where the `/ping` is active with the `entryPoint` option (default value: `traefik`)
|
||||
|
||||
| Path | Method | Description |
|
||||
|---------|---------------|-----------------------------------------------------------------------------------------------------|
|
||||
| `/ping` | `GET`, `HEAD` | A simple endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` |
|
||||
|
||||
## Configuration Options
|
||||
### `entryPoint`
|
||||
|
||||
The `/ping` health-check URL is enabled with the command-line `--ping` or config file option `[ping]`.
|
||||
Enabling /ping on a dedicated EntryPoint.
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[entryPoints]
|
||||
[entryPoints.ping]
|
||||
address = ":8082"
|
||||
|
||||
[ping]
|
||||
entryPoint = "ping"
|
||||
```
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
entryPoints:
|
||||
ping:
|
||||
address: ":8082"
|
||||
|
||||
ping:
|
||||
entryPoint: "ping"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--entryPoints.ping.address=":8082"
|
||||
--ping.entryPoint="ping"
|
||||
```
|
||||
|
|
|
@ -45,6 +45,9 @@ Activate dashboard. (Default: ```true```)
|
|||
`--api.debug`:
|
||||
Enable additional endpoints for debugging and profiling. (Default: ```false```)
|
||||
|
||||
`--api.insecure`:
|
||||
Activate API on an insecure entryPoints named traefik. (Default: ```false```)
|
||||
|
||||
`--certificatesresolvers.<name>`:
|
||||
Certificates resolvers configuration. (Default: ```false```)
|
||||
|
||||
|
@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```)
|
|||
`--metrics.prometheus.buckets`:
|
||||
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
||||
|
||||
`--metrics.prometheus.entrypoint`:
|
||||
EntryPoint (Default: ```traefik```)
|
||||
|
||||
`--metrics.statsd`:
|
||||
StatsD metrics exporter type. (Default: ```false```)
|
||||
|
||||
|
@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```)
|
|||
StatsD push interval. (Default: ```10```)
|
||||
|
||||
`--ping`:
|
||||
Enable ping. (Default: ```true```)
|
||||
Enable ping. (Default: ```false```)
|
||||
|
||||
`--ping.entrypoint`:
|
||||
EntryPoint (Default: ```traefik```)
|
||||
|
||||
`--providers.docker`:
|
||||
Enable Docker backend with default settings. (Default: ```false```)
|
||||
|
@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```)
|
|||
Watch provider. (Default: ```true```)
|
||||
|
||||
`--providers.rest`:
|
||||
Enable Rest backend with default settings. (Default: ```true```)
|
||||
Enable Rest backend with default settings. (Default: ```false```)
|
||||
|
||||
`--providers.rest.insecure`:
|
||||
Activate REST Provider on an insecure entryPoints named traefik. (Default: ```false```)
|
||||
|
||||
`--serverstransport.forwardingtimeouts.dialtimeout`:
|
||||
The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```)
|
||||
|
|
|
@ -45,6 +45,9 @@ Activate dashboard. (Default: ```true```)
|
|||
`TRAEFIK_API_DEBUG`:
|
||||
Enable additional endpoints for debugging and profiling. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_API_INSECURE`:
|
||||
Activate API on an insecure entryPoints named traefik. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_CERTIFICATESRESOLVERS_<NAME>`:
|
||||
Certificates resolvers configuration. (Default: ```false```)
|
||||
|
||||
|
@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```)
|
|||
`TRAEFIK_METRICS_PROMETHEUS_BUCKETS`:
|
||||
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
||||
|
||||
`TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT`:
|
||||
EntryPoint (Default: ```traefik```)
|
||||
|
||||
`TRAEFIK_METRICS_STATSD`:
|
||||
StatsD metrics exporter type. (Default: ```false```)
|
||||
|
||||
|
@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```)
|
|||
StatsD push interval. (Default: ```10```)
|
||||
|
||||
`TRAEFIK_PING`:
|
||||
Enable ping. (Default: ```true```)
|
||||
Enable ping. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_PING_ENTRYPOINT`:
|
||||
EntryPoint (Default: ```traefik```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_DOCKER`:
|
||||
Enable Docker backend with default settings. (Default: ```false```)
|
||||
|
@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```)
|
|||
Watch provider. (Default: ```true```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_REST`:
|
||||
Enable Rest backend with default settings. (Default: ```true```)
|
||||
Enable Rest backend with default settings. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_PROVIDERS_REST_INSECURE`:
|
||||
Activate REST Provider on an insecure entryPoints named traefik. (Default: ```false```)
|
||||
|
||||
`TRAEFIK_SERVERSTRANSPORT_FORWARDINGTIMEOUTS_DIALTIMEOUT`:
|
||||
The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. (Default: ```30```)
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
labelSelector = "foobar"
|
||||
ingressClass = "foobar"
|
||||
[providers.rest]
|
||||
insecure = true
|
||||
[providers.rancher]
|
||||
constraints = "foobar"
|
||||
watch = true
|
||||
|
@ -107,6 +108,7 @@
|
|||
prefix = "foobar"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
dashboard = true
|
||||
debug = true
|
||||
|
||||
|
@ -115,6 +117,7 @@
|
|||
buckets = [42.0, 42.0]
|
||||
addEntryPointsLabels = true
|
||||
addServicesLabels = true
|
||||
entryPoint = "foobar"
|
||||
[metrics.datadog]
|
||||
address = "foobar"
|
||||
pushInterval = "10s"
|
||||
|
@ -137,6 +140,7 @@
|
|||
addServicesLabels = true
|
||||
|
||||
[ping]
|
||||
entryPoint = "foobar"
|
||||
|
||||
[log]
|
||||
level = "foobar"
|
||||
|
|
|
@ -102,7 +102,8 @@ providers:
|
|||
- foobar
|
||||
labelSelector: foobar
|
||||
ingressClass: foobar
|
||||
rest: {}
|
||||
rest:
|
||||
insecure: true
|
||||
rancher:
|
||||
constraints: foobar
|
||||
watch: true
|
||||
|
@ -113,6 +114,7 @@ providers:
|
|||
intervalPoll: true
|
||||
prefix: foobar
|
||||
api:
|
||||
insecure: true
|
||||
dashboard: true
|
||||
debug: true
|
||||
metrics:
|
||||
|
@ -122,6 +124,7 @@ metrics:
|
|||
- 42
|
||||
addEntryPointsLabels: true
|
||||
addServicesLabels: true
|
||||
entryPoint: foobar
|
||||
datadog:
|
||||
address: foobar
|
||||
pushInterval: 42
|
||||
|
@ -142,7 +145,8 @@ metrics:
|
|||
password: foobar
|
||||
addEntryPointsLabels: true
|
||||
addServicesLabels: true
|
||||
ping: {}
|
||||
ping:
|
||||
entryPoint: foobar
|
||||
log:
|
||||
level: foobar
|
||||
filePath: foobar
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
address = ":8008"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.file]
|
||||
|
|
|
@ -34,3 +34,4 @@
|
|||
{{end}}
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8081"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
address = ":9000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.file]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -29,6 +29,7 @@ fblo6RBxUQ==
|
|||
address = ":8081"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
address = ":8081"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.footcp]
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
sendAnonymousUsage = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
address = ":9090"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.marathon]
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
sendAnonymousUsage = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
|
@ -13,6 +14,7 @@
|
|||
|
||||
[providers]
|
||||
[providers.rest]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
trustedIPs = ["{{.HaproxyIP}}"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
trustedIPs = ["1.2.3.4"]
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
sendAnonymousUsage = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.rest]
|
||||
insecure = true
|
||||
|
|
27
integration/fixtures/rest/simple_secure.toml
Normal file
27
integration/fixtures/rest/simple_secure.toml
Normal file
|
@ -0,0 +1,27 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.rest]
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
[http.routers.rest]
|
||||
rule="PathPrefix(`/secure`)"
|
||||
service="rest@internal"
|
||||
middlewares=["strip"]
|
||||
|
||||
[http.middlewares.strip.stripPrefix]
|
||||
prefixes = [ "/secure" ]
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":4443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8001"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
middlewares = ["authentication@file"]
|
||||
|
||||
[ping]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
25
integration/fixtures/simple_secure_api.toml
Normal file
25
integration/fixtures/simple_secure_api.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
|
||||
[entryPoints.traefik]
|
||||
address = ":8080"
|
||||
|
||||
|
||||
[api]
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
[http.routers.api]
|
||||
rule="PathPrefix(`/secure`)"
|
||||
service="api@internal"
|
||||
middlewares=["strip"]
|
||||
|
||||
[http.middlewares.strip.stripPrefix]
|
||||
prefixes = [ "/secure" ]
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
[entryPoints.web]
|
||||
address = ":8000"
|
||||
[entryPoints.web.ForwardedHeaders]
|
||||
insecure=true
|
||||
insecure = true
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8093"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
format = "json"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8443"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers]
|
||||
[providers.docker]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
level = "DEBUG"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.web]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
dashboard = false
|
||||
|
||||
[providers]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
address = ":8000"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
sendAnonymousUsage = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
sendAnonymousUsage = false
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containous/traefik/v2/integration/try"
|
||||
|
@ -20,7 +22,7 @@ func (s *RestSuite) SetUpSuite(c *check.C) {
|
|||
s.composeProject.Start(c)
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
func (s *RestSuite) TestSimpleConfigurationInsecure(c *check.C) {
|
||||
cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||
|
||||
defer display(c)
|
||||
|
@ -110,3 +112,107 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||
file := s.adaptFile(c, "fixtures/rest/simple_secure.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||
|
||||
defer display(c)
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
// Expected a 404 as we did not configure anything.
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 2000*time.Millisecond, try.BodyContains("PathPrefix(`/secure`)"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", strings.NewReader("{}"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
|
||||
testCase := []struct {
|
||||
desc string
|
||||
config *dynamic.Configuration
|
||||
ruleMatch string
|
||||
}{
|
||||
{
|
||||
desc: "deploy http configuration",
|
||||
config: &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"router1": {
|
||||
EntryPoints: []string{"web"},
|
||||
Middlewares: []string{},
|
||||
Service: "service1",
|
||||
Rule: "PathPrefix(`/`)",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"service1": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ruleMatch: "PathPrefix(`/`)",
|
||||
},
|
||||
{
|
||||
desc: "deploy tcp configuration",
|
||||
config: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: map[string]*dynamic.TCPRouter{
|
||||
"router1": {
|
||||
EntryPoints: []string{"web"},
|
||||
Service: "service1",
|
||||
Rule: "HostSNI(`*`)",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.TCPService{
|
||||
"service1": {
|
||||
LoadBalancer: &dynamic.TCPLoadBalancerService{
|
||||
Servers: []dynamic.TCPServer{
|
||||
{
|
||||
Address: s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ruleMatch: "HostSNI(`*`)",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCase {
|
||||
json, err := json.Marshal(test.config)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8000/secure/api/providers/rest", bytes.NewReader(json))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
response, err := http.DefaultClient.Do(request)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1000*time.Millisecond, try.BodyContains(test.ruleMatch))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,33 +161,6 @@ func (s *SimpleSuite) TestRequestAcceptGraceTimeout(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *SimpleSuite) TestApiOnSameEntryPoint(c *check.C) {
|
||||
c.Skip("Waiting for new api handler implementation")
|
||||
s.createComposeProject(c, "base")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.entryPoint=http", "--log.level=DEBUG", "--providers.docker")
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
// TODO validate : run on 80
|
||||
// Expected a 404 as we did not configure anything
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.BodyContains("PathPrefix"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/whoami", 1*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *SimpleSuite) TestStatsWithMultipleEntryPoint(c *check.C) {
|
||||
c.Skip("Stats is missing")
|
||||
s.createComposeProject(c, "stats")
|
||||
|
@ -250,7 +223,7 @@ func (s *SimpleSuite) TestDefaultEntryPointHTTP(c *check.C) {
|
|||
s.createComposeProject(c, "base")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api")
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure")
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
|
@ -268,7 +241,7 @@ func (s *SimpleSuite) TestWithNonExistingEntryPoint(c *check.C) {
|
|||
s.createComposeProject(c, "base")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api")
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--log.level=DEBUG", "--providers.docker", "--api.insecure")
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
|
@ -286,7 +259,7 @@ func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) {
|
|||
s.createComposeProject(c, "base")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--log.level=DEBUG")
|
||||
cmd, output := s.traefikCmd("--entryPoints.http.Address=:8000", "--api.insecure", "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0", "--providers.docker", "--log.level=DEBUG")
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
|
@ -785,3 +758,27 @@ func (s *SimpleSuite) TestMirrorCanceled(c *check.C) {
|
|||
c.Assert(val1, checker.Equals, int32(0))
|
||||
c.Assert(val2, checker.Equals, int32(0))
|
||||
}
|
||||
|
||||
func (s *SimpleSuite) TestSecureAPI(c *check.C) {
|
||||
s.createComposeProject(c, "base")
|
||||
s.composeProject.Start(c)
|
||||
|
||||
file := s.adaptFile(c, "./fixtures/simple_secure_api.toml", struct{}{})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, output := s.traefikCmd(withConfigFile(file))
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/secure/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8000/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
|
|
@ -55,6 +55,15 @@ type Handler struct {
|
|||
dashboardAssets *assetfs.AssetFS
|
||||
}
|
||||
|
||||
// NewBuilder returns a http.Handler builder based on runtime.Configuration
|
||||
func NewBuilder(staticConfig static.Configuration) func(*runtime.Configuration) http.Handler {
|
||||
return func(configuration *runtime.Configuration) http.Handler {
|
||||
router := mux.NewRouter()
|
||||
New(staticConfig, configuration).Append(router)
|
||||
return router
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a Handler defined by staticConfig, and if provided, by runtimeConfig.
|
||||
// It finishes populating the information provided in the runtimeConfig.
|
||||
func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration) *Handler {
|
||||
|
|
|
@ -85,6 +85,7 @@ type ServersTransport struct {
|
|||
|
||||
// API holds the API configuration
|
||||
type API struct {
|
||||
Insecure bool `description:"Activate API directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"`
|
||||
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
|
||||
Debug bool `description:"Enable additional endpoints for debugging and profiling." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"`
|
||||
// TODO: Re-enable statistics
|
||||
|
@ -173,9 +174,9 @@ func (c *Configuration) SetEffectiveConfiguration() {
|
|||
}
|
||||
}
|
||||
|
||||
if (c.API != nil) ||
|
||||
(c.Ping != nil) ||
|
||||
(c.Metrics != nil && c.Metrics.Prometheus != nil) ||
|
||||
if (c.API != nil && c.API.Insecure) ||
|
||||
(c.Ping != nil && c.Ping.EntryPoint == DefaultInternalEntryPointName) ||
|
||||
(c.Metrics != nil && c.Metrics.Prometheus != nil && c.Metrics.Prometheus.EntryPoint == DefaultInternalEntryPointName) ||
|
||||
(c.Providers.Rest != nil) {
|
||||
if _, ok := c.EntryPoints[DefaultInternalEntryPointName]; !ok {
|
||||
ep := &EntryPoint{Address: ":8080"}
|
||||
|
|
|
@ -10,11 +10,13 @@ import (
|
|||
|
||||
// Handler expose ping routes.
|
||||
type Handler struct {
|
||||
EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
||||
terminating bool
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values.
|
||||
func (h *Handler) SetDefaults() {
|
||||
h.EntryPoint = "traefik"
|
||||
}
|
||||
|
||||
// WithContext causes the ping endpoint to serve non 200 responses.
|
||||
|
|
|
@ -18,6 +18,7 @@ var _ provider.Provider = (*Provider)(nil)
|
|||
|
||||
// Provider is a provider.Provider implementation that provides a Rest API.
|
||||
type Provider struct {
|
||||
Insecure bool `description:"Activate REST Provider directly on the entryPoint named traefik." json:"insecure,omitempty" toml:"insecure,omitempty" yaml:"insecure,omitempty" export:"true"`
|
||||
configurationChan chan<- dynamic.Message
|
||||
}
|
||||
|
||||
|
@ -32,6 +33,13 @@ func (p *Provider) Init() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Handler creates an http.Handler for the Rest API
|
||||
func (p *Provider) Handler() http.Handler {
|
||||
router := mux.NewRouter()
|
||||
p.Append(router)
|
||||
return router
|
||||
}
|
||||
|
||||
// Append add rest provider routes on a router.
|
||||
func (p *Provider) Append(systemRouter *mux.Router) {
|
||||
systemRouter.
|
||||
|
|
|
@ -19,30 +19,30 @@ type chainBuilder interface {
|
|||
}
|
||||
|
||||
// NewRouteAppenderAggregator Creates a new RouteAppenderAggregator
|
||||
func NewRouteAppenderAggregator(ctx context.Context, chainBuilder chainBuilder, conf static.Configuration,
|
||||
func NewRouteAppenderAggregator(ctx context.Context, conf static.Configuration,
|
||||
entryPointName string, runtimeConfiguration *runtime.Configuration) *RouteAppenderAggregator {
|
||||
aggregator := &RouteAppenderAggregator{}
|
||||
|
||||
if conf.Ping != nil && conf.Ping.EntryPoint == entryPointName {
|
||||
aggregator.AddAppender(conf.Ping)
|
||||
}
|
||||
|
||||
if conf.Metrics != nil && conf.Metrics.Prometheus != nil && conf.Metrics.Prometheus.EntryPoint == entryPointName {
|
||||
aggregator.AddAppender(metrics.PrometheusHandler{})
|
||||
}
|
||||
|
||||
if entryPointName != "traefik" {
|
||||
return aggregator
|
||||
}
|
||||
|
||||
if conf.Providers != nil && conf.Providers.Rest != nil {
|
||||
if conf.Providers != nil && conf.Providers.Rest != nil && conf.Providers.Rest.Insecure {
|
||||
aggregator.AddAppender(conf.Providers.Rest)
|
||||
}
|
||||
|
||||
if conf.API != nil {
|
||||
if conf.API != nil && conf.API.Insecure {
|
||||
aggregator.AddAppender(api.New(conf, runtimeConfiguration))
|
||||
}
|
||||
|
||||
if conf.Ping != nil {
|
||||
aggregator.AddAppender(conf.Ping)
|
||||
}
|
||||
|
||||
if conf.Metrics != nil && conf.Metrics.Prometheus != nil {
|
||||
aggregator.AddAppender(metrics.PrometheusHandler{})
|
||||
}
|
||||
|
||||
return aggregator
|
||||
}
|
||||
|
||||
|
|
|
@ -6,72 +6,23 @@ import (
|
|||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/alice"
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
"github.com/containous/traefik/v2/pkg/ping"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type ChainBuilderMock struct {
|
||||
middles map[string]alice.Constructor
|
||||
}
|
||||
|
||||
func (c *ChainBuilderMock) BuildChain(ctx context.Context, middles []string) *alice.Chain {
|
||||
chain := alice.New()
|
||||
|
||||
for _, mName := range middles {
|
||||
if constructor, ok := c.middles[mName]; ok {
|
||||
chain = chain.Append(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
return &chain
|
||||
}
|
||||
|
||||
func TestNewRouteAppenderAggregator(t *testing.T) {
|
||||
t.Skip("Waiting for new api handler implementation")
|
||||
testCases := []struct {
|
||||
desc string
|
||||
staticConf static.Configuration
|
||||
middles map[string]alice.Constructor
|
||||
expected map[string]int
|
||||
}{
|
||||
{
|
||||
desc: "API with auth, ping without auth",
|
||||
desc: "Secure API",
|
||||
staticConf: static.Configuration{
|
||||
Global: &static.Global{},
|
||||
API: &static.API{
|
||||
// EntryPoint: "traefik",
|
||||
// Middlewares: []string{"dumb"},
|
||||
},
|
||||
Ping: &ping.Handler{
|
||||
// EntryPoint: "traefik",
|
||||
},
|
||||
EntryPoints: static.EntryPoints{
|
||||
"traefik": {},
|
||||
},
|
||||
},
|
||||
middles: map[string]alice.Constructor{
|
||||
"dumb": func(_ http.Handler) (http.Handler, error) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
}), nil
|
||||
},
|
||||
},
|
||||
expected: map[string]int{
|
||||
"/wrong": http.StatusBadGateway,
|
||||
"/ping": http.StatusOK,
|
||||
// "/.well-known/acme-challenge/token": http.StatusNotFound, // FIXME
|
||||
"/api/rawdata": http.StatusUnauthorized,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Wrong entrypoint name",
|
||||
staticConf: static.Configuration{
|
||||
Global: &static.Global{},
|
||||
API: &static.API{
|
||||
// EntryPoint: "no",
|
||||
API: &static.API{
|
||||
Insecure: false,
|
||||
},
|
||||
EntryPoints: static.EntryPoints{
|
||||
"traefik": {},
|
||||
|
@ -81,6 +32,21 @@ func TestNewRouteAppenderAggregator(t *testing.T) {
|
|||
"/api/providers": http.StatusBadGateway,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Insecure API",
|
||||
staticConf: static.Configuration{
|
||||
Global: &static.Global{},
|
||||
API: &static.API{
|
||||
Insecure: true,
|
||||
},
|
||||
EntryPoints: static.EntryPoints{
|
||||
"traefik": {},
|
||||
},
|
||||
},
|
||||
expected: map[string]int{
|
||||
"/api/rawdata": http.StatusOK,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -88,11 +54,9 @@ func TestNewRouteAppenderAggregator(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
chainBuilder := &ChainBuilderMock{middles: test.middles}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
router := NewRouteAppenderAggregator(ctx, chainBuilder, test.staticConf, "traefik", nil)
|
||||
router := NewRouteAppenderAggregator(ctx, test.staticConf, "traefik", nil)
|
||||
|
||||
internalMuxRouter := mux.NewRouter()
|
||||
router.Append(internalMuxRouter)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
"github.com/containous/traefik/v2/pkg/provider/acme"
|
||||
"github.com/containous/traefik/v2/pkg/server/middleware"
|
||||
"github.com/containous/traefik/v2/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -27,8 +26,8 @@ type RouteAppenderFactory struct {
|
|||
}
|
||||
|
||||
// NewAppender Creates a new RouteAppender
|
||||
func (r *RouteAppenderFactory) NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender {
|
||||
aggregator := NewRouteAppenderAggregator(ctx, middlewaresBuilder, r.staticConfiguration, r.entryPointName, runtimeConfiguration)
|
||||
func (r *RouteAppenderFactory) NewAppender(ctx context.Context, runtimeConfiguration *runtime.Configuration) types.RouteAppender {
|
||||
aggregator := NewRouteAppenderAggregator(ctx, r.staticConfiguration, r.entryPointName, runtimeConfiguration)
|
||||
|
||||
for _, p := range r.acmeProvider {
|
||||
if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == r.entryPointName {
|
||||
|
|
|
@ -306,7 +306,7 @@ func TestRouterManager_Get(t *testing.T) {
|
|||
Middlewares: test.middlewaresConfig,
|
||||
},
|
||||
})
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil)
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil)
|
||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||
|
@ -407,7 +407,7 @@ func TestAccessLog(t *testing.T) {
|
|||
Middlewares: test.middlewaresConfig,
|
||||
},
|
||||
})
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil)
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil)
|
||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||
|
@ -693,7 +693,7 @@ func TestRuntimeConfiguration(t *testing.T) {
|
|||
Middlewares: test.middlewareConfig,
|
||||
},
|
||||
})
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil)
|
||||
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil, nil, nil)
|
||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{})
|
||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||
|
@ -767,7 +767,7 @@ func BenchmarkRouterServe(b *testing.B) {
|
|||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
},
|
||||
})
|
||||
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil)
|
||||
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil, nil, nil)
|
||||
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||
|
@ -808,7 +808,7 @@ func BenchmarkService(b *testing.B) {
|
|||
Services: serviceConfig,
|
||||
},
|
||||
})
|
||||
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil)
|
||||
serviceManager := service.NewManager(rtConf.Services, &staticTransport{res}, nil, nil, nil, nil)
|
||||
w := httptest.NewRecorder()
|
||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://foo.bar/", nil)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/api"
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
|
@ -18,7 +19,6 @@ import (
|
|||
"github.com/containous/traefik/v2/pkg/middlewares/requestdecorator"
|
||||
"github.com/containous/traefik/v2/pkg/provider"
|
||||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"github.com/containous/traefik/v2/pkg/server/middleware"
|
||||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
"github.com/containous/traefik/v2/pkg/tracing"
|
||||
"github.com/containous/traefik/v2/pkg/tracing/jaeger"
|
||||
|
@ -44,11 +44,13 @@ type Server struct {
|
|||
requestDecorator *requestdecorator.RequestDecorator
|
||||
providersThrottleDuration time.Duration
|
||||
tlsManager *tls.Manager
|
||||
api func(configuration *runtime.Configuration) http.Handler
|
||||
restHandler http.Handler
|
||||
}
|
||||
|
||||
// RouteAppenderFactory the route appender factory interface
|
||||
type RouteAppenderFactory interface {
|
||||
NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender
|
||||
NewAppender(ctx context.Context, runtimeConfiguration *runtime.Configuration) types.RouteAppender
|
||||
}
|
||||
|
||||
func setupTracing(conf *static.Tracing) tracing.Backend {
|
||||
|
@ -103,6 +105,14 @@ func setupTracing(conf *static.Tracing) tracing.Backend {
|
|||
func NewServer(staticConfiguration static.Configuration, provider provider.Provider, entryPoints TCPEntryPoints, tlsManager *tls.Manager) *Server {
|
||||
server := &Server{}
|
||||
|
||||
if staticConfiguration.API != nil {
|
||||
server.api = api.NewBuilder(staticConfiguration)
|
||||
}
|
||||
|
||||
if staticConfiguration.Providers != nil && staticConfiguration.Providers.Rest != nil {
|
||||
server.restHandler = staticConfiguration.Providers.Rest.Handler()
|
||||
}
|
||||
|
||||
server.provider = provider
|
||||
server.entryPointsTCP = entryPoints
|
||||
server.configurationChan = make(chan dynamic.Message, 100)
|
||||
|
|
|
@ -97,7 +97,12 @@ func (s *Server) createTCPRouters(ctx context.Context, configuration *runtime.Co
|
|||
|
||||
// createHTTPHandlers returns, for the given configuration and entryPoints, the HTTP handlers for non-TLS connections, and for the TLS ones. the given configuration must not be nil. its fields will get mutated.
|
||||
func (s *Server) createHTTPHandlers(ctx context.Context, configuration *runtime.Configuration, entryPoints []string) (map[string]http.Handler, map[string]http.Handler) {
|
||||
serviceManager := service.NewManager(configuration.Services, s.defaultRoundTripper, s.metricsRegistry, s.routinesPool)
|
||||
var apiHandler http.Handler
|
||||
if s.api != nil {
|
||||
apiHandler = s.api(configuration)
|
||||
}
|
||||
|
||||
serviceManager := service.NewManager(configuration.Services, s.defaultRoundTripper, s.metricsRegistry, s.routinesPool, apiHandler, s.restHandler)
|
||||
middlewaresBuilder := middleware.NewBuilder(configuration.Middlewares, serviceManager)
|
||||
responseModifierFactory := responsemodifiers.NewBuilder(configuration.Middlewares)
|
||||
routerManager := router.NewManager(configuration, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||
|
@ -114,7 +119,7 @@ func (s *Server) createHTTPHandlers(ctx context.Context, configuration *runtime.
|
|||
factory := s.entryPointsTCP[entryPointName].RouteAppenderFactory
|
||||
if factory != nil {
|
||||
// FIXME remove currentConfigurations
|
||||
appender := factory.NewAppender(ctx, middlewaresBuilder, configuration)
|
||||
appender := factory.NewAppender(ctx, configuration)
|
||||
appender.Append(internalMuxRouter)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ const (
|
|||
)
|
||||
|
||||
// NewManager creates a new Manager
|
||||
func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper http.RoundTripper, metricsRegistry metrics.Registry, routinePool *safe.Pool) *Manager {
|
||||
func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper http.RoundTripper, metricsRegistry metrics.Registry, routinePool *safe.Pool, api http.Handler, rest http.Handler) *Manager {
|
||||
return &Manager{
|
||||
routinePool: routinePool,
|
||||
metricsRegistry: metricsRegistry,
|
||||
|
@ -42,6 +42,8 @@ func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper htt
|
|||
defaultRoundTripper: defaultRoundTripper,
|
||||
balancers: make(map[string][]healthcheck.BalancerHandler),
|
||||
configs: configs,
|
||||
api: api,
|
||||
rest: rest,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,10 +55,26 @@ type Manager struct {
|
|||
defaultRoundTripper http.RoundTripper
|
||||
balancers map[string][]healthcheck.BalancerHandler
|
||||
configs map[string]*runtime.ServiceInfo
|
||||
api http.Handler
|
||||
rest http.Handler
|
||||
}
|
||||
|
||||
// BuildHTTP Creates a http.Handler for a service configuration.
|
||||
func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string, responseModifier func(*http.Response) error) (http.Handler, error) {
|
||||
if serviceName == "api@internal" {
|
||||
if m.api == nil {
|
||||
return nil, errors.New("api is not enabled")
|
||||
}
|
||||
return m.api, nil
|
||||
}
|
||||
|
||||
if serviceName == "rest@internal" {
|
||||
if m.rest == nil {
|
||||
return nil, errors.New("rest is not enabled")
|
||||
}
|
||||
return m.rest, nil
|
||||
}
|
||||
|
||||
ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName))
|
||||
|
||||
serviceName = internal.GetQualifiedName(ctx, serviceName)
|
||||
|
|
|
@ -80,7 +80,7 @@ func TestGetLoadBalancer(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetLoadBalancerServiceHandler(t *testing.T) {
|
||||
sm := NewManager(nil, http.DefaultTransport, nil, nil)
|
||||
sm := NewManager(nil, http.DefaultTransport, nil, nil, nil, nil)
|
||||
|
||||
server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("X-From", "first")
|
||||
|
@ -332,7 +332,7 @@ func TestManager_Build(t *testing.T) {
|
|||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
manager := NewManager(test.configs, http.DefaultTransport, nil, nil)
|
||||
manager := NewManager(test.configs, http.DefaultTransport, nil, nil, nil, nil)
|
||||
|
||||
ctx := context.Background()
|
||||
if len(test.providerName) > 0 {
|
||||
|
@ -353,7 +353,7 @@ func TestMultipleTypeOnBuildHTTP(t *testing.T) {
|
|||
Weighted: &dynamic.WeightedRoundRobin{},
|
||||
},
|
||||
},
|
||||
}, http.DefaultTransport, nil, nil)
|
||||
}, http.DefaultTransport, nil, nil, nil, nil)
|
||||
|
||||
_, err := manager.BuildHTTP(context.Background(), "test@file", nil)
|
||||
assert.Error(t, err, "cannot create service: multi-types service not supported, consider declaring two different pieces of service instead")
|
||||
|
|
|
@ -17,6 +17,7 @@ type Prometheus struct {
|
|||
Buckets []float64 `description:"Buckets for latency metrics." json:"buckets,omitempty" toml:"buckets,omitempty" yaml:"buckets,omitempty" export:"true"`
|
||||
AddEntryPointsLabels bool `description:"Enable metrics on entry points." json:"addEntryPointsLabels,omitempty" toml:"addEntryPointsLabels,omitempty" yaml:"addEntryPointsLabels,omitempty" export:"true"`
|
||||
AddServicesLabels bool `description:"Enable metrics on services." json:"addServicesLabels,omitempty" toml:"addServicesLabels,omitempty" yaml:"addServicesLabels,omitempty" export:"true"`
|
||||
EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
||||
}
|
||||
|
||||
// SetDefaults sets the default values.
|
||||
|
@ -24,6 +25,7 @@ func (p *Prometheus) SetDefaults() {
|
|||
p.Buckets = []float64{0.1, 0.3, 1.2, 5}
|
||||
p.AddEntryPointsLabels = true
|
||||
p.AddServicesLabels = true
|
||||
p.EntryPoint = "traefik"
|
||||
}
|
||||
|
||||
// Datadog contains address and metrics pushing interval configuration.
|
||||
|
|
Loading…
Reference in a new issue