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"
|
```bash tab="CLI"
|
||||||
--metrics.prometheus.addServicesLabels=true
|
--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
|
# 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.
|
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).
|
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
|
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).
|
(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
|
## 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:
|
To enable the API handler:
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
|
@ -41,6 +37,83 @@ api: {}
|
||||||
--api=true
|
--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`
|
### `dashboard`
|
||||||
|
|
||||||
_Optional, Default=true_
|
_Optional, Default=true_
|
||||||
|
|
|
@ -5,7 +5,7 @@ Checking the Health of Your Traefik Instances
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
??? example "Enabling /ping"
|
!!! example "Enabling /ping"
|
||||||
|
|
||||||
```toml tab="File (TOML)"
|
```toml tab="File (TOML)"
|
||||||
[ping]
|
[ping]
|
||||||
|
@ -19,10 +19,39 @@ ping: {}
|
||||||
--ping=true
|
--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 |
|
| Path | Method | Description |
|
||||||
|---------|---------------|-----------------------------------------------------------------------------------------------------|
|
|---------|---------------|-----------------------------------------------------------------------------------------------------|
|
||||||
| `/ping` | `GET`, `HEAD` | A simple endpoint to check for Traefik process liveness. Return a code `200` with the content: `OK` |
|
| `/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`:
|
`--api.debug`:
|
||||||
Enable additional endpoints for debugging and profiling. (Default: ```false```)
|
Enable additional endpoints for debugging and profiling. (Default: ```false```)
|
||||||
|
|
||||||
|
`--api.insecure`:
|
||||||
|
Activate API on an insecure entryPoints named traefik. (Default: ```false```)
|
||||||
|
|
||||||
`--certificatesresolvers.<name>`:
|
`--certificatesresolvers.<name>`:
|
||||||
Certificates resolvers configuration. (Default: ```false```)
|
Certificates resolvers configuration. (Default: ```false```)
|
||||||
|
|
||||||
|
@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```)
|
||||||
`--metrics.prometheus.buckets`:
|
`--metrics.prometheus.buckets`:
|
||||||
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
||||||
|
|
||||||
|
`--metrics.prometheus.entrypoint`:
|
||||||
|
EntryPoint (Default: ```traefik```)
|
||||||
|
|
||||||
`--metrics.statsd`:
|
`--metrics.statsd`:
|
||||||
StatsD metrics exporter type. (Default: ```false```)
|
StatsD metrics exporter type. (Default: ```false```)
|
||||||
|
|
||||||
|
@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```)
|
||||||
StatsD push interval. (Default: ```10```)
|
StatsD push interval. (Default: ```10```)
|
||||||
|
|
||||||
`--ping`:
|
`--ping`:
|
||||||
Enable ping. (Default: ```true```)
|
Enable ping. (Default: ```false```)
|
||||||
|
|
||||||
|
`--ping.entrypoint`:
|
||||||
|
EntryPoint (Default: ```traefik```)
|
||||||
|
|
||||||
`--providers.docker`:
|
`--providers.docker`:
|
||||||
Enable Docker backend with default settings. (Default: ```false```)
|
Enable Docker backend with default settings. (Default: ```false```)
|
||||||
|
@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```)
|
||||||
Watch provider. (Default: ```true```)
|
Watch provider. (Default: ```true```)
|
||||||
|
|
||||||
`--providers.rest`:
|
`--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`:
|
`--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```)
|
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`:
|
`TRAEFIK_API_DEBUG`:
|
||||||
Enable additional endpoints for debugging and profiling. (Default: ```false```)
|
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>`:
|
`TRAEFIK_CERTIFICATESRESOLVERS_<NAME>`:
|
||||||
Certificates resolvers configuration. (Default: ```false```)
|
Certificates resolvers configuration. (Default: ```false```)
|
||||||
|
|
||||||
|
@ -207,6 +210,9 @@ Enable metrics on services. (Default: ```true```)
|
||||||
`TRAEFIK_METRICS_PROMETHEUS_BUCKETS`:
|
`TRAEFIK_METRICS_PROMETHEUS_BUCKETS`:
|
||||||
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000```)
|
||||||
|
|
||||||
|
`TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT`:
|
||||||
|
EntryPoint (Default: ```traefik```)
|
||||||
|
|
||||||
`TRAEFIK_METRICS_STATSD`:
|
`TRAEFIK_METRICS_STATSD`:
|
||||||
StatsD metrics exporter type. (Default: ```false```)
|
StatsD metrics exporter type. (Default: ```false```)
|
||||||
|
|
||||||
|
@ -223,7 +229,10 @@ Enable metrics on services. (Default: ```true```)
|
||||||
StatsD push interval. (Default: ```10```)
|
StatsD push interval. (Default: ```10```)
|
||||||
|
|
||||||
`TRAEFIK_PING`:
|
`TRAEFIK_PING`:
|
||||||
Enable ping. (Default: ```true```)
|
Enable ping. (Default: ```false```)
|
||||||
|
|
||||||
|
`TRAEFIK_PING_ENTRYPOINT`:
|
||||||
|
EntryPoint (Default: ```traefik```)
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_DOCKER`:
|
`TRAEFIK_PROVIDERS_DOCKER`:
|
||||||
Enable Docker backend with default settings. (Default: ```false```)
|
Enable Docker backend with default settings. (Default: ```false```)
|
||||||
|
@ -433,7 +442,10 @@ Defines the polling interval in seconds. (Default: ```15```)
|
||||||
Watch provider. (Default: ```true```)
|
Watch provider. (Default: ```true```)
|
||||||
|
|
||||||
`TRAEFIK_PROVIDERS_REST`:
|
`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`:
|
`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```)
|
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"
|
labelSelector = "foobar"
|
||||||
ingressClass = "foobar"
|
ingressClass = "foobar"
|
||||||
[providers.rest]
|
[providers.rest]
|
||||||
|
insecure = true
|
||||||
[providers.rancher]
|
[providers.rancher]
|
||||||
constraints = "foobar"
|
constraints = "foobar"
|
||||||
watch = true
|
watch = true
|
||||||
|
@ -107,6 +108,7 @@
|
||||||
prefix = "foobar"
|
prefix = "foobar"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
dashboard = true
|
dashboard = true
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
@ -115,6 +117,7 @@
|
||||||
buckets = [42.0, 42.0]
|
buckets = [42.0, 42.0]
|
||||||
addEntryPointsLabels = true
|
addEntryPointsLabels = true
|
||||||
addServicesLabels = true
|
addServicesLabels = true
|
||||||
|
entryPoint = "foobar"
|
||||||
[metrics.datadog]
|
[metrics.datadog]
|
||||||
address = "foobar"
|
address = "foobar"
|
||||||
pushInterval = "10s"
|
pushInterval = "10s"
|
||||||
|
@ -137,6 +140,7 @@
|
||||||
addServicesLabels = true
|
addServicesLabels = true
|
||||||
|
|
||||||
[ping]
|
[ping]
|
||||||
|
entryPoint = "foobar"
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "foobar"
|
level = "foobar"
|
||||||
|
|
|
@ -102,7 +102,8 @@ providers:
|
||||||
- foobar
|
- foobar
|
||||||
labelSelector: foobar
|
labelSelector: foobar
|
||||||
ingressClass: foobar
|
ingressClass: foobar
|
||||||
rest: {}
|
rest:
|
||||||
|
insecure: true
|
||||||
rancher:
|
rancher:
|
||||||
constraints: foobar
|
constraints: foobar
|
||||||
watch: true
|
watch: true
|
||||||
|
@ -113,6 +114,7 @@ providers:
|
||||||
intervalPoll: true
|
intervalPoll: true
|
||||||
prefix: foobar
|
prefix: foobar
|
||||||
api:
|
api:
|
||||||
|
insecure: true
|
||||||
dashboard: true
|
dashboard: true
|
||||||
debug: true
|
debug: true
|
||||||
metrics:
|
metrics:
|
||||||
|
@ -122,6 +124,7 @@ metrics:
|
||||||
- 42
|
- 42
|
||||||
addEntryPointsLabels: true
|
addEntryPointsLabels: true
|
||||||
addServicesLabels: true
|
addServicesLabels: true
|
||||||
|
entryPoint: foobar
|
||||||
datadog:
|
datadog:
|
||||||
address: foobar
|
address: foobar
|
||||||
pushInterval: 42
|
pushInterval: 42
|
||||||
|
@ -142,7 +145,8 @@ metrics:
|
||||||
password: foobar
|
password: foobar
|
||||||
addEntryPointsLabels: true
|
addEntryPointsLabels: true
|
||||||
addServicesLabels: true
|
addServicesLabels: true
|
||||||
ping: {}
|
ping:
|
||||||
|
entryPoint: foobar
|
||||||
log:
|
log:
|
||||||
level: foobar
|
level: foobar
|
||||||
filePath: foobar
|
filePath: foobar
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
address = ":8008"
|
address = ":8008"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.file]
|
[providers.file]
|
||||||
|
|
|
@ -34,3 +34,4 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8081"
|
address = ":8081"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
address = ":9000"
|
address = ":9000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8443"
|
address = ":8443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.file]
|
[providers.file]
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8443"
|
address = ":8443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -29,6 +29,7 @@ fblo6RBxUQ==
|
||||||
address = ":8081"
|
address = ":8081"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
address = ":8081"
|
address = ":8081"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.footcp]
|
[entryPoints.footcp]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
sendAnonymousUsage = false
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
address = ":9090"
|
address = ":9090"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.marathon]
|
[providers.marathon]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
sendAnonymousUsage = false
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.web]
|
[entryPoints.web]
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.rest]
|
[providers.rest]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
trustedIPs = ["{{.HaproxyIP}}"]
|
trustedIPs = ["{{.HaproxyIP}}"]
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
trustedIPs = ["1.2.3.4"]
|
trustedIPs = ["1.2.3.4"]
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
sendAnonymousUsage = false
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.rest]
|
[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"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8001"
|
address = ":8001"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
middlewares = ["authentication@file"]
|
middlewares = ["authentication@file"]
|
||||||
|
|
||||||
[ping]
|
[ping]
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[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"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,3 +10,4 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
|
@ -9,9 +9,10 @@
|
||||||
[entryPoints.web]
|
[entryPoints.web]
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
[entryPoints.web.ForwardedHeaders]
|
[entryPoints.web.ForwardedHeaders]
|
||||||
insecure=true
|
insecure = true
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8093"
|
address = ":8093"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
format = "json"
|
format = "json"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8443"
|
address = ":8443"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
[providers.docker]
|
[providers.docker]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.web]
|
[entryPoints.web]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.web]
|
[entryPoints.web]
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.web]
|
[entryPoints.web]
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
dashboard = false
|
dashboard = false
|
||||||
|
|
||||||
[providers]
|
[providers]
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
address = ":8000"
|
address = ":8000"
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[providers.file]
|
[providers.file]
|
||||||
filename = "{{ .SelfFilename }}"
|
filename = "{{ .SelfFilename }}"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
sendAnonymousUsage = false
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
sendAnonymousUsage = false
|
sendAnonymousUsage = false
|
||||||
|
|
||||||
[api]
|
[api]
|
||||||
|
insecure = true
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containous/traefik/v2/integration/try"
|
"github.com/containous/traefik/v2/integration/try"
|
||||||
|
@ -20,7 +22,7 @@ func (s *RestSuite) SetUpSuite(c *check.C) {
|
||||||
s.composeProject.Start(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"))
|
cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
|
||||||
|
|
||||||
defer display(c)
|
defer display(c)
|
||||||
|
@ -110,3 +112,107 @@ func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
|
||||||
c.Assert(err, checker.IsNil)
|
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) {
|
func (s *SimpleSuite) TestStatsWithMultipleEntryPoint(c *check.C) {
|
||||||
c.Skip("Stats is missing")
|
c.Skip("Stats is missing")
|
||||||
s.createComposeProject(c, "stats")
|
s.createComposeProject(c, "stats")
|
||||||
|
@ -250,7 +223,7 @@ func (s *SimpleSuite) TestDefaultEntryPointHTTP(c *check.C) {
|
||||||
s.createComposeProject(c, "base")
|
s.createComposeProject(c, "base")
|
||||||
s.composeProject.Start(c)
|
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)
|
defer output(c)
|
||||||
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
|
@ -268,7 +241,7 @@ func (s *SimpleSuite) TestWithNonExistingEntryPoint(c *check.C) {
|
||||||
s.createComposeProject(c, "base")
|
s.createComposeProject(c, "base")
|
||||||
s.composeProject.Start(c)
|
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)
|
defer output(c)
|
||||||
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
|
@ -286,7 +259,7 @@ func (s *SimpleSuite) TestMetricsPrometheusDefaultEntryPoint(c *check.C) {
|
||||||
s.createComposeProject(c, "base")
|
s.createComposeProject(c, "base")
|
||||||
s.composeProject.Start(c)
|
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)
|
defer output(c)
|
||||||
|
|
||||||
err := cmd.Start()
|
err := cmd.Start()
|
||||||
|
@ -785,3 +758,27 @@ func (s *SimpleSuite) TestMirrorCanceled(c *check.C) {
|
||||||
c.Assert(val1, checker.Equals, int32(0))
|
c.Assert(val1, checker.Equals, int32(0))
|
||||||
c.Assert(val2, 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
|
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.
|
// New returns a Handler defined by staticConfig, and if provided, by runtimeConfig.
|
||||||
// It finishes populating the information provided in the runtimeConfig.
|
// It finishes populating the information provided in the runtimeConfig.
|
||||||
func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration) *Handler {
|
func New(staticConfig static.Configuration, runtimeConfig *runtime.Configuration) *Handler {
|
||||||
|
|
|
@ -85,6 +85,7 @@ type ServersTransport struct {
|
||||||
|
|
||||||
// API holds the API configuration
|
// API holds the API configuration
|
||||||
type API struct {
|
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"`
|
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"`
|
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
|
// TODO: Re-enable statistics
|
||||||
|
@ -173,9 +174,9 @@ func (c *Configuration) SetEffectiveConfiguration() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.API != nil) ||
|
if (c.API != nil && c.API.Insecure) ||
|
||||||
(c.Ping != nil) ||
|
(c.Ping != nil && c.Ping.EntryPoint == DefaultInternalEntryPointName) ||
|
||||||
(c.Metrics != nil && c.Metrics.Prometheus != nil) ||
|
(c.Metrics != nil && c.Metrics.Prometheus != nil && c.Metrics.Prometheus.EntryPoint == DefaultInternalEntryPointName) ||
|
||||||
(c.Providers.Rest != nil) {
|
(c.Providers.Rest != nil) {
|
||||||
if _, ok := c.EntryPoints[DefaultInternalEntryPointName]; !ok {
|
if _, ok := c.EntryPoints[DefaultInternalEntryPointName]; !ok {
|
||||||
ep := &EntryPoint{Address: ":8080"}
|
ep := &EntryPoint{Address: ":8080"}
|
||||||
|
|
|
@ -10,11 +10,13 @@ import (
|
||||||
|
|
||||||
// Handler expose ping routes.
|
// Handler expose ping routes.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
EntryPoint string `description:"EntryPoint" export:"true" json:"entryPoint,omitempty" toml:"entryPoint,omitempty" yaml:"entryPoint,omitempty"`
|
||||||
terminating bool
|
terminating bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
func (h *Handler) SetDefaults() {
|
func (h *Handler) SetDefaults() {
|
||||||
|
h.EntryPoint = "traefik"
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithContext causes the ping endpoint to serve non 200 responses.
|
// 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.
|
// Provider is a provider.Provider implementation that provides a Rest API.
|
||||||
type Provider struct {
|
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
|
configurationChan chan<- dynamic.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +33,13 @@ func (p *Provider) Init() error {
|
||||||
return nil
|
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.
|
// Append add rest provider routes on a router.
|
||||||
func (p *Provider) Append(systemRouter *mux.Router) {
|
func (p *Provider) Append(systemRouter *mux.Router) {
|
||||||
systemRouter.
|
systemRouter.
|
||||||
|
|
|
@ -19,30 +19,30 @@ type chainBuilder interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRouteAppenderAggregator Creates a new RouteAppenderAggregator
|
// 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 {
|
entryPointName string, runtimeConfiguration *runtime.Configuration) *RouteAppenderAggregator {
|
||||||
aggregator := &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" {
|
if entryPointName != "traefik" {
|
||||||
return aggregator
|
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)
|
aggregator.AddAppender(conf.Providers.Rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.API != nil {
|
if conf.API != nil && conf.API.Insecure {
|
||||||
aggregator.AddAppender(api.New(conf, runtimeConfiguration))
|
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
|
return aggregator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,72 +6,23 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containous/alice"
|
|
||||||
"github.com/containous/traefik/v2/pkg/config/static"
|
"github.com/containous/traefik/v2/pkg/config/static"
|
||||||
"github.com/containous/traefik/v2/pkg/ping"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/stretchr/testify/assert"
|
"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) {
|
func TestNewRouteAppenderAggregator(t *testing.T) {
|
||||||
t.Skip("Waiting for new api handler implementation")
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
staticConf static.Configuration
|
staticConf static.Configuration
|
||||||
middles map[string]alice.Constructor
|
|
||||||
expected map[string]int
|
expected map[string]int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "API with auth, ping without auth",
|
desc: "Secure API",
|
||||||
staticConf: static.Configuration{
|
staticConf: static.Configuration{
|
||||||
Global: &static.Global{},
|
Global: &static.Global{},
|
||||||
API: &static.API{
|
API: &static.API{
|
||||||
// EntryPoint: "traefik",
|
Insecure: false,
|
||||||
// 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",
|
|
||||||
},
|
},
|
||||||
EntryPoints: static.EntryPoints{
|
EntryPoints: static.EntryPoints{
|
||||||
"traefik": {},
|
"traefik": {},
|
||||||
|
@ -81,6 +32,21 @@ func TestNewRouteAppenderAggregator(t *testing.T) {
|
||||||
"/api/providers": http.StatusBadGateway,
|
"/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 {
|
for _, test := range testCases {
|
||||||
|
@ -88,11 +54,9 @@ func TestNewRouteAppenderAggregator(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
chainBuilder := &ChainBuilderMock{middles: test.middles}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
router := NewRouteAppenderAggregator(ctx, chainBuilder, test.staticConf, "traefik", nil)
|
router := NewRouteAppenderAggregator(ctx, test.staticConf, "traefik", nil)
|
||||||
|
|
||||||
internalMuxRouter := mux.NewRouter()
|
internalMuxRouter := mux.NewRouter()
|
||||||
router.Append(internalMuxRouter)
|
router.Append(internalMuxRouter)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||||
"github.com/containous/traefik/v2/pkg/config/static"
|
"github.com/containous/traefik/v2/pkg/config/static"
|
||||||
"github.com/containous/traefik/v2/pkg/provider/acme"
|
"github.com/containous/traefik/v2/pkg/provider/acme"
|
||||||
"github.com/containous/traefik/v2/pkg/server/middleware"
|
|
||||||
"github.com/containous/traefik/v2/pkg/types"
|
"github.com/containous/traefik/v2/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,8 +26,8 @@ type RouteAppenderFactory struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAppender Creates a new RouteAppender
|
// NewAppender Creates a new RouteAppender
|
||||||
func (r *RouteAppenderFactory) NewAppender(ctx context.Context, middlewaresBuilder *middleware.Builder, runtimeConfiguration *runtime.Configuration) types.RouteAppender {
|
func (r *RouteAppenderFactory) NewAppender(ctx context.Context, runtimeConfiguration *runtime.Configuration) types.RouteAppender {
|
||||||
aggregator := NewRouteAppenderAggregator(ctx, middlewaresBuilder, r.staticConfiguration, r.entryPointName, runtimeConfiguration)
|
aggregator := NewRouteAppenderAggregator(ctx, r.staticConfiguration, r.entryPointName, runtimeConfiguration)
|
||||||
|
|
||||||
for _, p := range r.acmeProvider {
|
for _, p := range r.acmeProvider {
|
||||||
if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == r.entryPointName {
|
if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == r.entryPointName {
|
||||||
|
|
|
@ -306,7 +306,7 @@ func TestRouterManager_Get(t *testing.T) {
|
||||||
Middlewares: test.middlewaresConfig,
|
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)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||||
|
@ -407,7 +407,7 @@ func TestAccessLog(t *testing.T) {
|
||||||
Middlewares: test.middlewaresConfig,
|
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)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||||
|
@ -693,7 +693,7 @@ func TestRuntimeConfiguration(t *testing.T) {
|
||||||
Middlewares: test.middlewareConfig,
|
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)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||||
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{})
|
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{})
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||||
|
@ -767,7 +767,7 @@ func BenchmarkRouterServe(b *testing.B) {
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
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)
|
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
|
||||||
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
responseModifierFactory := responsemodifiers.NewBuilder(rtConf.Middlewares)
|
||||||
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory)
|
||||||
|
@ -808,7 +808,7 @@ func BenchmarkService(b *testing.B) {
|
||||||
Services: serviceConfig,
|
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()
|
w := httptest.NewRecorder()
|
||||||
req := testhelpers.MustNewRequest(http.MethodGet, "http://foo.bar/", nil)
|
req := testhelpers.MustNewRequest(http.MethodGet, "http://foo.bar/", nil)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/v2/pkg/api"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
"github.com/containous/traefik/v2/pkg/config/runtime"
|
"github.com/containous/traefik/v2/pkg/config/runtime"
|
||||||
"github.com/containous/traefik/v2/pkg/config/static"
|
"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/middlewares/requestdecorator"
|
||||||
"github.com/containous/traefik/v2/pkg/provider"
|
"github.com/containous/traefik/v2/pkg/provider"
|
||||||
"github.com/containous/traefik/v2/pkg/safe"
|
"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/tls"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing"
|
"github.com/containous/traefik/v2/pkg/tracing"
|
||||||
"github.com/containous/traefik/v2/pkg/tracing/jaeger"
|
"github.com/containous/traefik/v2/pkg/tracing/jaeger"
|
||||||
|
@ -44,11 +44,13 @@ type Server struct {
|
||||||
requestDecorator *requestdecorator.RequestDecorator
|
requestDecorator *requestdecorator.RequestDecorator
|
||||||
providersThrottleDuration time.Duration
|
providersThrottleDuration time.Duration
|
||||||
tlsManager *tls.Manager
|
tlsManager *tls.Manager
|
||||||
|
api func(configuration *runtime.Configuration) http.Handler
|
||||||
|
restHandler http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// RouteAppenderFactory the route appender factory interface
|
// RouteAppenderFactory the route appender factory interface
|
||||||
type RouteAppenderFactory 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 {
|
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 {
|
func NewServer(staticConfiguration static.Configuration, provider provider.Provider, entryPoints TCPEntryPoints, tlsManager *tls.Manager) *Server {
|
||||||
server := &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.provider = provider
|
||||||
server.entryPointsTCP = entryPoints
|
server.entryPointsTCP = entryPoints
|
||||||
server.configurationChan = make(chan dynamic.Message, 100)
|
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.
|
// 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) {
|
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)
|
middlewaresBuilder := middleware.NewBuilder(configuration.Middlewares, serviceManager)
|
||||||
responseModifierFactory := responsemodifiers.NewBuilder(configuration.Middlewares)
|
responseModifierFactory := responsemodifiers.NewBuilder(configuration.Middlewares)
|
||||||
routerManager := router.NewManager(configuration, serviceManager, middlewaresBuilder, responseModifierFactory)
|
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
|
factory := s.entryPointsTCP[entryPointName].RouteAppenderFactory
|
||||||
if factory != nil {
|
if factory != nil {
|
||||||
// FIXME remove currentConfigurations
|
// FIXME remove currentConfigurations
|
||||||
appender := factory.NewAppender(ctx, middlewaresBuilder, configuration)
|
appender := factory.NewAppender(ctx, configuration)
|
||||||
appender.Append(internalMuxRouter)
|
appender.Append(internalMuxRouter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewManager creates a new Manager
|
// 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{
|
return &Manager{
|
||||||
routinePool: routinePool,
|
routinePool: routinePool,
|
||||||
metricsRegistry: metricsRegistry,
|
metricsRegistry: metricsRegistry,
|
||||||
|
@ -42,6 +42,8 @@ func NewManager(configs map[string]*runtime.ServiceInfo, defaultRoundTripper htt
|
||||||
defaultRoundTripper: defaultRoundTripper,
|
defaultRoundTripper: defaultRoundTripper,
|
||||||
balancers: make(map[string][]healthcheck.BalancerHandler),
|
balancers: make(map[string][]healthcheck.BalancerHandler),
|
||||||
configs: configs,
|
configs: configs,
|
||||||
|
api: api,
|
||||||
|
rest: rest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,10 +55,26 @@ type Manager struct {
|
||||||
defaultRoundTripper http.RoundTripper
|
defaultRoundTripper http.RoundTripper
|
||||||
balancers map[string][]healthcheck.BalancerHandler
|
balancers map[string][]healthcheck.BalancerHandler
|
||||||
configs map[string]*runtime.ServiceInfo
|
configs map[string]*runtime.ServiceInfo
|
||||||
|
api http.Handler
|
||||||
|
rest http.Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildHTTP Creates a http.Handler for a service configuration.
|
// 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) {
|
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))
|
ctx := log.With(rootCtx, log.Str(log.ServiceName, serviceName))
|
||||||
|
|
||||||
serviceName = internal.GetQualifiedName(ctx, serviceName)
|
serviceName = internal.GetQualifiedName(ctx, serviceName)
|
||||||
|
|
|
@ -80,7 +80,7 @@ func TestGetLoadBalancer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetLoadBalancerServiceHandler(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) {
|
server1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("X-From", "first")
|
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.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
manager := NewManager(test.configs, http.DefaultTransport, nil, nil)
|
manager := NewManager(test.configs, http.DefaultTransport, nil, nil, nil, nil)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
if len(test.providerName) > 0 {
|
if len(test.providerName) > 0 {
|
||||||
|
@ -353,7 +353,7 @@ func TestMultipleTypeOnBuildHTTP(t *testing.T) {
|
||||||
Weighted: &dynamic.WeightedRoundRobin{},
|
Weighted: &dynamic.WeightedRoundRobin{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, http.DefaultTransport, nil, nil)
|
}, http.DefaultTransport, nil, nil, nil, nil)
|
||||||
|
|
||||||
_, err := manager.BuildHTTP(context.Background(), "test@file", 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")
|
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"`
|
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"`
|
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"`
|
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.
|
// SetDefaults sets the default values.
|
||||||
|
@ -24,6 +25,7 @@ func (p *Prometheus) SetDefaults() {
|
||||||
p.Buckets = []float64{0.1, 0.3, 1.2, 5}
|
p.Buckets = []float64{0.1, 0.3, 1.2, 5}
|
||||||
p.AddEntryPointsLabels = true
|
p.AddEntryPointsLabels = true
|
||||||
p.AddServicesLabels = true
|
p.AddServicesLabels = true
|
||||||
|
p.EntryPoint = "traefik"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Datadog contains address and metrics pushing interval configuration.
|
// Datadog contains address and metrics pushing interval configuration.
|
||||||
|
|
Loading…
Reference in a new issue