Reintroduce dropped v2 dynamic config
Co-authored-by: Baptiste Mayelle <baptiste.mayelle@traefik.io>
This commit is contained in:
parent
18203f57d2
commit
40de310927
53 changed files with 880 additions and 392 deletions
|
@ -161,7 +161,10 @@ linters-settings:
|
||||||
- len
|
- len
|
||||||
- suite-extra-assert-call
|
- suite-extra-assert-call
|
||||||
- suite-thelper
|
- suite-thelper
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- all
|
||||||
|
- -SA1019
|
||||||
linters:
|
linters:
|
||||||
enable-all: true
|
enable-all: true
|
||||||
disable:
|
disable:
|
||||||
|
|
|
@ -52,3 +52,16 @@ http:
|
||||||
[http.middlewares]
|
[http.middlewares]
|
||||||
[http.middlewares.autodetect.contentType]
|
[http.middlewares.autodetect.contentType]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### `autoDetect`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
`autoDetect` option is deprecated and should not be used.
|
||||||
|
Moreover, it is redundant with an empty ContentType middleware declaration.
|
||||||
|
|
||||||
|
`autoDetect` specifies whether to let the `Content-Type` header,
|
||||||
|
if it has not been set by the backend,
|
||||||
|
be automatically set to a value derived from the contents of the response.
|
||||||
|
|
|
@ -314,11 +314,43 @@ The `allowedHosts` option lists fully qualified domain names that are allowed.
|
||||||
|
|
||||||
The `hostsProxyHeaders` option is a set of header keys that may hold a proxied hostname value for the request.
|
The `hostsProxyHeaders` option is a set of header keys that may hold a proxied hostname value for the request.
|
||||||
|
|
||||||
|
### `sslRedirect`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md).
|
||||||
|
|
||||||
|
The `sslRedirect` only allow HTTPS requests when set to `true`.
|
||||||
|
|
||||||
|
### `sslTemporaryRedirect`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of [EntryPoint redirection](../../routing/entrypoints.md#redirection) or the [RedirectScheme middleware](./redirectscheme.md).
|
||||||
|
|
||||||
|
Set `sslTemporaryRedirect` to `true` to force an SSL redirection using a 302 (instead of a 301).
|
||||||
|
|
||||||
|
### `sslHost`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md).
|
||||||
|
|
||||||
|
The `sslHost` option is the host name that is used to redirect HTTP requests to HTTPS.
|
||||||
|
|
||||||
### `sslProxyHeaders`
|
### `sslProxyHeaders`
|
||||||
|
|
||||||
The `sslProxyHeaders` option is set of header keys with associated values that would indicate a valid HTTPS request.
|
The `sslProxyHeaders` option is set of header keys with associated values that would indicate a valid HTTPS request.
|
||||||
It can be useful when using other proxies (example: `"X-Forwarded-Proto": "https"`).
|
It can be useful when using other proxies (example: `"X-Forwarded-Proto": "https"`).
|
||||||
|
|
||||||
|
### `sslForceHost`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of the [RedirectRegex middleware](./redirectregex.md).
|
||||||
|
|
||||||
|
Set `sslForceHost` to `true` and set `sslHost` to force requests to use `SSLHost` regardless of whether they already use SSL.
|
||||||
|
|
||||||
### `stsSeconds`
|
### `stsSeconds`
|
||||||
|
|
||||||
The `stsSeconds` is the max-age of the `Strict-Transport-Security` header.
|
The `stsSeconds` is the max-age of the `Strict-Transport-Security` header.
|
||||||
|
@ -370,6 +402,14 @@ The `publicKey` implements HPKP to prevent MITM attacks with forged certificates
|
||||||
|
|
||||||
The `referrerPolicy` allows sites to control whether browsers forward the `Referer` header to other sites.
|
The `referrerPolicy` allows sites to control whether browsers forward the `Referer` header to other sites.
|
||||||
|
|
||||||
|
### `featurePolicy`
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of [`permissionsPolicy`](#permissionsPolicy)
|
||||||
|
|
||||||
|
The `featurePolicy` allows sites to control browser features.
|
||||||
|
|
||||||
### `permissionsPolicy`
|
### `permissionsPolicy`
|
||||||
|
|
||||||
The `permissionsPolicy` allows sites to control browser features.
|
The `permissionsPolicy` allows sites to control browser features.
|
||||||
|
|
|
@ -76,3 +76,72 @@ For instance, `/products` also matches `/products/shoes` and `/products/shirts`.
|
||||||
|
|
||||||
If your backend is serving assets (e.g., images or JavaScript files), it can use the `X-Forwarded-Prefix` header to properly construct relative URLs.
|
If your backend is serving assets (e.g., images or JavaScript files), it can use the `X-Forwarded-Prefix` header to properly construct relative URLs.
|
||||||
Using the previous example, the backend should return `/products/shoes/image.png` (and not `/image.png`, which Traefik would likely not be able to associate with the same backend).
|
Using the previous example, the backend should return `/products/shoes/image.png` (and not `/image.png`, which Traefik would likely not be able to associate with the same backend).
|
||||||
|
|
||||||
|
### `forceSlash`
|
||||||
|
|
||||||
|
_Optional, Default=true_
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
`forceSlash` option is deprecated and should not be used.
|
||||||
|
|
||||||
|
The `forceSlash` option ensures the resulting stripped path is not the empty string, by replacing it with `/` when necessary.
|
||||||
|
|
||||||
|
??? info "Behavior examples"
|
||||||
|
|
||||||
|
- `forceSlash=true`
|
||||||
|
|
||||||
|
| Path | Prefix to strip | Result |
|
||||||
|
|------------|-----------------|--------|
|
||||||
|
| `/` | `/` | `/` |
|
||||||
|
| `/foo` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo/` | `/` |
|
||||||
|
| `/bar` | `/foo` | `/bar` |
|
||||||
|
| `/foo/bar` | `/foo` | `/bar` |
|
||||||
|
|
||||||
|
- `forceSlash=false`
|
||||||
|
|
||||||
|
| Path | Prefix to strip | Result |
|
||||||
|
|------------|-----------------|--------|
|
||||||
|
| `/` | `/` | empty |
|
||||||
|
| `/foo` | `/foo` | empty |
|
||||||
|
| `/foo/` | `/foo` | `/` |
|
||||||
|
| `/foo/` | `/foo/` | empty |
|
||||||
|
| `/bar` | `/foo` | `/bar` |
|
||||||
|
| `/foo/bar` | `/foo` | `/bar` |
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
labels:
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.prefixes=/foobar"
|
||||||
|
- "traefik.http.middlewares.example.stripprefix.forceSlash=false"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
spec:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- "/foobar"
|
||||||
|
forceSlash: false
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
http:
|
||||||
|
middlewares:
|
||||||
|
example:
|
||||||
|
stripPrefix:
|
||||||
|
prefixes:
|
||||||
|
- "/foobar"
|
||||||
|
forceSlash: false
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
[http.middlewares]
|
||||||
|
[http.middlewares.example.stripPrefix]
|
||||||
|
prefixes = ["/foobar"]
|
||||||
|
forceSlash = false
|
||||||
|
```
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
- "traefik.http.middlewares.middleware06.compress.includedcontenttypes=foobar, foobar"
|
- "traefik.http.middlewares.middleware06.compress.includedcontenttypes=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware06.compress.minresponsebodybytes=42"
|
- "traefik.http.middlewares.middleware06.compress.minresponsebodybytes=42"
|
||||||
- "traefik.http.middlewares.middleware07.contenttype=true"
|
- "traefik.http.middlewares.middleware07.contenttype=true"
|
||||||
|
- "traefik.http.middlewares.middleware07.contenttype.autodetect=true"
|
||||||
- "traefik.http.middlewares.middleware08.digestauth.headerfield=foobar"
|
- "traefik.http.middlewares.middleware08.digestauth.headerfield=foobar"
|
||||||
- "traefik.http.middlewares.middleware08.digestauth.realm=foobar"
|
- "traefik.http.middlewares.middleware08.digestauth.realm=foobar"
|
||||||
- "traefik.http.middlewares.middleware08.digestauth.removeheader=true"
|
- "traefik.http.middlewares.middleware08.digestauth.removeheader=true"
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.authresponseheaders=foobar, foobar"
|
- "traefik.http.middlewares.middleware10.forwardauth.authresponseheaders=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.authresponseheadersregex=foobar"
|
- "traefik.http.middlewares.middleware10.forwardauth.authresponseheadersregex=foobar"
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.tls.ca=foobar"
|
- "traefik.http.middlewares.middleware10.forwardauth.tls.ca=foobar"
|
||||||
|
- "traefik.http.middlewares.middleware10.forwardauth.tls.caoptional=true"
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.tls.cert=foobar"
|
- "traefik.http.middlewares.middleware10.forwardauth.tls.cert=foobar"
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.tls.insecureskipverify=true"
|
- "traefik.http.middlewares.middleware10.forwardauth.tls.insecureskipverify=true"
|
||||||
- "traefik.http.middlewares.middleware10.forwardauth.tls.key=foobar"
|
- "traefik.http.middlewares.middleware10.forwardauth.tls.key=foobar"
|
||||||
|
@ -59,6 +61,7 @@
|
||||||
- "traefik.http.middlewares.middleware12.headers.customrequestheaders.name1=foobar"
|
- "traefik.http.middlewares.middleware12.headers.customrequestheaders.name1=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name0=foobar"
|
- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name0=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name1=foobar"
|
- "traefik.http.middlewares.middleware12.headers.customresponseheaders.name1=foobar"
|
||||||
|
- "traefik.http.middlewares.middleware12.headers.featurepolicy=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.forcestsheader=true"
|
- "traefik.http.middlewares.middleware12.headers.forcestsheader=true"
|
||||||
- "traefik.http.middlewares.middleware12.headers.framedeny=true"
|
- "traefik.http.middlewares.middleware12.headers.framedeny=true"
|
||||||
- "traefik.http.middlewares.middleware12.headers.hostsproxyheaders=foobar, foobar"
|
- "traefik.http.middlewares.middleware12.headers.hostsproxyheaders=foobar, foobar"
|
||||||
|
@ -66,8 +69,12 @@
|
||||||
- "traefik.http.middlewares.middleware12.headers.permissionspolicy=foobar"
|
- "traefik.http.middlewares.middleware12.headers.permissionspolicy=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.publickey=foobar"
|
- "traefik.http.middlewares.middleware12.headers.publickey=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.referrerpolicy=foobar"
|
- "traefik.http.middlewares.middleware12.headers.referrerpolicy=foobar"
|
||||||
|
- "traefik.http.middlewares.middleware12.headers.sslforcehost=true"
|
||||||
|
- "traefik.http.middlewares.middleware12.headers.sslhost=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name0=foobar"
|
- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name0=foobar"
|
||||||
- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name1=foobar"
|
- "traefik.http.middlewares.middleware12.headers.sslproxyheaders.name1=foobar"
|
||||||
|
- "traefik.http.middlewares.middleware12.headers.sslredirect=true"
|
||||||
|
- "traefik.http.middlewares.middleware12.headers.ssltemporaryredirect=true"
|
||||||
- "traefik.http.middlewares.middleware12.headers.stsincludesubdomains=true"
|
- "traefik.http.middlewares.middleware12.headers.stsincludesubdomains=true"
|
||||||
- "traefik.http.middlewares.middleware12.headers.stspreload=true"
|
- "traefik.http.middlewares.middleware12.headers.stspreload=true"
|
||||||
- "traefik.http.middlewares.middleware12.headers.stsseconds=42"
|
- "traefik.http.middlewares.middleware12.headers.stsseconds=42"
|
||||||
|
@ -127,6 +134,7 @@
|
||||||
- "traefik.http.middlewares.middleware22.replacepathregex.replacement=foobar"
|
- "traefik.http.middlewares.middleware22.replacepathregex.replacement=foobar"
|
||||||
- "traefik.http.middlewares.middleware23.retry.attempts=42"
|
- "traefik.http.middlewares.middleware23.retry.attempts=42"
|
||||||
- "traefik.http.middlewares.middleware23.retry.initialinterval=42s"
|
- "traefik.http.middlewares.middleware23.retry.initialinterval=42s"
|
||||||
|
- "traefik.http.middlewares.middleware24.stripprefix.forceslash=true"
|
||||||
- "traefik.http.middlewares.middleware24.stripprefix.prefixes=foobar, foobar"
|
- "traefik.http.middlewares.middleware24.stripprefix.prefixes=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware25.stripprefixregex.regex=foobar, foobar"
|
- "traefik.http.middlewares.middleware25.stripprefixregex.regex=foobar, foobar"
|
||||||
- "traefik.http.routers.router0.entrypoints=foobar, foobar"
|
- "traefik.http.routers.router0.entrypoints=foobar, foobar"
|
||||||
|
@ -214,6 +222,7 @@
|
||||||
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol=true"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol=true"
|
||||||
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.proxyprotocol.version=42"
|
||||||
- "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.serverstransport=foobar"
|
||||||
|
- "traefik.tcp.services.tcpservice01.loadbalancer.terminationdelay=42"
|
||||||
- "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.server.port=foobar"
|
||||||
- "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true"
|
- "traefik.tcp.services.tcpservice01.loadbalancer.server.tls=true"
|
||||||
- "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar"
|
- "traefik.udp.routers.udprouter0.entrypoints=foobar, foobar"
|
||||||
|
|
|
@ -145,6 +145,7 @@
|
||||||
minResponseBodyBytes = 42
|
minResponseBodyBytes = 42
|
||||||
[http.middlewares.Middleware07]
|
[http.middlewares.Middleware07]
|
||||||
[http.middlewares.Middleware07.contentType]
|
[http.middlewares.Middleware07.contentType]
|
||||||
|
autoDetect = true
|
||||||
[http.middlewares.Middleware08]
|
[http.middlewares.Middleware08]
|
||||||
[http.middlewares.Middleware08.digestAuth]
|
[http.middlewares.Middleware08.digestAuth]
|
||||||
users = ["foobar", "foobar"]
|
users = ["foobar", "foobar"]
|
||||||
|
@ -170,6 +171,7 @@
|
||||||
cert = "foobar"
|
cert = "foobar"
|
||||||
key = "foobar"
|
key = "foobar"
|
||||||
insecureSkipVerify = true
|
insecureSkipVerify = true
|
||||||
|
caOptional = true
|
||||||
[http.middlewares.Middleware11]
|
[http.middlewares.Middleware11]
|
||||||
[http.middlewares.Middleware11.grpcWeb]
|
[http.middlewares.Middleware11.grpcWeb]
|
||||||
allowOrigins = ["foobar", "foobar"]
|
allowOrigins = ["foobar", "foobar"]
|
||||||
|
@ -199,6 +201,11 @@
|
||||||
referrerPolicy = "foobar"
|
referrerPolicy = "foobar"
|
||||||
permissionsPolicy = "foobar"
|
permissionsPolicy = "foobar"
|
||||||
isDevelopment = true
|
isDevelopment = true
|
||||||
|
featurePolicy = "foobar"
|
||||||
|
sslRedirect = true
|
||||||
|
sslTemporaryRedirect = true
|
||||||
|
sslHost = "foobar"
|
||||||
|
sslForceHost = true
|
||||||
[http.middlewares.Middleware12.headers.customRequestHeaders]
|
[http.middlewares.Middleware12.headers.customRequestHeaders]
|
||||||
name0 = "foobar"
|
name0 = "foobar"
|
||||||
name1 = "foobar"
|
name1 = "foobar"
|
||||||
|
@ -298,6 +305,7 @@
|
||||||
[http.middlewares.Middleware24]
|
[http.middlewares.Middleware24]
|
||||||
[http.middlewares.Middleware24.stripPrefix]
|
[http.middlewares.Middleware24.stripPrefix]
|
||||||
prefixes = ["foobar", "foobar"]
|
prefixes = ["foobar", "foobar"]
|
||||||
|
forceSlash = true
|
||||||
[http.middlewares.Middleware25]
|
[http.middlewares.Middleware25]
|
||||||
[http.middlewares.Middleware25.stripPrefixRegex]
|
[http.middlewares.Middleware25.stripPrefixRegex]
|
||||||
regex = ["foobar", "foobar"]
|
regex = ["foobar", "foobar"]
|
||||||
|
@ -395,6 +403,7 @@
|
||||||
[tcp.services.TCPService01]
|
[tcp.services.TCPService01]
|
||||||
[tcp.services.TCPService01.loadBalancer]
|
[tcp.services.TCPService01.loadBalancer]
|
||||||
serversTransport = "foobar"
|
serversTransport = "foobar"
|
||||||
|
terminationDelay = 42
|
||||||
[tcp.services.TCPService01.loadBalancer.proxyProtocol]
|
[tcp.services.TCPService01.loadBalancer.proxyProtocol]
|
||||||
version = 42
|
version = 42
|
||||||
|
|
||||||
|
@ -514,6 +523,7 @@
|
||||||
curvePreferences = ["foobar", "foobar"]
|
curvePreferences = ["foobar", "foobar"]
|
||||||
sniStrict = true
|
sniStrict = true
|
||||||
alpnProtocols = ["foobar", "foobar"]
|
alpnProtocols = ["foobar", "foobar"]
|
||||||
|
preferServerCipherSuites = true
|
||||||
[tls.options.Options0.clientAuth]
|
[tls.options.Options0.clientAuth]
|
||||||
caFiles = ["foobar", "foobar"]
|
caFiles = ["foobar", "foobar"]
|
||||||
clientAuthType = "foobar"
|
clientAuthType = "foobar"
|
||||||
|
@ -524,6 +534,7 @@
|
||||||
curvePreferences = ["foobar", "foobar"]
|
curvePreferences = ["foobar", "foobar"]
|
||||||
sniStrict = true
|
sniStrict = true
|
||||||
alpnProtocols = ["foobar", "foobar"]
|
alpnProtocols = ["foobar", "foobar"]
|
||||||
|
preferServerCipherSuites = true
|
||||||
[tls.options.Options1.clientAuth]
|
[tls.options.Options1.clientAuth]
|
||||||
caFiles = ["foobar", "foobar"]
|
caFiles = ["foobar", "foobar"]
|
||||||
clientAuthType = "foobar"
|
clientAuthType = "foobar"
|
||||||
|
|
|
@ -153,7 +153,8 @@ http:
|
||||||
- foobar
|
- foobar
|
||||||
minResponseBodyBytes: 42
|
minResponseBodyBytes: 42
|
||||||
Middleware07:
|
Middleware07:
|
||||||
contentType: {}
|
contentType:
|
||||||
|
autoDetect: true
|
||||||
Middleware08:
|
Middleware08:
|
||||||
digestAuth:
|
digestAuth:
|
||||||
users:
|
users:
|
||||||
|
@ -178,6 +179,7 @@ http:
|
||||||
cert: foobar
|
cert: foobar
|
||||||
key: foobar
|
key: foobar
|
||||||
insecureSkipVerify: true
|
insecureSkipVerify: true
|
||||||
|
caOptional: true
|
||||||
trustForwardHeader: true
|
trustForwardHeader: true
|
||||||
authResponseHeaders:
|
authResponseHeaders:
|
||||||
- foobar
|
- foobar
|
||||||
|
@ -243,6 +245,11 @@ http:
|
||||||
referrerPolicy: foobar
|
referrerPolicy: foobar
|
||||||
permissionsPolicy: foobar
|
permissionsPolicy: foobar
|
||||||
isDevelopment: true
|
isDevelopment: true
|
||||||
|
featurePolicy: foobar
|
||||||
|
sslRedirect: true
|
||||||
|
sslTemporaryRedirect: true
|
||||||
|
sslHost: foobar
|
||||||
|
sslForceHost: true
|
||||||
Middleware13:
|
Middleware13:
|
||||||
ipAllowList:
|
ipAllowList:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
|
@ -347,6 +354,7 @@ http:
|
||||||
prefixes:
|
prefixes:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
forceSlash: true
|
||||||
Middleware25:
|
Middleware25:
|
||||||
stripPrefixRegex:
|
stripPrefixRegex:
|
||||||
regex:
|
regex:
|
||||||
|
@ -464,6 +472,7 @@ tcp:
|
||||||
- address: foobar
|
- address: foobar
|
||||||
tls: true
|
tls: true
|
||||||
serversTransport: foobar
|
serversTransport: foobar
|
||||||
|
terminationDelay: 42
|
||||||
TCPService02:
|
TCPService02:
|
||||||
weighted:
|
weighted:
|
||||||
services:
|
services:
|
||||||
|
@ -584,6 +593,7 @@ tls:
|
||||||
alpnProtocols:
|
alpnProtocols:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
preferServerCipherSuites: true
|
||||||
Options1:
|
Options1:
|
||||||
minVersion: foobar
|
minVersion: foobar
|
||||||
maxVersion: foobar
|
maxVersion: foobar
|
||||||
|
@ -602,6 +612,7 @@ tls:
|
||||||
alpnProtocols:
|
alpnProtocols:
|
||||||
- foobar
|
- foobar
|
||||||
- foobar
|
- foobar
|
||||||
|
preferServerCipherSuites: true
|
||||||
stores:
|
stores:
|
||||||
Store0:
|
Store0:
|
||||||
defaultCertificate:
|
defaultCertificate:
|
||||||
|
|
|
@ -393,6 +393,18 @@ spec:
|
||||||
between Traefik and your servers. Can only be used on
|
between Traefik and your servers. Can only be used on
|
||||||
a Kubernetes Service.
|
a Kubernetes Service.
|
||||||
type: string
|
type: string
|
||||||
|
terminationDelay:
|
||||||
|
description: 'TerminationDelay defines the deadline that
|
||||||
|
the proxy sets, after one of its connected peers indicates
|
||||||
|
it has closed the writing capability of its connection,
|
||||||
|
to close the reading capability as well, hence fully
|
||||||
|
terminating the connection. It is a duration in milliseconds,
|
||||||
|
defaulting to 100. A negative value means an infinite
|
||||||
|
deadline (i.e. the reading capability is never closed).
|
||||||
|
Deprecated: TerminationDelay is not supported APIVersion
|
||||||
|
traefik.io/v1, please use ServersTransport to configure
|
||||||
|
the TerminationDelay instead.'
|
||||||
|
type: integer
|
||||||
tls:
|
tls:
|
||||||
description: TLS determines whether to use TLS when dialing
|
description: TLS determines whether to use TLS when dialing
|
||||||
with the backend.
|
with the backend.
|
||||||
|
@ -779,9 +791,17 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
contentType:
|
contentType:
|
||||||
description: ContentType holds the content-type middleware configuration.
|
description: ContentType holds the content-type middleware configuration.
|
||||||
This middleware sets the `Content-Type` header value to the media
|
This middleware exists to enable the correct behavior until at least
|
||||||
type detected from the response content, when it is not set by the
|
the default one can be changed in a future version.
|
||||||
backend.
|
properties:
|
||||||
|
autoDetect:
|
||||||
|
description: 'AutoDetect specifies whether to let the `Content-Type`
|
||||||
|
header, if it has not been set by the backend, be automatically
|
||||||
|
set to a value derived from the contents of the response. Deprecated:
|
||||||
|
AutoDetect option is deprecated, Content-Type middleware is
|
||||||
|
only meant to be used to enable the content-type detection,
|
||||||
|
please remove any usage of this option.'
|
||||||
|
type: boolean
|
||||||
type: object
|
type: object
|
||||||
digestAuth:
|
digestAuth:
|
||||||
description: 'DigestAuth holds the digest auth middleware configuration.
|
description: 'DigestAuth holds the digest auth middleware configuration.
|
||||||
|
@ -972,6 +992,10 @@ spec:
|
||||||
description: TLS defines the configuration used to secure the
|
description: TLS defines the configuration used to secure the
|
||||||
connection to the authentication server.
|
connection to the authentication server.
|
||||||
properties:
|
properties:
|
||||||
|
caOptional:
|
||||||
|
description: 'Deprecated: TLS client authentication is a server
|
||||||
|
side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).'
|
||||||
|
type: boolean
|
||||||
caSecret:
|
caSecret:
|
||||||
description: CASecret is the name of the referenced Kubernetes
|
description: CASecret is the name of the referenced Kubernetes
|
||||||
Secret containing the CA to validate the server certificate.
|
Secret containing the CA to validate the server certificate.
|
||||||
|
@ -1090,6 +1114,10 @@ spec:
|
||||||
description: CustomResponseHeaders defines the header names and
|
description: CustomResponseHeaders defines the header names and
|
||||||
values to apply to the response.
|
values to apply to the response.
|
||||||
type: object
|
type: object
|
||||||
|
featurePolicy:
|
||||||
|
description: 'Deprecated: FeaturePolicy option is deprecated,
|
||||||
|
please use PermissionsPolicy instead.'
|
||||||
|
type: string
|
||||||
forceSTSHeader:
|
forceSTSHeader:
|
||||||
description: ForceSTSHeader defines whether to add the STS header
|
description: ForceSTSHeader defines whether to add the STS header
|
||||||
even when the connection is HTTP.
|
even when the connection is HTTP.
|
||||||
|
@ -1125,6 +1153,14 @@ spec:
|
||||||
value. This allows sites to control whether browsers forward
|
value. This allows sites to control whether browsers forward
|
||||||
the Referer header to other sites.
|
the Referer header to other sites.
|
||||||
type: string
|
type: string
|
||||||
|
sslForceHost:
|
||||||
|
description: 'Deprecated: SSLForceHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: boolean
|
||||||
|
sslHost:
|
||||||
|
description: 'Deprecated: SSLHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: string
|
||||||
sslProxyHeaders:
|
sslProxyHeaders:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1133,6 +1169,14 @@ spec:
|
||||||
useful when using other proxies (example: "X-Forwarded-Proto":
|
useful when using other proxies (example: "X-Forwarded-Proto":
|
||||||
"https").'
|
"https").'
|
||||||
type: object
|
type: object
|
||||||
|
sslRedirect:
|
||||||
|
description: 'Deprecated: SSLRedirect option is deprecated, please
|
||||||
|
use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
|
sslTemporaryRedirect:
|
||||||
|
description: 'Deprecated: SSLTemporaryRedirect option is deprecated,
|
||||||
|
please use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
stsIncludeSubdomains:
|
stsIncludeSubdomains:
|
||||||
description: STSIncludeSubdomains defines whether the includeSubDomains
|
description: STSIncludeSubdomains defines whether the includeSubDomains
|
||||||
directive is appended to the Strict-Transport-Security header.
|
directive is appended to the Strict-Transport-Security header.
|
||||||
|
@ -1504,6 +1548,12 @@ spec:
|
||||||
This middleware removes the specified prefixes from the URL path.
|
This middleware removes the specified prefixes from the URL path.
|
||||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
||||||
properties:
|
properties:
|
||||||
|
forceSlash:
|
||||||
|
description: 'Deprecated: ForceSlash option is deprecated, please
|
||||||
|
remove any usage of this option. ForceSlash ensures that the
|
||||||
|
resulting stripped path is not the empty string, by replacing
|
||||||
|
it with / when necessary. Default: true.'
|
||||||
|
type: boolean
|
||||||
prefixes:
|
prefixes:
|
||||||
description: Prefixes defines the prefixes to strip from the request
|
description: Prefixes defines the prefixes to strip from the request
|
||||||
URL.
|
URL.
|
||||||
|
@ -1578,7 +1628,9 @@ spec:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
ipAllowList:
|
ipAllowList:
|
||||||
description: IPAllowList defines the IPAllowList middleware configuration.
|
description: 'IPAllowList defines the IPAllowList middleware configuration.
|
||||||
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
@ -1589,7 +1641,8 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
ipWhiteList:
|
ipWhiteList:
|
||||||
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
||||||
Deprecated: please use IPAllowList instead.'
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipwhitelist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
@ -1940,6 +1993,12 @@ spec:
|
||||||
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
||||||
VersionTLS13. Default: VersionTLS10.'
|
VersionTLS13. Default: VersionTLS10.'
|
||||||
type: string
|
type: string
|
||||||
|
preferServerCipherSuites:
|
||||||
|
description: 'PreferServerCipherSuites defines whether the server
|
||||||
|
chooses a cipher suite among his own instead of among the client''s.
|
||||||
|
It is enabled automatically when minVersion or maxVersion is set.
|
||||||
|
Deprecated: https://github.com/golang/go/issues/45430'
|
||||||
|
type: boolean
|
||||||
sniStrict:
|
sniStrict:
|
||||||
description: SniStrict defines whether Traefik allows connections
|
description: SniStrict defines whether Traefik allows connections
|
||||||
from clients connections that do not specify a server_name extension.
|
from clients connections that do not specify a server_name extension.
|
||||||
|
|
|
@ -26,7 +26,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware06/compress/includedContentTypes/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware06/compress/minResponseBodyBytes` | `42` |
|
| `traefik/http/middlewares/Middleware06/compress/minResponseBodyBytes` | `42` |
|
||||||
| `traefik/http/middlewares/Middleware07/contentType` | `` |
|
| `traefik/http/middlewares/Middleware07/contentType/autoDetect` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware08/digestAuth/headerField` | `foobar` |
|
| `traefik/http/middlewares/Middleware08/digestAuth/headerField` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware08/digestAuth/realm` | `foobar` |
|
| `traefik/http/middlewares/Middleware08/digestAuth/realm` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware08/digestAuth/removeHeader` | `true` |
|
| `traefik/http/middlewares/Middleware08/digestAuth/removeHeader` | `true` |
|
||||||
|
@ -46,6 +46,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeaders/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeadersRegex` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/authResponseHeadersRegex` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/ca` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/ca` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/caOptional` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/cert` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/cert` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/insecureSkipVerify` | `true` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/insecureSkipVerify` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/key` | `foobar` |
|
| `traefik/http/middlewares/Middleware10/forwardAuth/tls/key` | `foobar` |
|
||||||
|
@ -76,6 +77,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name1` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/customRequestHeaders/name1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name0` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name1` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/customResponseHeaders/name1` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/headers/featurePolicy` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/forceSTSHeader` | `true` |
|
| `traefik/http/middlewares/Middleware12/headers/forceSTSHeader` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/frameDeny` | `true` |
|
| `traefik/http/middlewares/Middleware12/headers/frameDeny` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/hostsProxyHeaders/0` | `foobar` |
|
||||||
|
@ -84,8 +86,12 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/http/middlewares/Middleware12/headers/permissionsPolicy` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/permissionsPolicy` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/publicKey` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/publicKey` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/referrerPolicy` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/referrerPolicy` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/headers/sslForceHost` | `true` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/headers/sslHost` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name0` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name1` | `foobar` |
|
| `traefik/http/middlewares/Middleware12/headers/sslProxyHeaders/name1` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/headers/sslRedirect` | `true` |
|
||||||
|
| `traefik/http/middlewares/Middleware12/headers/sslTemporaryRedirect` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/stsIncludeSubdomains` | `true` |
|
| `traefik/http/middlewares/Middleware12/headers/stsIncludeSubdomains` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/stsPreload` | `true` |
|
| `traefik/http/middlewares/Middleware12/headers/stsPreload` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware12/headers/stsSeconds` | `42` |
|
| `traefik/http/middlewares/Middleware12/headers/stsSeconds` | `42` |
|
||||||
|
@ -149,6 +155,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/http/middlewares/Middleware22/replacePathRegex/replacement` | `foobar` |
|
| `traefik/http/middlewares/Middleware22/replacePathRegex/replacement` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware23/retry/attempts` | `42` |
|
| `traefik/http/middlewares/Middleware23/retry/attempts` | `42` |
|
||||||
| `traefik/http/middlewares/Middleware23/retry/initialInterval` | `42s` |
|
| `traefik/http/middlewares/Middleware23/retry/initialInterval` | `42s` |
|
||||||
|
| `traefik/http/middlewares/Middleware24/stripPrefix/forceSlash` | `true` |
|
||||||
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware24/stripPrefix/prefixes/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware25/stripPrefixRegex/regex/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware25/stripPrefixRegex/regex/0` | `foobar` |
|
||||||
|
@ -342,6 +349,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/tcp/services/TCPService01/loadBalancer/servers/1/address` | `foobar` |
|
| `traefik/tcp/services/TCPService01/loadBalancer/servers/1/address` | `foobar` |
|
||||||
| `traefik/tcp/services/TCPService01/loadBalancer/servers/1/tls` | `true` |
|
| `traefik/tcp/services/TCPService01/loadBalancer/servers/1/tls` | `true` |
|
||||||
| `traefik/tcp/services/TCPService01/loadBalancer/serversTransport` | `foobar` |
|
| `traefik/tcp/services/TCPService01/loadBalancer/serversTransport` | `foobar` |
|
||||||
|
| `traefik/tcp/services/TCPService01/loadBalancer/terminationDelay` | `42` |
|
||||||
| `traefik/tcp/services/TCPService02/weighted/services/0/name` | `foobar` |
|
| `traefik/tcp/services/TCPService02/weighted/services/0/name` | `foobar` |
|
||||||
| `traefik/tcp/services/TCPService02/weighted/services/0/weight` | `42` |
|
| `traefik/tcp/services/TCPService02/weighted/services/0/weight` | `42` |
|
||||||
| `traefik/tcp/services/TCPService02/weighted/services/1/name` | `foobar` |
|
| `traefik/tcp/services/TCPService02/weighted/services/1/name` | `foobar` |
|
||||||
|
@ -365,6 +373,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/tls/options/Options0/curvePreferences/1` | `foobar` |
|
| `traefik/tls/options/Options0/curvePreferences/1` | `foobar` |
|
||||||
| `traefik/tls/options/Options0/maxVersion` | `foobar` |
|
| `traefik/tls/options/Options0/maxVersion` | `foobar` |
|
||||||
| `traefik/tls/options/Options0/minVersion` | `foobar` |
|
| `traefik/tls/options/Options0/minVersion` | `foobar` |
|
||||||
|
| `traefik/tls/options/Options0/preferServerCipherSuites` | `true` |
|
||||||
| `traefik/tls/options/Options0/sniStrict` | `true` |
|
| `traefik/tls/options/Options0/sniStrict` | `true` |
|
||||||
| `traefik/tls/options/Options1/alpnProtocols/0` | `foobar` |
|
| `traefik/tls/options/Options1/alpnProtocols/0` | `foobar` |
|
||||||
| `traefik/tls/options/Options1/alpnProtocols/1` | `foobar` |
|
| `traefik/tls/options/Options1/alpnProtocols/1` | `foobar` |
|
||||||
|
@ -377,6 +386,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
| `traefik/tls/options/Options1/curvePreferences/1` | `foobar` |
|
| `traefik/tls/options/Options1/curvePreferences/1` | `foobar` |
|
||||||
| `traefik/tls/options/Options1/maxVersion` | `foobar` |
|
| `traefik/tls/options/Options1/maxVersion` | `foobar` |
|
||||||
| `traefik/tls/options/Options1/minVersion` | `foobar` |
|
| `traefik/tls/options/Options1/minVersion` | `foobar` |
|
||||||
|
| `traefik/tls/options/Options1/preferServerCipherSuites` | `true` |
|
||||||
| `traefik/tls/options/Options1/sniStrict` | `true` |
|
| `traefik/tls/options/Options1/sniStrict` | `true` |
|
||||||
| `traefik/tls/stores/Store0/defaultCertificate/certFile` | `foobar` |
|
| `traefik/tls/stores/Store0/defaultCertificate/certFile` | `foobar` |
|
||||||
| `traefik/tls/stores/Store0/defaultCertificate/keyFile` | `foobar` |
|
| `traefik/tls/stores/Store0/defaultCertificate/keyFile` | `foobar` |
|
||||||
|
|
|
@ -116,6 +116,18 @@ spec:
|
||||||
between Traefik and your servers. Can only be used on
|
between Traefik and your servers. Can only be used on
|
||||||
a Kubernetes Service.
|
a Kubernetes Service.
|
||||||
type: string
|
type: string
|
||||||
|
terminationDelay:
|
||||||
|
description: 'TerminationDelay defines the deadline that
|
||||||
|
the proxy sets, after one of its connected peers indicates
|
||||||
|
it has closed the writing capability of its connection,
|
||||||
|
to close the reading capability as well, hence fully
|
||||||
|
terminating the connection. It is a duration in milliseconds,
|
||||||
|
defaulting to 100. A negative value means an infinite
|
||||||
|
deadline (i.e. the reading capability is never closed).
|
||||||
|
Deprecated: TerminationDelay is not supported APIVersion
|
||||||
|
traefik.io/v1, please use ServersTransport to configure
|
||||||
|
the TerminationDelay instead.'
|
||||||
|
type: integer
|
||||||
tls:
|
tls:
|
||||||
description: TLS determines whether to use TLS when dialing
|
description: TLS determines whether to use TLS when dialing
|
||||||
with the backend.
|
with the backend.
|
||||||
|
|
|
@ -190,9 +190,17 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
contentType:
|
contentType:
|
||||||
description: ContentType holds the content-type middleware configuration.
|
description: ContentType holds the content-type middleware configuration.
|
||||||
This middleware sets the `Content-Type` header value to the media
|
This middleware exists to enable the correct behavior until at least
|
||||||
type detected from the response content, when it is not set by the
|
the default one can be changed in a future version.
|
||||||
backend.
|
properties:
|
||||||
|
autoDetect:
|
||||||
|
description: 'AutoDetect specifies whether to let the `Content-Type`
|
||||||
|
header, if it has not been set by the backend, be automatically
|
||||||
|
set to a value derived from the contents of the response. Deprecated:
|
||||||
|
AutoDetect option is deprecated, Content-Type middleware is
|
||||||
|
only meant to be used to enable the content-type detection,
|
||||||
|
please remove any usage of this option.'
|
||||||
|
type: boolean
|
||||||
type: object
|
type: object
|
||||||
digestAuth:
|
digestAuth:
|
||||||
description: 'DigestAuth holds the digest auth middleware configuration.
|
description: 'DigestAuth holds the digest auth middleware configuration.
|
||||||
|
@ -383,6 +391,10 @@ spec:
|
||||||
description: TLS defines the configuration used to secure the
|
description: TLS defines the configuration used to secure the
|
||||||
connection to the authentication server.
|
connection to the authentication server.
|
||||||
properties:
|
properties:
|
||||||
|
caOptional:
|
||||||
|
description: 'Deprecated: TLS client authentication is a server
|
||||||
|
side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).'
|
||||||
|
type: boolean
|
||||||
caSecret:
|
caSecret:
|
||||||
description: CASecret is the name of the referenced Kubernetes
|
description: CASecret is the name of the referenced Kubernetes
|
||||||
Secret containing the CA to validate the server certificate.
|
Secret containing the CA to validate the server certificate.
|
||||||
|
@ -501,6 +513,10 @@ spec:
|
||||||
description: CustomResponseHeaders defines the header names and
|
description: CustomResponseHeaders defines the header names and
|
||||||
values to apply to the response.
|
values to apply to the response.
|
||||||
type: object
|
type: object
|
||||||
|
featurePolicy:
|
||||||
|
description: 'Deprecated: FeaturePolicy option is deprecated,
|
||||||
|
please use PermissionsPolicy instead.'
|
||||||
|
type: string
|
||||||
forceSTSHeader:
|
forceSTSHeader:
|
||||||
description: ForceSTSHeader defines whether to add the STS header
|
description: ForceSTSHeader defines whether to add the STS header
|
||||||
even when the connection is HTTP.
|
even when the connection is HTTP.
|
||||||
|
@ -536,6 +552,14 @@ spec:
|
||||||
value. This allows sites to control whether browsers forward
|
value. This allows sites to control whether browsers forward
|
||||||
the Referer header to other sites.
|
the Referer header to other sites.
|
||||||
type: string
|
type: string
|
||||||
|
sslForceHost:
|
||||||
|
description: 'Deprecated: SSLForceHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: boolean
|
||||||
|
sslHost:
|
||||||
|
description: 'Deprecated: SSLHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: string
|
||||||
sslProxyHeaders:
|
sslProxyHeaders:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
@ -544,6 +568,14 @@ spec:
|
||||||
useful when using other proxies (example: "X-Forwarded-Proto":
|
useful when using other proxies (example: "X-Forwarded-Proto":
|
||||||
"https").'
|
"https").'
|
||||||
type: object
|
type: object
|
||||||
|
sslRedirect:
|
||||||
|
description: 'Deprecated: SSLRedirect option is deprecated, please
|
||||||
|
use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
|
sslTemporaryRedirect:
|
||||||
|
description: 'Deprecated: SSLTemporaryRedirect option is deprecated,
|
||||||
|
please use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
stsIncludeSubdomains:
|
stsIncludeSubdomains:
|
||||||
description: STSIncludeSubdomains defines whether the includeSubDomains
|
description: STSIncludeSubdomains defines whether the includeSubDomains
|
||||||
directive is appended to the Strict-Transport-Security header.
|
directive is appended to the Strict-Transport-Security header.
|
||||||
|
@ -915,6 +947,12 @@ spec:
|
||||||
This middleware removes the specified prefixes from the URL path.
|
This middleware removes the specified prefixes from the URL path.
|
||||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
||||||
properties:
|
properties:
|
||||||
|
forceSlash:
|
||||||
|
description: 'Deprecated: ForceSlash option is deprecated, please
|
||||||
|
remove any usage of this option. ForceSlash ensures that the
|
||||||
|
resulting stripped path is not the empty string, by replacing
|
||||||
|
it with / when necessary. Default: true.'
|
||||||
|
type: boolean
|
||||||
prefixes:
|
prefixes:
|
||||||
description: Prefixes defines the prefixes to strip from the request
|
description: Prefixes defines the prefixes to strip from the request
|
||||||
URL.
|
URL.
|
||||||
|
|
|
@ -46,7 +46,9 @@ spec:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
ipAllowList:
|
ipAllowList:
|
||||||
description: IPAllowList defines the IPAllowList middleware configuration.
|
description: 'IPAllowList defines the IPAllowList middleware configuration.
|
||||||
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
@ -57,7 +59,8 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
ipWhiteList:
|
ipWhiteList:
|
||||||
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
||||||
Deprecated: please use IPAllowList instead.'
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipwhitelist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
|
|
@ -86,6 +86,12 @@ spec:
|
||||||
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
||||||
VersionTLS13. Default: VersionTLS10.'
|
VersionTLS13. Default: VersionTLS10.'
|
||||||
type: string
|
type: string
|
||||||
|
preferServerCipherSuites:
|
||||||
|
description: 'PreferServerCipherSuites defines whether the server
|
||||||
|
chooses a cipher suite among his own instead of among the client''s.
|
||||||
|
It is enabled automatically when minVersion or maxVersion is set.
|
||||||
|
Deprecated: https://github.com/golang/go/issues/45430'
|
||||||
|
type: boolean
|
||||||
sniStrict:
|
sniStrict:
|
||||||
description: SniStrict defines whether Traefik allows connections
|
description: SniStrict defines whether Traefik allows connections
|
||||||
from clients connections that do not specify a server_name extension.
|
from clients connections that do not specify a server_name extension.
|
||||||
|
|
|
@ -1617,6 +1617,46 @@ Below are the available options for the PROXY protocol:
|
||||||
version = 1
|
version = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Termination Delay
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Deprecated in favor of [`serversTransport.terminationDelay`](#terminationdelay).
|
||||||
|
Please note that if any `serversTransport` configuration on the servers load balancer is found,
|
||||||
|
it will take precedence over the servers load balancer `terminationDelay` value,
|
||||||
|
even if the `serversTransport.terminationDelay` is undefined.
|
||||||
|
|
||||||
|
As a proxy between a client and a server, it can happen that either side (e.g. client side) decides to terminate its writing capability on the connection (i.e. issuance of a FIN packet).
|
||||||
|
The proxy needs to propagate that intent to the other side, and so when that happens, it also does the same on its connection with the other side (e.g. backend side).
|
||||||
|
|
||||||
|
However, if for some reason (bad implementation, or malicious intent) the other side does not eventually do the same as well,
|
||||||
|
the connection would stay half-open, which would lock resources for however long.
|
||||||
|
|
||||||
|
To that end, as soon as the proxy enters this termination sequence, it sets a deadline on fully terminating the connections on both sides.
|
||||||
|
|
||||||
|
The termination delay controls that deadline.
|
||||||
|
It is a duration in milliseconds, defaulting to 100.
|
||||||
|
A negative value means an infinite deadline (i.e. the connection is never fully terminated by the proxy itself).
|
||||||
|
|
||||||
|
??? example "A Service with a termination delay -- Using the [File Provider](../../providers/file.md)"
|
||||||
|
|
||||||
|
```yaml tab="YAML"
|
||||||
|
## Dynamic configuration
|
||||||
|
tcp:
|
||||||
|
services:
|
||||||
|
my-service:
|
||||||
|
loadBalancer:
|
||||||
|
terminationDelay: 200
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="TOML"
|
||||||
|
## Dynamic configuration
|
||||||
|
[tcp.services]
|
||||||
|
[tcp.services.my-service.loadBalancer]
|
||||||
|
[[tcp.services.my-service.loadBalancer]]
|
||||||
|
terminationDelay = 200
|
||||||
|
```
|
||||||
|
|
||||||
### Weighted Round Robin
|
### Weighted Round Robin
|
||||||
|
|
||||||
The Weighted Round Robin (alias `WRR`) load-balancer of services is in charge of balancing the requests between multiple services based on provided weights.
|
The Weighted Round Robin (alias `WRR`) load-balancer of services is in charge of balancing the requests between multiple services based on provided weights.
|
||||||
|
|
|
@ -393,6 +393,18 @@ spec:
|
||||||
between Traefik and your servers. Can only be used on
|
between Traefik and your servers. Can only be used on
|
||||||
a Kubernetes Service.
|
a Kubernetes Service.
|
||||||
type: string
|
type: string
|
||||||
|
terminationDelay:
|
||||||
|
description: 'TerminationDelay defines the deadline that
|
||||||
|
the proxy sets, after one of its connected peers indicates
|
||||||
|
it has closed the writing capability of its connection,
|
||||||
|
to close the reading capability as well, hence fully
|
||||||
|
terminating the connection. It is a duration in milliseconds,
|
||||||
|
defaulting to 100. A negative value means an infinite
|
||||||
|
deadline (i.e. the reading capability is never closed).
|
||||||
|
Deprecated: TerminationDelay is not supported APIVersion
|
||||||
|
traefik.io/v1, please use ServersTransport to configure
|
||||||
|
the TerminationDelay instead.'
|
||||||
|
type: integer
|
||||||
tls:
|
tls:
|
||||||
description: TLS determines whether to use TLS when dialing
|
description: TLS determines whether to use TLS when dialing
|
||||||
with the backend.
|
with the backend.
|
||||||
|
@ -779,9 +791,17 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
contentType:
|
contentType:
|
||||||
description: ContentType holds the content-type middleware configuration.
|
description: ContentType holds the content-type middleware configuration.
|
||||||
This middleware sets the `Content-Type` header value to the media
|
This middleware exists to enable the correct behavior until at least
|
||||||
type detected from the response content, when it is not set by the
|
the default one can be changed in a future version.
|
||||||
backend.
|
properties:
|
||||||
|
autoDetect:
|
||||||
|
description: 'AutoDetect specifies whether to let the `Content-Type`
|
||||||
|
header, if it has not been set by the backend, be automatically
|
||||||
|
set to a value derived from the contents of the response. Deprecated:
|
||||||
|
AutoDetect option is deprecated, Content-Type middleware is
|
||||||
|
only meant to be used to enable the content-type detection,
|
||||||
|
please remove any usage of this option.'
|
||||||
|
type: boolean
|
||||||
type: object
|
type: object
|
||||||
digestAuth:
|
digestAuth:
|
||||||
description: 'DigestAuth holds the digest auth middleware configuration.
|
description: 'DigestAuth holds the digest auth middleware configuration.
|
||||||
|
@ -972,6 +992,10 @@ spec:
|
||||||
description: TLS defines the configuration used to secure the
|
description: TLS defines the configuration used to secure the
|
||||||
connection to the authentication server.
|
connection to the authentication server.
|
||||||
properties:
|
properties:
|
||||||
|
caOptional:
|
||||||
|
description: 'Deprecated: TLS client authentication is a server
|
||||||
|
side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).'
|
||||||
|
type: boolean
|
||||||
caSecret:
|
caSecret:
|
||||||
description: CASecret is the name of the referenced Kubernetes
|
description: CASecret is the name of the referenced Kubernetes
|
||||||
Secret containing the CA to validate the server certificate.
|
Secret containing the CA to validate the server certificate.
|
||||||
|
@ -1090,6 +1114,10 @@ spec:
|
||||||
description: CustomResponseHeaders defines the header names and
|
description: CustomResponseHeaders defines the header names and
|
||||||
values to apply to the response.
|
values to apply to the response.
|
||||||
type: object
|
type: object
|
||||||
|
featurePolicy:
|
||||||
|
description: 'Deprecated: FeaturePolicy option is deprecated,
|
||||||
|
please use PermissionsPolicy instead.'
|
||||||
|
type: string
|
||||||
forceSTSHeader:
|
forceSTSHeader:
|
||||||
description: ForceSTSHeader defines whether to add the STS header
|
description: ForceSTSHeader defines whether to add the STS header
|
||||||
even when the connection is HTTP.
|
even when the connection is HTTP.
|
||||||
|
@ -1125,6 +1153,14 @@ spec:
|
||||||
value. This allows sites to control whether browsers forward
|
value. This allows sites to control whether browsers forward
|
||||||
the Referer header to other sites.
|
the Referer header to other sites.
|
||||||
type: string
|
type: string
|
||||||
|
sslForceHost:
|
||||||
|
description: 'Deprecated: SSLForceHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: boolean
|
||||||
|
sslHost:
|
||||||
|
description: 'Deprecated: SSLHost option is deprecated, please
|
||||||
|
use RedirectRegex instead.'
|
||||||
|
type: string
|
||||||
sslProxyHeaders:
|
sslProxyHeaders:
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
@ -1133,6 +1169,14 @@ spec:
|
||||||
useful when using other proxies (example: "X-Forwarded-Proto":
|
useful when using other proxies (example: "X-Forwarded-Proto":
|
||||||
"https").'
|
"https").'
|
||||||
type: object
|
type: object
|
||||||
|
sslRedirect:
|
||||||
|
description: 'Deprecated: SSLRedirect option is deprecated, please
|
||||||
|
use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
|
sslTemporaryRedirect:
|
||||||
|
description: 'Deprecated: SSLTemporaryRedirect option is deprecated,
|
||||||
|
please use EntryPoint redirection or RedirectScheme instead.'
|
||||||
|
type: boolean
|
||||||
stsIncludeSubdomains:
|
stsIncludeSubdomains:
|
||||||
description: STSIncludeSubdomains defines whether the includeSubDomains
|
description: STSIncludeSubdomains defines whether the includeSubDomains
|
||||||
directive is appended to the Strict-Transport-Security header.
|
directive is appended to the Strict-Transport-Security header.
|
||||||
|
@ -1504,6 +1548,12 @@ spec:
|
||||||
This middleware removes the specified prefixes from the URL path.
|
This middleware removes the specified prefixes from the URL path.
|
||||||
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/stripprefix/'
|
||||||
properties:
|
properties:
|
||||||
|
forceSlash:
|
||||||
|
description: 'Deprecated: ForceSlash option is deprecated, please
|
||||||
|
remove any usage of this option. ForceSlash ensures that the
|
||||||
|
resulting stripped path is not the empty string, by replacing
|
||||||
|
it with / when necessary. Default: true.'
|
||||||
|
type: boolean
|
||||||
prefixes:
|
prefixes:
|
||||||
description: Prefixes defines the prefixes to strip from the request
|
description: Prefixes defines the prefixes to strip from the request
|
||||||
URL.
|
URL.
|
||||||
|
@ -1578,7 +1628,9 @@ spec:
|
||||||
type: integer
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
ipAllowList:
|
ipAllowList:
|
||||||
description: IPAllowList defines the IPAllowList middleware configuration.
|
description: 'IPAllowList defines the IPAllowList middleware configuration.
|
||||||
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
@ -1589,7 +1641,8 @@ spec:
|
||||||
type: object
|
type: object
|
||||||
ipWhiteList:
|
ipWhiteList:
|
||||||
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
description: 'IPWhiteList defines the IPWhiteList middleware configuration.
|
||||||
Deprecated: please use IPAllowList instead.'
|
This middleware accepts/refuses connections based on the client
|
||||||
|
IP. Deprecated: please use IPAllowList instead. More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipwhitelist/'
|
||||||
properties:
|
properties:
|
||||||
sourceRange:
|
sourceRange:
|
||||||
description: SourceRange defines the allowed IPs (or ranges of
|
description: SourceRange defines the allowed IPs (or ranges of
|
||||||
|
@ -1940,6 +1993,12 @@ spec:
|
||||||
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
||||||
VersionTLS13. Default: VersionTLS10.'
|
VersionTLS13. Default: VersionTLS10.'
|
||||||
type: string
|
type: string
|
||||||
|
preferServerCipherSuites:
|
||||||
|
description: 'PreferServerCipherSuites defines whether the server
|
||||||
|
chooses a cipher suite among his own instead of among the client''s.
|
||||||
|
It is enabled automatically when minVersion or maxVersion is set.
|
||||||
|
Deprecated: https://github.com/golang/go/issues/45430'
|
||||||
|
type: boolean
|
||||||
sniStrict:
|
sniStrict:
|
||||||
description: SniStrict defines whether Traefik allows connections
|
description: SniStrict defines whether Traefik allows connections
|
||||||
from clients connections that do not specify a server_name extension.
|
from clients connections that do not specify a server_name extension.
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
ptypes "github.com/traefik/paerser/types"
|
ptypes "github.com/traefik/paerser/types"
|
||||||
"github.com/traefik/traefik/v3/pkg/ip"
|
"github.com/traefik/traefik/v3/pkg/ip"
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -55,9 +54,13 @@ type GrpcWeb struct {
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// ContentType holds the content-type middleware configuration.
|
// ContentType holds the content-type middleware configuration.
|
||||||
// This middleware sets the `Content-Type` header value to the media type detected from the response content,
|
// This middleware exists to enable the correct behavior until at least the default one can be changed in a future version.
|
||||||
// when it is not set by the backend.
|
type ContentType struct {
|
||||||
type ContentType struct{}
|
// AutoDetect specifies whether to let the `Content-Type` header, if it has not been set by the backend,
|
||||||
|
// be automatically set to a value derived from the contents of the response.
|
||||||
|
// Deprecated: AutoDetect option is deprecated, Content-Type middleware is only meant to be used to enable the content-type detection, please remove any usage of this option.
|
||||||
|
AutoDetect *bool `json:"autoDetect,omitempty" toml:"autoDetect,omitempty" yaml:"autoDetect,omitempty" export:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
@ -218,7 +221,7 @@ type ForwardAuth struct {
|
||||||
// Address defines the authentication server address.
|
// Address defines the authentication server address.
|
||||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
||||||
// TLS defines the configuration used to secure the connection to the authentication server.
|
// TLS defines the configuration used to secure the connection to the authentication server.
|
||||||
TLS *types.ClientTLS `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
TLS *ClientTLS `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
||||||
// TrustForwardHeader defines whether to trust (ie: forward) all X-Forwarded-* headers.
|
// TrustForwardHeader defines whether to trust (ie: forward) all X-Forwarded-* headers.
|
||||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty" toml:"trustForwardHeader,omitempty" yaml:"trustForwardHeader,omitempty" export:"true"`
|
TrustForwardHeader bool `json:"trustForwardHeader,omitempty" toml:"trustForwardHeader,omitempty" yaml:"trustForwardHeader,omitempty" export:"true"`
|
||||||
// AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers.
|
// AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers.
|
||||||
|
@ -235,6 +238,20 @@ type ForwardAuth struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// ClientTLS holds TLS specific configurations as client
|
||||||
|
// CA, Cert and Key can be either path or file contents.
|
||||||
|
// TODO: remove this struct when CAOptional option will be removed.
|
||||||
|
type ClientTLS struct {
|
||||||
|
CA string `description:"TLS CA" json:"ca,omitempty" toml:"ca,omitempty" yaml:"ca,omitempty"`
|
||||||
|
Cert string `description:"TLS cert" json:"cert,omitempty" toml:"cert,omitempty" yaml:"cert,omitempty"`
|
||||||
|
Key string `description:"TLS key" json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty" loggable:"false"`
|
||||||
|
InsecureSkipVerify bool `description:"TLS insecure skip verify" json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"`
|
||||||
|
// Deprecated: TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).
|
||||||
|
CAOptional *bool `description:"TLS CA.Optional" json:"caOptional,omitempty" toml:"caOptional,omitempty" yaml:"caOptional,omitempty" export:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Headers holds the headers middleware configuration.
|
// Headers holds the headers middleware configuration.
|
||||||
// This middleware manages the requests and responses headers.
|
// This middleware manages the requests and responses headers.
|
||||||
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/headers/#customrequestheaders
|
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/http/headers/#customrequestheaders
|
||||||
|
@ -303,6 +320,17 @@ type Headers struct {
|
||||||
// If you would like your development environment to mimic production with complete Host blocking, SSL redirects,
|
// If you would like your development environment to mimic production with complete Host blocking, SSL redirects,
|
||||||
// and STS headers, leave this as false.
|
// and STS headers, leave this as false.
|
||||||
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"`
|
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// Deprecated: FeaturePolicy option is deprecated, please use PermissionsPolicy instead.
|
||||||
|
FeaturePolicy *string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty" export:"true"`
|
||||||
|
// Deprecated: SSLRedirect option is deprecated, please use EntryPoint redirection or RedirectScheme instead.
|
||||||
|
SSLRedirect *bool `json:"sslRedirect,omitempty" toml:"sslRedirect,omitempty" yaml:"sslRedirect,omitempty" export:"true"`
|
||||||
|
// Deprecated: SSLTemporaryRedirect option is deprecated, please use EntryPoint redirection or RedirectScheme instead.
|
||||||
|
SSLTemporaryRedirect *bool `json:"sslTemporaryRedirect,omitempty" toml:"sslTemporaryRedirect,omitempty" yaml:"sslTemporaryRedirect,omitempty" export:"true"`
|
||||||
|
// Deprecated: SSLHost option is deprecated, please use RedirectRegex instead.
|
||||||
|
SSLHost *string `json:"sslHost,omitempty" toml:"sslHost,omitempty" yaml:"sslHost,omitempty"`
|
||||||
|
// Deprecated: SSLForceHost option is deprecated, please use RedirectRegex instead.
|
||||||
|
SSLForceHost *bool `json:"sslForceHost,omitempty" toml:"sslForceHost,omitempty" yaml:"sslForceHost,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set.
|
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set.
|
||||||
|
@ -327,6 +355,10 @@ func (h *Headers) HasCorsHeadersDefined() bool {
|
||||||
func (h *Headers) HasSecureHeadersDefined() bool {
|
func (h *Headers) HasSecureHeadersDefined() bool {
|
||||||
return h != nil && (len(h.AllowedHosts) != 0 ||
|
return h != nil && (len(h.AllowedHosts) != 0 ||
|
||||||
len(h.HostsProxyHeaders) != 0 ||
|
len(h.HostsProxyHeaders) != 0 ||
|
||||||
|
(h.SSLRedirect != nil && *h.SSLRedirect) ||
|
||||||
|
(h.SSLTemporaryRedirect != nil && *h.SSLTemporaryRedirect) ||
|
||||||
|
(h.SSLForceHost != nil && *h.SSLForceHost) ||
|
||||||
|
(h.SSLHost != nil && *h.SSLHost != "") ||
|
||||||
len(h.SSLProxyHeaders) != 0 ||
|
len(h.SSLProxyHeaders) != 0 ||
|
||||||
h.STSSeconds != 0 ||
|
h.STSSeconds != 0 ||
|
||||||
h.STSIncludeSubdomains ||
|
h.STSIncludeSubdomains ||
|
||||||
|
@ -340,6 +372,7 @@ func (h *Headers) HasSecureHeadersDefined() bool {
|
||||||
h.ContentSecurityPolicy != "" ||
|
h.ContentSecurityPolicy != "" ||
|
||||||
h.PublicKey != "" ||
|
h.PublicKey != "" ||
|
||||||
h.ReferrerPolicy != "" ||
|
h.ReferrerPolicy != "" ||
|
||||||
|
(h.FeaturePolicy != nil && *h.FeaturePolicy != "") ||
|
||||||
h.PermissionsPolicy != "" ||
|
h.PermissionsPolicy != "" ||
|
||||||
h.IsDevelopment)
|
h.IsDevelopment)
|
||||||
}
|
}
|
||||||
|
@ -557,6 +590,11 @@ type Retry struct {
|
||||||
type StripPrefix struct {
|
type StripPrefix struct {
|
||||||
// Prefixes defines the prefixes to strip from the request URL.
|
// Prefixes defines the prefixes to strip from the request URL.
|
||||||
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty" export:"true"`
|
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// Deprecated: ForceSlash option is deprecated, please remove any usage of this option.
|
||||||
|
// ForceSlash ensures that the resulting stripped path is not the empty string, by replacing it with / when necessary.
|
||||||
|
// Default: true.
|
||||||
|
ForceSlash *bool `json:"forceSlash,omitempty" toml:"forceSlash,omitempty" yaml:"forceSlash,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -86,6 +86,14 @@ type TCPServersLoadBalancer struct {
|
||||||
ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||||
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server" export:"true"`
|
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server" export:"true"`
|
||||||
ServersTransport string `json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"`
|
ServersTransport string `json:"serversTransport,omitempty" toml:"serversTransport,omitempty" yaml:"serversTransport,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// TerminationDelay, corresponds to the deadline that the proxy sets, after one
|
||||||
|
// of its connected peers indicates it has closed the writing capability of its
|
||||||
|
// connection, to close the reading capability as well, hence fully terminating the
|
||||||
|
// connection. It is a duration in milliseconds, defaulting to 100. A negative value
|
||||||
|
// means an infinite deadline (i.e. the reading capability is never closed).
|
||||||
|
// Deprecated: use ServersTransport to configure the TerminationDelay instead.
|
||||||
|
TerminationDelay *int `json:"terminationDelay,omitempty" toml:"terminationDelay,omitempty" yaml:"terminationDelay,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mergeable tells if the given service is mergeable.
|
// Mergeable tells if the given service is mergeable.
|
||||||
|
|
|
@ -124,6 +124,27 @@ func (in *CircuitBreaker) DeepCopy() *CircuitBreaker {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ClientTLS) DeepCopyInto(out *ClientTLS) {
|
||||||
|
*out = *in
|
||||||
|
if in.CAOptional != nil {
|
||||||
|
in, out := &in.CAOptional, &out.CAOptional
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTLS.
|
||||||
|
func (in *ClientTLS) DeepCopy() *ClientTLS {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ClientTLS)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Compress) DeepCopyInto(out *Compress) {
|
func (in *Compress) DeepCopyInto(out *Compress) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -219,6 +240,11 @@ func (in Configurations) DeepCopy() Configurations {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ContentType) DeepCopyInto(out *ContentType) {
|
func (in *ContentType) DeepCopyInto(out *ContentType) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.AutoDetect != nil {
|
||||||
|
in, out := &in.AutoDetect, &out.AutoDetect
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,8 +342,8 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.TLS != nil {
|
if in.TLS != nil {
|
||||||
in, out := &in.TLS, &out.TLS
|
in, out := &in.TLS, &out.TLS
|
||||||
*out = new(types.ClientTLS)
|
*out = new(ClientTLS)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.AuthResponseHeaders != nil {
|
if in.AuthResponseHeaders != nil {
|
||||||
in, out := &in.AuthResponseHeaders, &out.AuthResponseHeaders
|
in, out := &in.AuthResponseHeaders, &out.AuthResponseHeaders
|
||||||
|
@ -534,6 +560,31 @@ func (in *Headers) DeepCopyInto(out *Headers) {
|
||||||
(*out)[key] = val
|
(*out)[key] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if in.FeaturePolicy != nil {
|
||||||
|
in, out := &in.FeaturePolicy, &out.FeaturePolicy
|
||||||
|
*out = new(string)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.SSLRedirect != nil {
|
||||||
|
in, out := &in.SSLRedirect, &out.SSLRedirect
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.SSLTemporaryRedirect != nil {
|
||||||
|
in, out := &in.SSLTemporaryRedirect, &out.SSLTemporaryRedirect
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.SSLHost != nil {
|
||||||
|
in, out := &in.SSLHost, &out.SSLHost
|
||||||
|
*out = new(string)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.SSLForceHost != nil {
|
||||||
|
in, out := &in.SSLForceHost, &out.SSLForceHost
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,7 +845,7 @@ func (in *Middleware) DeepCopyInto(out *Middleware) {
|
||||||
if in.ContentType != nil {
|
if in.ContentType != nil {
|
||||||
in, out := &in.ContentType, &out.ContentType
|
in, out := &in.ContentType, &out.ContentType
|
||||||
*out = new(ContentType)
|
*out = new(ContentType)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.GrpcWeb != nil {
|
if in.GrpcWeb != nil {
|
||||||
in, out := &in.GrpcWeb, &out.GrpcWeb
|
in, out := &in.GrpcWeb, &out.GrpcWeb
|
||||||
|
@ -1360,6 +1411,11 @@ func (in *StripPrefix) DeepCopyInto(out *StripPrefix) {
|
||||||
*out = make([]string, len(*in))
|
*out = make([]string, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
|
if in.ForceSlash != nil {
|
||||||
|
in, out := &in.ForceSlash, &out.ForceSlash
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1650,6 +1706,11 @@ func (in *TCPServersLoadBalancer) DeepCopyInto(out *TCPServersLoadBalancer) {
|
||||||
*out = make([]TCPServer, len(*in))
|
*out = make([]TCPServer, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
|
if in.TerminationDelay != nil {
|
||||||
|
in, out := &in.TerminationDelay, &out.TerminationDelay
|
||||||
|
*out = new(int)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,11 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
ptypes "github.com/traefik/paerser/types"
|
ptypes "github.com/traefik/paerser/types"
|
||||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Bool(v bool) *bool { return &v }
|
||||||
|
func String(v string) *string { return &v }
|
||||||
|
|
||||||
func TestDecodeConfiguration(t *testing.T) {
|
func TestDecodeConfiguration(t *testing.T) {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"traefik.http.middlewares.Middleware0.addprefix.prefix": "foobar",
|
"traefik.http.middlewares.Middleware0.addprefix.prefix": "foobar",
|
||||||
|
@ -43,6 +45,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.authresponseheaders": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware7.forwardauth.authresponseheaders": "foobar, fiibar",
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.authrequestheaders": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware7.forwardauth.authrequestheaders": "foobar, fiibar",
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.tls.ca": "foobar",
|
"traefik.http.middlewares.Middleware7.forwardauth.tls.ca": "foobar",
|
||||||
|
"traefik.http.middlewares.Middleware7.forwardauth.tls.caoptional": "true",
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.tls.cert": "foobar",
|
"traefik.http.middlewares.Middleware7.forwardauth.tls.cert": "foobar",
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.tls.insecureskipverify": "true",
|
"traefik.http.middlewares.Middleware7.forwardauth.tls.insecureskipverify": "true",
|
||||||
"traefik.http.middlewares.Middleware7.forwardauth.tls.key": "foobar",
|
"traefik.http.middlewares.Middleware7.forwardauth.tls.key": "foobar",
|
||||||
|
@ -71,9 +74,14 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware8.headers.isdevelopment": "true",
|
"traefik.http.middlewares.Middleware8.headers.isdevelopment": "true",
|
||||||
"traefik.http.middlewares.Middleware8.headers.publickey": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.publickey": "foobar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.referrerpolicy": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.referrerpolicy": "foobar",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.featurepolicy": "foobar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.permissionspolicy": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.permissionspolicy": "foobar",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.sslforcehost": "true",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.sslhost": "foobar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.sslproxyheaders.name0": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.sslproxyheaders.name0": "foobar",
|
||||||
"traefik.http.middlewares.Middleware8.headers.sslproxyheaders.name1": "foobar",
|
"traefik.http.middlewares.Middleware8.headers.sslproxyheaders.name1": "foobar",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.sslredirect": "true",
|
||||||
|
"traefik.http.middlewares.Middleware8.headers.ssltemporaryredirect": "true",
|
||||||
"traefik.http.middlewares.Middleware8.headers.stsincludesubdomains": "true",
|
"traefik.http.middlewares.Middleware8.headers.stsincludesubdomains": "true",
|
||||||
"traefik.http.middlewares.Middleware8.headers.stspreload": "true",
|
"traefik.http.middlewares.Middleware8.headers.stspreload": "true",
|
||||||
"traefik.http.middlewares.Middleware8.headers.stsseconds": "42",
|
"traefik.http.middlewares.Middleware8.headers.stsseconds": "42",
|
||||||
|
@ -124,6 +132,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware16.retry.attempts": "42",
|
"traefik.http.middlewares.Middleware16.retry.attempts": "42",
|
||||||
"traefik.http.middlewares.Middleware16.retry.initialinterval": "1s",
|
"traefik.http.middlewares.Middleware16.retry.initialinterval": "1s",
|
||||||
"traefik.http.middlewares.Middleware17.stripprefix.prefixes": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware17.stripprefix.prefixes": "foobar, fiibar",
|
||||||
|
"traefik.http.middlewares.Middleware17.stripprefix.forceslash": "true",
|
||||||
"traefik.http.middlewares.Middleware18.stripprefixregex.regex": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware18.stripprefixregex.regex": "foobar, fiibar",
|
||||||
"traefik.http.middlewares.Middleware19.compress.minresponsebodybytes": "42",
|
"traefik.http.middlewares.Middleware19.compress.minresponsebodybytes": "42",
|
||||||
"traefik.http.middlewares.Middleware20.plugin.tomato.aaa": "foo1",
|
"traefik.http.middlewares.Middleware20.plugin.tomato.aaa": "foo1",
|
||||||
|
@ -194,9 +203,11 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.tcp.routers.Router1.tls.options": "foo",
|
"traefik.tcp.routers.Router1.tls.options": "foo",
|
||||||
"traefik.tcp.routers.Router1.tls.passthrough": "false",
|
"traefik.tcp.routers.Router1.tls.passthrough": "false",
|
||||||
"traefik.tcp.services.Service0.loadbalancer.server.Port": "42",
|
"traefik.tcp.services.Service0.loadbalancer.server.Port": "42",
|
||||||
|
"traefik.tcp.services.Service0.loadbalancer.TerminationDelay": "42",
|
||||||
"traefik.tcp.services.Service0.loadbalancer.proxyProtocol.version": "42",
|
"traefik.tcp.services.Service0.loadbalancer.proxyProtocol.version": "42",
|
||||||
"traefik.tcp.services.Service0.loadbalancer.serversTransport": "foo",
|
"traefik.tcp.services.Service0.loadbalancer.serversTransport": "foo",
|
||||||
"traefik.tcp.services.Service1.loadbalancer.server.Port": "42",
|
"traefik.tcp.services.Service1.loadbalancer.server.Port": "42",
|
||||||
|
"traefik.tcp.services.Service1.loadbalancer.TerminationDelay": "42",
|
||||||
"traefik.tcp.services.Service1.loadbalancer.proxyProtocol": "true",
|
"traefik.tcp.services.Service1.loadbalancer.proxyProtocol": "true",
|
||||||
"traefik.tcp.services.Service1.loadbalancer.serversTransport": "foo",
|
"traefik.tcp.services.Service1.loadbalancer.serversTransport": "foo",
|
||||||
|
|
||||||
|
@ -261,6 +272,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
ProxyProtocol: &dynamic.ProxyProtocol{Version: 42},
|
ProxyProtocol: &dynamic.ProxyProtocol{Version: 42},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
},
|
},
|
||||||
|
@ -272,6 +284,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
Port: "42",
|
Port: "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
ProxyProtocol: &dynamic.ProxyProtocol{Version: 2},
|
ProxyProtocol: &dynamic.ProxyProtocol{Version: 2},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
},
|
},
|
||||||
|
@ -459,6 +472,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
ForceSlash: Bool(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -525,11 +539,12 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"Middleware7": {
|
"Middleware7": {
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "foobar",
|
Address: "foobar",
|
||||||
TLS: &types.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
CA: "foobar",
|
CA: "foobar",
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
CAOptional: Bool(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -583,10 +598,14 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
SSLRedirect: Bool(true),
|
||||||
|
SSLTemporaryRedirect: Bool(true),
|
||||||
|
SSLHost: String("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
|
SSLForceHost: Bool(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -599,6 +618,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicy: "foobar",
|
ContentSecurityPolicy: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
|
FeaturePolicy: String("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -758,6 +778,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Service1": {
|
"Service1": {
|
||||||
|
@ -768,6 +789,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ServersTransport: "foo",
|
ServersTransport: "foo",
|
||||||
|
TerminationDelay: func(i int) *int { return &i }(42),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -952,6 +974,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
ForceSlash: Bool(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware18": {
|
"Middleware18": {
|
||||||
|
@ -1026,11 +1049,12 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"Middleware7": {
|
"Middleware7": {
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "foobar",
|
Address: "foobar",
|
||||||
TLS: &types.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
CA: "foobar",
|
CA: "foobar",
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
CAOptional: Bool(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -1084,10 +1108,14 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"fiibar",
|
"fiibar",
|
||||||
},
|
},
|
||||||
|
SSLRedirect: Bool(true),
|
||||||
|
SSLTemporaryRedirect: Bool(true),
|
||||||
|
SSLHost: String("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
},
|
},
|
||||||
|
SSLForceHost: Bool(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -1100,6 +1128,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicy: "foobar",
|
ContentSecurityPolicy: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
|
FeaturePolicy: String("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -1222,6 +1251,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.AuthResponseHeaders": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.AuthResponseHeaders": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.AuthRequestHeaders": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.AuthRequestHeaders": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.CA": "foobar",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.CA": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.CAOptional": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.Cert": "foobar",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.Cert": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.InsecureSkipVerify": "true",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.InsecureSkipVerify": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.Key": "foobar",
|
"traefik.HTTP.Middlewares.Middleware7.ForwardAuth.TLS.Key": "foobar",
|
||||||
|
@ -1250,9 +1280,14 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.IsDevelopment": "true",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.IsDevelopment": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.PublicKey": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.PublicKey": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.ReferrerPolicy": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.ReferrerPolicy": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.FeaturePolicy": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.PermissionsPolicy": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.PermissionsPolicy": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLForceHost": "true",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLHost": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLProxyHeaders.name0": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLProxyHeaders.name0": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLProxyHeaders.name1": "foobar",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLProxyHeaders.name1": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLRedirect": "true",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware8.Headers.SSLTemporaryRedirect": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.STSIncludeSubdomains": "true",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.STSIncludeSubdomains": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.STSPreload": "true",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.STSPreload": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware8.Headers.STSSeconds": "42",
|
"traefik.HTTP.Middlewares.Middleware8.Headers.STSSeconds": "42",
|
||||||
|
@ -1304,6 +1339,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware16.Retry.Attempts": "42",
|
"traefik.HTTP.Middlewares.Middleware16.Retry.Attempts": "42",
|
||||||
"traefik.HTTP.Middlewares.Middleware16.Retry.InitialInterval": "1000000000",
|
"traefik.HTTP.Middlewares.Middleware16.Retry.InitialInterval": "1000000000",
|
||||||
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.Prefixes": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.Prefixes": "foobar, fiibar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware17.StripPrefix.ForceSlash": "true",
|
||||||
"traefik.HTTP.Middlewares.Middleware18.StripPrefixRegex.Regex": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware18.StripPrefixRegex.Regex": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware19.Compress.MinResponseBodyBytes": "42",
|
"traefik.HTTP.Middlewares.Middleware19.Compress.MinResponseBodyBytes": "42",
|
||||||
"traefik.HTTP.Middlewares.Middleware20.Plugin.tomato.aaa": "foo1",
|
"traefik.HTTP.Middlewares.Middleware20.Plugin.tomato.aaa": "foo1",
|
||||||
|
@ -1373,9 +1409,11 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.TCP.Services.Service0.LoadBalancer.server.Port": "42",
|
"traefik.TCP.Services.Service0.LoadBalancer.server.Port": "42",
|
||||||
"traefik.TCP.Services.Service0.LoadBalancer.server.TLS": "false",
|
"traefik.TCP.Services.Service0.LoadBalancer.server.TLS": "false",
|
||||||
"traefik.TCP.Services.Service0.LoadBalancer.ServersTransport": "foo",
|
"traefik.TCP.Services.Service0.LoadBalancer.ServersTransport": "foo",
|
||||||
|
"traefik.TCP.Services.Service0.LoadBalancer.TerminationDelay": "42",
|
||||||
"traefik.TCP.Services.Service1.LoadBalancer.server.Port": "42",
|
"traefik.TCP.Services.Service1.LoadBalancer.server.Port": "42",
|
||||||
"traefik.TCP.Services.Service1.LoadBalancer.server.TLS": "false",
|
"traefik.TCP.Services.Service1.LoadBalancer.server.TLS": "false",
|
||||||
"traefik.TCP.Services.Service1.LoadBalancer.ServersTransport": "foo",
|
"traefik.TCP.Services.Service1.LoadBalancer.ServersTransport": "foo",
|
||||||
|
"traefik.TCP.Services.Service1.LoadBalancer.TerminationDelay": "42",
|
||||||
|
|
||||||
"traefik.UDP.Routers.Router0.EntryPoints": "foobar, fiibar",
|
"traefik.UDP.Routers.Router0.EntryPoints": "foobar, fiibar",
|
||||||
"traefik.UDP.Routers.Router0.Service": "foobar",
|
"traefik.UDP.Routers.Router0.Service": "foobar",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/middlewares"
|
"github.com/traefik/traefik/v3/pkg/middlewares"
|
||||||
"github.com/traefik/traefik/v3/pkg/middlewares/connectionheader"
|
"github.com/traefik/traefik/v3/pkg/middlewares/connectionheader"
|
||||||
"github.com/traefik/traefik/v3/pkg/tracing"
|
"github.com/traefik/traefik/v3/pkg/tracing"
|
||||||
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
"github.com/vulcand/oxy/v2/forward"
|
"github.com/vulcand/oxy/v2/forward"
|
||||||
"github.com/vulcand/oxy/v2/utils"
|
"github.com/vulcand/oxy/v2/utils"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
|
@ -53,7 +54,8 @@ type forwardAuth struct {
|
||||||
|
|
||||||
// NewForward creates a forward auth middleware.
|
// NewForward creates a forward auth middleware.
|
||||||
func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) {
|
func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAuth, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeNameForward).Debug().Msg("Creating middleware")
|
logger := middlewares.GetLogger(ctx, name, typeNameForward)
|
||||||
|
logger.Debug().Msg("Creating middleware")
|
||||||
|
|
||||||
addAuthCookiesToResponse := make(map[string]struct{})
|
addAuthCookiesToResponse := make(map[string]struct{})
|
||||||
for _, cookieName := range config.AddAuthCookiesToResponse {
|
for _, cookieName := range config.AddAuthCookiesToResponse {
|
||||||
|
@ -79,7 +81,18 @@ func NewForward(ctx context.Context, next http.Handler, config dynamic.ForwardAu
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TLS != nil {
|
if config.TLS != nil {
|
||||||
tlsConfig, err := config.TLS.CreateTLSConfig(ctx)
|
if config.TLS.CAOptional != nil {
|
||||||
|
logger.Warn().Msg("CAOptional option is deprecated, TLS client authentication is a server side option, please remove any usage of this option.")
|
||||||
|
}
|
||||||
|
|
||||||
|
clientTLS := &types.ClientTLS{
|
||||||
|
CA: config.TLS.CA,
|
||||||
|
Cert: config.TLS.Cert,
|
||||||
|
Key: config.TLS.Key,
|
||||||
|
InsecureSkipVerify: config.TLS.InsecureSkipVerify,
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig, err := clientTLS.CreateTLSConfig(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to create client TLS configuration: %w", err)
|
return nil, fmt.Errorf("unable to create client TLS configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v3/pkg/middlewares"
|
"github.com/traefik/traefik/v3/pkg/middlewares"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,8 +19,19 @@ type contentType struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new handler.
|
// New creates a new handler.
|
||||||
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.ContentType, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")
|
logger := middlewares.GetLogger(ctx, name, typeName)
|
||||||
|
logger.Debug().Msg("Creating middleware")
|
||||||
|
|
||||||
|
if config.AutoDetect != nil {
|
||||||
|
logger.Warn().Msg("AutoDetect option is deprecated, Content-Type middleware is only meant to be used to enable the content-type detection, please remove any usage of this option.")
|
||||||
|
|
||||||
|
// Disable content-type detection (idempotent).
|
||||||
|
if !*config.AutoDetect {
|
||||||
|
return next, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &contentType{next: next, name: name}, nil
|
return &contentType{next: next, name: name}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||||
"github.com/traefik/traefik/v3/pkg/testhelpers"
|
"github.com/traefik/traefik/v3/pkg/testhelpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ func TestAutoDetection(t *testing.T) {
|
||||||
|
|
||||||
if test.autoDetect {
|
if test.autoDetect {
|
||||||
var err error
|
var err error
|
||||||
next, err = New(context.Background(), next, "foo-content-type")
|
next, err = New(context.Background(), next, dynamic.ContentType{}, "foo-content-type")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,27 @@ type stripPrefix struct {
|
||||||
next http.Handler
|
next http.Handler
|
||||||
prefixes []string
|
prefixes []string
|
||||||
name string
|
name string
|
||||||
|
|
||||||
|
// Deprecated: Must be removed (breaking), the default behavior must be forceSlash=false
|
||||||
|
forceSlash bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new strip prefix middleware.
|
// New creates a new strip prefix middleware.
|
||||||
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, name string) (http.Handler, error) {
|
func New(ctx context.Context, next http.Handler, config dynamic.StripPrefix, name string) (http.Handler, error) {
|
||||||
middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")
|
logger := middlewares.GetLogger(ctx, name, typeName)
|
||||||
|
logger.Debug().Msg("Creating middleware")
|
||||||
|
|
||||||
|
if config.ForceSlash != nil {
|
||||||
|
logger.Warn().Msgf("`ForceSlash` option is deprecated, please remove any usage of this option.")
|
||||||
|
}
|
||||||
|
// Handle default value (here because of deprecation and the removal of setDefault).
|
||||||
|
forceSlash := config.ForceSlash != nil && *config.ForceSlash
|
||||||
|
|
||||||
return &stripPrefix{
|
return &stripPrefix{
|
||||||
prefixes: config.Prefixes,
|
prefixes: config.Prefixes,
|
||||||
next: next,
|
next: next,
|
||||||
name: name,
|
name: name,
|
||||||
|
forceSlash: forceSlash,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +70,13 @@ func (s *stripPrefix) serveRequest(rw http.ResponseWriter, req *http.Request, pr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stripPrefix) getPrefixStripped(urlPath, prefix string) string {
|
func (s *stripPrefix) getPrefixStripped(urlPath, prefix string) string {
|
||||||
|
if s.forceSlash {
|
||||||
|
// Only for compatibility reason with the previous behavior,
|
||||||
|
// but the previous behavior is wrong.
|
||||||
|
// This needs to be removed in the next breaking version.
|
||||||
|
return "/" + strings.TrimPrefix(strings.TrimPrefix(urlPath, prefix), "/")
|
||||||
|
}
|
||||||
|
|
||||||
return ensureLeadingSlash(strings.TrimPrefix(urlPath, prefix))
|
return ensureLeadingSlash(strings.TrimPrefix(urlPath, prefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,6 +146,9 @@ func TestStripPrefix(t *testing.T) {
|
||||||
requestURI = r.RequestURI
|
requestURI = r.RequestURI
|
||||||
})
|
})
|
||||||
|
|
||||||
|
pointer := func(v bool) *bool { return &v }
|
||||||
|
test.config.ForceSlash = pointer(false)
|
||||||
|
|
||||||
handler, err := New(context.Background(), next, test.config, "foo-strip-prefix")
|
handler, err := New(context.Background(), next, test.config, "foo-strip-prefix")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -1,196 +0,0 @@
|
||||||
package crd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
traefikv1alpha1 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
|
||||||
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
kscheme "k8s.io/client-go/kubernetes/scheme"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ Client = (*clientMock)(nil)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// required by k8s.MustParseYaml
|
|
||||||
err := traefikv1alpha1.AddToScheme(kscheme.Scheme)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type clientMock struct {
|
|
||||||
services []*corev1.Service
|
|
||||||
secrets []*corev1.Secret
|
|
||||||
endpoints []*corev1.Endpoints
|
|
||||||
|
|
||||||
apiServiceError error
|
|
||||||
apiSecretError error
|
|
||||||
apiEndpointsError error
|
|
||||||
|
|
||||||
ingressRoutes []*traefikv1alpha1.IngressRoute
|
|
||||||
ingressRouteTCPs []*traefikv1alpha1.IngressRouteTCP
|
|
||||||
ingressRouteUDPs []*traefikv1alpha1.IngressRouteUDP
|
|
||||||
middlewares []*traefikv1alpha1.Middleware
|
|
||||||
middlewareTCPs []*traefikv1alpha1.MiddlewareTCP
|
|
||||||
tlsOptions []*traefikv1alpha1.TLSOption
|
|
||||||
tlsStores []*traefikv1alpha1.TLSStore
|
|
||||||
traefikServices []*traefikv1alpha1.TraefikService
|
|
||||||
serversTransports []*traefikv1alpha1.ServersTransport
|
|
||||||
serversTransportTCPs []*traefikv1alpha1.ServersTransportTCP
|
|
||||||
|
|
||||||
watchChan chan interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newClientMock(paths ...string) clientMock {
|
|
||||||
var c clientMock
|
|
||||||
|
|
||||||
for _, path := range paths {
|
|
||||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
k8sObjects := k8s.MustParseYaml(yamlContent)
|
|
||||||
for _, obj := range k8sObjects {
|
|
||||||
switch o := obj.(type) {
|
|
||||||
case *corev1.Service:
|
|
||||||
c.services = append(c.services, o)
|
|
||||||
case *corev1.Endpoints:
|
|
||||||
c.endpoints = append(c.endpoints, o)
|
|
||||||
case *traefikv1alpha1.IngressRoute:
|
|
||||||
c.ingressRoutes = append(c.ingressRoutes, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteTCP:
|
|
||||||
c.ingressRouteTCPs = append(c.ingressRouteTCPs, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteUDP:
|
|
||||||
c.ingressRouteUDPs = append(c.ingressRouteUDPs, o)
|
|
||||||
case *traefikv1alpha1.Middleware:
|
|
||||||
c.middlewares = append(c.middlewares, o)
|
|
||||||
case *traefikv1alpha1.MiddlewareTCP:
|
|
||||||
c.middlewareTCPs = append(c.middlewareTCPs, o)
|
|
||||||
case *traefikv1alpha1.TraefikService:
|
|
||||||
c.traefikServices = append(c.traefikServices, o)
|
|
||||||
case *traefikv1alpha1.TLSOption:
|
|
||||||
c.tlsOptions = append(c.tlsOptions, o)
|
|
||||||
case *traefikv1alpha1.ServersTransport:
|
|
||||||
c.serversTransports = append(c.serversTransports, o)
|
|
||||||
case *traefikv1alpha1.ServersTransportTCP:
|
|
||||||
c.serversTransportTCPs = append(c.serversTransportTCPs, o)
|
|
||||||
case *traefikv1alpha1.TLSStore:
|
|
||||||
c.tlsStores = append(c.tlsStores, o)
|
|
||||||
case *corev1.Secret:
|
|
||||||
c.secrets = append(c.secrets, o)
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("Unknown runtime object %+v %T", o, o))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetIngressRoutes() []*traefikv1alpha1.IngressRoute {
|
|
||||||
return c.ingressRoutes
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetIngressRouteTCPs() []*traefikv1alpha1.IngressRouteTCP {
|
|
||||||
return c.ingressRouteTCPs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetIngressRouteUDPs() []*traefikv1alpha1.IngressRouteUDP {
|
|
||||||
return c.ingressRouteUDPs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetMiddlewares() []*traefikv1alpha1.Middleware {
|
|
||||||
return c.middlewares
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetMiddlewareTCPs() []*traefikv1alpha1.MiddlewareTCP {
|
|
||||||
return c.middlewareTCPs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTraefikService(namespace, name string) (*traefikv1alpha1.TraefikService, bool, error) {
|
|
||||||
for _, svc := range c.traefikServices {
|
|
||||||
if svc.Namespace == namespace && svc.Name == name {
|
|
||||||
return svc, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTraefikServices() []*traefikv1alpha1.TraefikService {
|
|
||||||
return c.traefikServices
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTLSOptions() []*traefikv1alpha1.TLSOption {
|
|
||||||
return c.tlsOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTLSStores() []*traefikv1alpha1.TLSStore {
|
|
||||||
return c.tlsStores
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetServersTransports() []*traefikv1alpha1.ServersTransport {
|
|
||||||
return c.serversTransports
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetServersTransportTCPs() []*traefikv1alpha1.ServersTransportTCP {
|
|
||||||
return c.serversTransportTCPs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetTLSOption(namespace, name string) (*traefikv1alpha1.TLSOption, bool, error) {
|
|
||||||
for _, option := range c.tlsOptions {
|
|
||||||
if option.Namespace == namespace && option.Name == name {
|
|
||||||
return option, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetService(namespace, name string) (*corev1.Service, bool, error) {
|
|
||||||
if c.apiServiceError != nil {
|
|
||||||
return nil, false, c.apiServiceError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, service := range c.services {
|
|
||||||
if service.Namespace == namespace && service.Name == name {
|
|
||||||
return service, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false, c.apiServiceError
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetEndpoints(namespace, name string) (*corev1.Endpoints, bool, error) {
|
|
||||||
if c.apiEndpointsError != nil {
|
|
||||||
return nil, false, c.apiEndpointsError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, endpoints := range c.endpoints {
|
|
||||||
if endpoints.Namespace == namespace && endpoints.Name == name {
|
|
||||||
return endpoints, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &corev1.Endpoints{}, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) GetSecret(namespace, name string) (*corev1.Secret, bool, error) {
|
|
||||||
if c.apiSecretError != nil {
|
|
||||||
return nil, false, c.apiSecretError
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, secret := range c.secrets {
|
|
||||||
if secret.Namespace == namespace && secret.Name == name {
|
|
||||||
return secret, true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c clientMock) WatchAll(namespaces []string, stopCh <-chan struct{}) (<-chan interface{}, error) {
|
|
||||||
return c.watchChan, nil
|
|
||||||
}
|
|
|
@ -166,7 +166,7 @@ subsets:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: external-svc
|
name: external-svc-tcp
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
externalName: external.domain
|
externalName: external.domain
|
||||||
|
@ -176,7 +176,7 @@ spec:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: external.service.with.port
|
name: external.service.with.port.tcp
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
externalName: external.domain
|
externalName: external.domain
|
||||||
|
@ -186,19 +186,6 @@ spec:
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: external.service.without.port
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
externalName: external.domain
|
|
||||||
type: ExternalName
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
protocol: TCP
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
@ -266,7 +253,7 @@ metadata:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: native-svc
|
name: native-svc-tcp
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -11,5 +11,5 @@ spec:
|
||||||
routes:
|
routes:
|
||||||
- match: HostSNI(`foo.com`)
|
- match: HostSNI(`foo.com`)
|
||||||
services:
|
services:
|
||||||
- name: external-svc
|
- name: external-svc-tcp
|
||||||
port: 8000
|
port: 8000
|
||||||
|
|
|
@ -11,5 +11,5 @@ spec:
|
||||||
routes:
|
routes:
|
||||||
- match: HostSNI(`foo.com`)
|
- match: HostSNI(`foo.com`)
|
||||||
services:
|
services:
|
||||||
- name: external.service.with.port
|
- name: external.service.with.port.tcp
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -11,4 +11,4 @@ spec:
|
||||||
routes:
|
routes:
|
||||||
- match: HostSNI(`foo.com`)
|
- match: HostSNI(`foo.com`)
|
||||||
services:
|
services:
|
||||||
- name: external-svc
|
- name: external-svc-tcp
|
||||||
|
|
|
@ -11,6 +11,6 @@ spec:
|
||||||
routes:
|
routes:
|
||||||
- match: HostSNI(`foo.com`)
|
- match: HostSNI(`foo.com`)
|
||||||
services:
|
services:
|
||||||
- name: native-svc
|
- name: native-svc-tcp
|
||||||
port: 8000
|
port: 8000
|
||||||
nativeLB: true
|
nativeLB: true
|
||||||
|
|
|
@ -150,7 +150,7 @@ spec:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: external-svc
|
name: external-svc-udp
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
externalName: external.domain
|
externalName: external.domain
|
||||||
|
@ -160,7 +160,7 @@ spec:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: external.service.with.port
|
name: external.service.with.port.udp
|
||||||
namespace: default
|
namespace: default
|
||||||
spec:
|
spec:
|
||||||
externalName: external.domain
|
externalName: external.domain
|
||||||
|
@ -170,19 +170,6 @@ spec:
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: external.service.without.port
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
externalName: external.domain
|
|
||||||
type: ExternalName
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
protocol: TCP
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: Endpoints
|
kind: Endpoints
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
@ -225,7 +212,7 @@ metadata:
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: native-svc
|
name: native-svc-udp
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: external-svc
|
- name: external-svc-udp
|
||||||
port: 8000
|
port: 8000
|
||||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: external.service.with.port
|
- name: external.service.with.port.udp
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -10,5 +10,5 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: external.service.with.port
|
- name: external.service.with.port.udp
|
||||||
port: 80
|
port: 80
|
||||||
|
|
|
@ -10,4 +10,4 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: external-svc
|
- name: external-svc-udp
|
||||||
|
|
|
@ -10,6 +10,6 @@ spec:
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- services:
|
- services:
|
||||||
- name: native-svc
|
- name: native-svc-udp
|
||||||
port: 8000
|
port: 8000
|
||||||
nativeLB: true
|
nativeLB: true
|
||||||
|
|
|
@ -40,7 +40,7 @@ spec:
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
name: test.route
|
name: test.route.default
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -23,7 +23,7 @@ data:
|
||||||
apiVersion: traefik.io/v1alpha1
|
apiVersion: traefik.io/v1alpha1
|
||||||
kind: IngressRoute
|
kind: IngressRoute
|
||||||
metadata:
|
metadata:
|
||||||
name: test.route
|
name: test.route.default
|
||||||
namespace: default
|
namespace: default
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
|
|
|
@ -735,7 +735,7 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef
|
||||||
return forwardAuth, nil
|
return forwardAuth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardAuth.TLS = &types.ClientTLS{
|
forwardAuth.TLS = &dynamic.ClientTLS{
|
||||||
InsecureSkipVerify: auth.TLS.InsecureSkipVerify,
|
InsecureSkipVerify: auth.TLS.InsecureSkipVerify,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,6 +756,8 @@ func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *traef
|
||||||
forwardAuth.TLS.Key = authSecretKey
|
forwardAuth.TLS.Key = authSecretKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forwardAuth.TLS.CAOptional = auth.TLS.CAOptional
|
||||||
|
|
||||||
return forwardAuth, nil
|
return forwardAuth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1008,8 +1010,9 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options
|
||||||
CAFiles: clientCAs,
|
CAFiles: clientCAs,
|
||||||
ClientAuthType: tlsOption.Spec.ClientAuth.ClientAuthType,
|
ClientAuthType: tlsOption.Spec.ClientAuth.ClientAuthType,
|
||||||
},
|
},
|
||||||
SniStrict: tlsOption.Spec.SniStrict,
|
SniStrict: tlsOption.Spec.SniStrict,
|
||||||
ALPNProtocols: alpnProtocols,
|
ALPNProtocols: alpnProtocols,
|
||||||
|
PreferServerCipherSuites: tlsOption.Spec.PreferServerCipherSuites,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,10 @@ func (p *Provider) createLoadBalancerServerTCP(client Client, parentNamespace st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if service.ServersTransport == "" && service.TerminationDelay != nil {
|
||||||
|
tcpService.LoadBalancer.TerminationDelay = service.TerminationDelay
|
||||||
|
}
|
||||||
|
|
||||||
if service.ServersTransport != "" {
|
if service.ServersTransport != "" {
|
||||||
tcpService.LoadBalancer.ServersTransport, err = p.makeTCPServersTransportKey(parentNamespace, service.ServersTransport)
|
tcpService.LoadBalancer.ServersTransport, err = p.makeTCPServersTransportKey(parentNamespace, service.ServersTransport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
kubefake "k8s.io/client-go/kubernetes/fake"
|
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||||
|
kscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ provider.Provider = (*Provider)(nil)
|
var _ provider.Provider = (*Provider)(nil)
|
||||||
|
@ -30,6 +31,14 @@ var _ provider.Provider = (*Provider)(nil)
|
||||||
func Int(v int) *int { return &v }
|
func Int(v int) *int { return &v }
|
||||||
func Bool(v bool) *bool { return &v }
|
func Bool(v bool) *bool { return &v }
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// required by k8s.MustParseYaml
|
||||||
|
err := traefikv1alpha1.AddToScheme(kscheme.Scheme)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadIngressRouteTCPs(t *testing.T) {
|
func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -1035,6 +1044,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"default-test.route-fdd3e9338e47a45efefc": {
|
"default-test.route-fdd3e9338e47a45efefc": {
|
||||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
TerminationDelay: Int(500),
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{
|
{
|
||||||
Address: "10.10.0.1:8000",
|
Address: "10.10.0.1:8000",
|
||||||
|
@ -1568,6 +1578,23 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, crdClient)
|
||||||
|
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, stopCh)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if k8sObjects != nil || crdObjects != nil {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
p := Provider{
|
p := Provider{
|
||||||
IngressClass: test.ingressClass,
|
IngressClass: test.ingressClass,
|
||||||
AllowCrossNamespace: true,
|
AllowCrossNamespace: true,
|
||||||
|
@ -1575,8 +1602,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
AllowEmptyServices: test.allowEmptyServices,
|
AllowEmptyServices: test.allowEmptyServices,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientMock := newClientMock(test.paths...)
|
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3063,6 +3089,15 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
Options: "default-foo",
|
Options: "default-foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"default-test-route-default-6b204d94623b3df4370c": {
|
||||||
|
EntryPoints: []string{"web"},
|
||||||
|
Service: "default-test-route-default-6b204d94623b3df4370c",
|
||||||
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
|
Priority: 12,
|
||||||
|
TLS: &dynamic.RouterTLSConfig{
|
||||||
|
Options: "default-foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
|
@ -3082,6 +3117,22 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"default-test-route-default-6b204d94623b3df4370c": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.2:80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: Bool(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||||
},
|
},
|
||||||
|
@ -3602,7 +3653,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
"default-forwardauth": {
|
"default-forwardauth": {
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "test.com",
|
Address: "test.com",
|
||||||
TLS: &types.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
CA: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
CA: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
||||||
Cert: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
Cert: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
|
||||||
Key: "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----",
|
Key: "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----",
|
||||||
|
@ -4017,6 +4068,13 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
Priority: 12,
|
Priority: 12,
|
||||||
TLS: &dynamic.RouterTLSConfig{},
|
TLS: &dynamic.RouterTLSConfig{},
|
||||||
},
|
},
|
||||||
|
"default-test-route-default-6b204d94623b3df4370c": {
|
||||||
|
EntryPoints: []string{"web"},
|
||||||
|
Service: "default-test-route-default-6b204d94623b3df4370c",
|
||||||
|
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
|
||||||
|
Priority: 12,
|
||||||
|
TLS: &dynamic.RouterTLSConfig{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Middlewares: map[string]*dynamic.Middleware{},
|
Middlewares: map[string]*dynamic.Middleware{},
|
||||||
Services: map[string]*dynamic.Service{
|
Services: map[string]*dynamic.Service{
|
||||||
|
@ -4036,6 +4094,22 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"default-test-route-default-6b204d94623b3df4370c": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.1:80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
URL: "http://10.10.0.2:80",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PassHostHeader: Bool(true),
|
||||||
|
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||||
|
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ServersTransports: map[string]*dynamic.ServersTransport{},
|
ServersTransports: map[string]*dynamic.ServersTransport{},
|
||||||
},
|
},
|
||||||
|
@ -4521,6 +4595,23 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, crdClient)
|
||||||
|
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, stopCh)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if k8sObjects != nil || crdObjects != nil {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
p := Provider{
|
p := Provider{
|
||||||
IngressClass: test.ingressClass,
|
IngressClass: test.ingressClass,
|
||||||
AllowCrossNamespace: test.allowCrossNamespace,
|
AllowCrossNamespace: test.allowCrossNamespace,
|
||||||
|
@ -4528,8 +4619,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
AllowEmptyServices: test.allowEmptyServices,
|
AllowEmptyServices: test.allowEmptyServices,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientMock := newClientMock(test.paths...)
|
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5016,6 +5106,23 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
|
|
||||||
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
|
||||||
|
client := newClientImpl(kubeClient, crdClient)
|
||||||
|
|
||||||
|
stopCh := make(chan struct{})
|
||||||
|
|
||||||
|
eventCh, err := client.WatchAll(nil, stopCh)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if k8sObjects != nil || crdObjects != nil {
|
||||||
|
// just wait for the first event
|
||||||
|
<-eventCh
|
||||||
|
}
|
||||||
|
|
||||||
p := Provider{
|
p := Provider{
|
||||||
IngressClass: test.ingressClass,
|
IngressClass: test.ingressClass,
|
||||||
AllowCrossNamespace: true,
|
AllowCrossNamespace: true,
|
||||||
|
@ -5023,8 +5130,7 @@ func TestLoadIngressRouteUDPs(t *testing.T) {
|
||||||
AllowEmptyServices: test.allowEmptyServices,
|
AllowEmptyServices: test.allowEmptyServices,
|
||||||
}
|
}
|
||||||
|
|
||||||
clientMock := newClientMock(test.paths...)
|
conf := p.loadConfigurationFromCRD(context.Background(), client)
|
||||||
conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
|
|
||||||
assert.Equal(t, test.expected, conf)
|
assert.Equal(t, test.expected, conf)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -6435,43 +6541,7 @@ func TestCrossNamespace(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var k8sObjects []runtime.Object
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
var crdObjects []runtime.Object
|
|
||||||
for _, path := range test.paths {
|
|
||||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objects := k8s.MustParseYaml(yamlContent)
|
|
||||||
for _, obj := range objects {
|
|
||||||
switch o := obj.(type) {
|
|
||||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
|
||||||
k8sObjects = append(k8sObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRoute:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteTCP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteUDP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.Middleware:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.MiddlewareTCP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TraefikService:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSOption:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSStore:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.ServersTransport:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.ServersTransportTCP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
@ -6742,37 +6812,7 @@ func TestExternalNameService(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var k8sObjects []runtime.Object
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
var crdObjects []runtime.Object
|
|
||||||
for _, path := range test.paths {
|
|
||||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objects := k8s.MustParseYaml(yamlContent)
|
|
||||||
for _, obj := range objects {
|
|
||||||
switch o := obj.(type) {
|
|
||||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
|
||||||
k8sObjects = append(k8sObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRoute:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteTCP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteUDP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.Middleware:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TraefikService:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSOption:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSStore:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
@ -6955,37 +6995,7 @@ func TestNativeLB(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
var k8sObjects []runtime.Object
|
k8sObjects, crdObjects := readResources(t, test.paths)
|
||||||
var crdObjects []runtime.Object
|
|
||||||
for _, path := range test.paths {
|
|
||||||
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
objects := k8s.MustParseYaml(yamlContent)
|
|
||||||
for _, obj := range objects {
|
|
||||||
switch o := obj.(type) {
|
|
||||||
case *corev1.Service, *corev1.Endpoints, *corev1.Secret:
|
|
||||||
k8sObjects = append(k8sObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRoute:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteTCP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.IngressRouteUDP:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.Middleware:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TraefikService:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSOption:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
case *traefikv1alpha1.TLSStore:
|
|
||||||
crdObjects = append(crdObjects, o)
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
kubeClient := kubefake.NewSimpleClientset(k8sObjects...)
|
||||||
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
crdClient := traefikcrdfake.NewSimpleClientset(crdObjects...)
|
||||||
|
@ -7071,3 +7081,28 @@ func TestCreateBasicAuthCredentials(t *testing.T) {
|
||||||
assert.Equal(t, "$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", hashedPassword)
|
assert.Equal(t, "$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", hashedPassword)
|
||||||
assert.True(t, auth.CheckSecret("test2", hashedPassword))
|
assert.True(t, auth.CheckSecret("test2", hashedPassword))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readResources(t *testing.T, paths []string) ([]runtime.Object, []runtime.Object) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var k8sObjects []runtime.Object
|
||||||
|
var crdObjects []runtime.Object
|
||||||
|
for _, path := range paths {
|
||||||
|
yamlContent, err := os.ReadFile(filepath.FromSlash("./fixtures/" + path))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
objects := k8s.MustParseYaml(yamlContent)
|
||||||
|
for _, obj := range objects {
|
||||||
|
switch obj.GetObjectKind().GroupVersionKind().Group {
|
||||||
|
case "traefik.io":
|
||||||
|
crdObjects = append(crdObjects, obj)
|
||||||
|
default:
|
||||||
|
k8sObjects = append(k8sObjects, obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return k8sObjects, crdObjects
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,13 @@ type ServiceTCP struct {
|
||||||
Port intstr.IntOrString `json:"port"`
|
Port intstr.IntOrString `json:"port"`
|
||||||
// Weight defines the weight used when balancing requests between multiple Kubernetes Service.
|
// Weight defines the weight used when balancing requests between multiple Kubernetes Service.
|
||||||
Weight *int `json:"weight,omitempty"`
|
Weight *int `json:"weight,omitempty"`
|
||||||
|
// TerminationDelay defines the deadline that the proxy sets, after one of its connected peers indicates
|
||||||
|
// it has closed the writing capability of its connection, to close the reading capability as well,
|
||||||
|
// hence fully terminating the connection.
|
||||||
|
// It is a duration in milliseconds, defaulting to 100.
|
||||||
|
// A negative value means an infinite deadline (i.e. the reading capability is never closed).
|
||||||
|
// Deprecated: TerminationDelay is not supported APIVersion traefik.io/v1, please use ServersTransport to configure the TerminationDelay instead.
|
||||||
|
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
||||||
// ProxyProtocol defines the PROXY protocol configuration.
|
// ProxyProtocol defines the PROXY protocol configuration.
|
||||||
// More info: https://doc.traefik.io/traefik/v3.0/routing/services/#proxy-protocol
|
// More info: https://doc.traefik.io/traefik/v3.0/routing/services/#proxy-protocol
|
||||||
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
||||||
|
|
|
@ -171,6 +171,9 @@ type ClientTLS struct {
|
||||||
CertSecret string `json:"certSecret,omitempty"`
|
CertSecret string `json:"certSecret,omitempty"`
|
||||||
// InsecureSkipVerify defines whether the server certificates should be validated.
|
// InsecureSkipVerify defines whether the server certificates should be validated.
|
||||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||||
|
|
||||||
|
// Deprecated: TLS client authentication is a server side option (see https://github.com/golang/go/blob/740a490f71d026bb7d2d13cb8fa2d6d6e0572b70/src/crypto/tls/common.go#L634).
|
||||||
|
CAOptional *bool `json:"caOptional,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -26,9 +26,13 @@ type MiddlewareTCPSpec struct {
|
||||||
// InFlightConn defines the InFlightConn middleware configuration.
|
// InFlightConn defines the InFlightConn middleware configuration.
|
||||||
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
|
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
|
||||||
// IPWhiteList defines the IPWhiteList middleware configuration.
|
// IPWhiteList defines the IPWhiteList middleware configuration.
|
||||||
|
// This middleware accepts/refuses connections based on the client IP.
|
||||||
// Deprecated: please use IPAllowList instead.
|
// Deprecated: please use IPAllowList instead.
|
||||||
|
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipwhitelist/
|
||||||
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
||||||
// IPAllowList defines the IPAllowList middleware configuration.
|
// IPAllowList defines the IPAllowList middleware configuration.
|
||||||
|
// This middleware accepts/refuses connections based on the client IP.
|
||||||
|
// More info: https://doc.traefik.io/traefik/v3.0/middlewares/tcp/ipallowlist/
|
||||||
IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"`
|
IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ type TLSOptionSpec struct {
|
||||||
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
|
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
|
||||||
// More info: https://doc.traefik.io/traefik/v3.0/https/tls/#alpn-protocols
|
// More info: https://doc.traefik.io/traefik/v3.0/https/tls/#alpn-protocols
|
||||||
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
|
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
|
||||||
|
|
||||||
|
// PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
|
||||||
|
// It is enabled automatically when minVersion or maxVersion is set.
|
||||||
|
// Deprecated: https://github.com/golang/go/issues/45430
|
||||||
|
PreferServerCipherSuites *bool `json:"preferServerCipherSuites,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -146,6 +146,11 @@ func (in *ClientAuth) DeepCopy() *ClientAuth {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ClientTLS) DeepCopyInto(out *ClientTLS) {
|
func (in *ClientTLS) DeepCopyInto(out *ClientTLS) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.CAOptional != nil {
|
||||||
|
in, out := &in.CAOptional, &out.CAOptional
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +218,7 @@ func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
|
||||||
if in.TLS != nil {
|
if in.TLS != nil {
|
||||||
in, out := &in.TLS, &out.TLS
|
in, out := &in.TLS, &out.TLS
|
||||||
*out = new(ClientTLS)
|
*out = new(ClientTLS)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.AddAuthCookiesToResponse != nil {
|
if in.AddAuthCookiesToResponse != nil {
|
||||||
in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse
|
in, out := &in.AddAuthCookiesToResponse, &out.AddAuthCookiesToResponse
|
||||||
|
@ -777,7 +782,7 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
|
||||||
if in.ContentType != nil {
|
if in.ContentType != nil {
|
||||||
in, out := &in.ContentType, &out.ContentType
|
in, out := &in.ContentType, &out.ContentType
|
||||||
*out = new(dynamic.ContentType)
|
*out = new(dynamic.ContentType)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.GrpcWeb != nil {
|
if in.GrpcWeb != nil {
|
||||||
in, out := &in.GrpcWeb, &out.GrpcWeb
|
in, out := &in.GrpcWeb, &out.GrpcWeb
|
||||||
|
@ -1318,6 +1323,11 @@ func (in *ServiceTCP) DeepCopyInto(out *ServiceTCP) {
|
||||||
*out = new(int)
|
*out = new(int)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
|
if in.TerminationDelay != nil {
|
||||||
|
in, out := &in.TerminationDelay, &out.TerminationDelay
|
||||||
|
*out = new(int)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.ProxyProtocol != nil {
|
if in.ProxyProtocol != nil {
|
||||||
in, out := &in.ProxyProtocol, &out.ProxyProtocol
|
in, out := &in.ProxyProtocol, &out.ProxyProtocol
|
||||||
*out = new(dynamic.ProxyProtocol)
|
*out = new(dynamic.ProxyProtocol)
|
||||||
|
@ -1517,6 +1527,11 @@ func (in *TLSOptionSpec) DeepCopyInto(out *TLSOptionSpec) {
|
||||||
*out = make([]string, len(*in))
|
*out = make([]string, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
|
if in.PreferServerCipherSuites != nil {
|
||||||
|
in, out := &in.PreferServerCipherSuites, &out.PreferServerCipherSuites
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/types"
|
"github.com/traefik/traefik/v3/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Bool(v bool) *bool { return &v }
|
||||||
|
func String(v string) *string { return &v }
|
||||||
|
|
||||||
func Test_buildConfiguration(t *testing.T) {
|
func Test_buildConfiguration(t *testing.T) {
|
||||||
provider := newProviderMock(mapToPairs(map[string]string{
|
provider := newProviderMock(mapToPairs(map[string]string{
|
||||||
"traefik/http/routers/Router0/entryPoints/0": "foobar",
|
"traefik/http/routers/Router0/entryPoints/0": "foobar",
|
||||||
|
@ -79,6 +82,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/tls/key": "foobar",
|
"traefik/http/middlewares/Middleware08/forwardAuth/tls/key": "foobar",
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/tls/insecureSkipVerify": "true",
|
"traefik/http/middlewares/Middleware08/forwardAuth/tls/insecureSkipVerify": "true",
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/tls/ca": "foobar",
|
"traefik/http/middlewares/Middleware08/forwardAuth/tls/ca": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware08/forwardAuth/tls/caOptional": "true",
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/tls/cert": "foobar",
|
"traefik/http/middlewares/Middleware08/forwardAuth/tls/cert": "foobar",
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/address": "foobar",
|
"traefik/http/middlewares/Middleware08/forwardAuth/address": "foobar",
|
||||||
"traefik/http/middlewares/Middleware08/forwardAuth/trustForwardHeader": "true",
|
"traefik/http/middlewares/Middleware08/forwardAuth/trustForwardHeader": "true",
|
||||||
|
@ -105,8 +109,12 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginListRegex/1": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowOriginListRegex/1": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/contentTypeNosniff": "true",
|
"traefik/http/middlewares/Middleware09/headers/contentTypeNosniff": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlAllowCredentials": "true",
|
"traefik/http/middlewares/Middleware09/headers/accessControlAllowCredentials": "true",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/featurePolicy": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/permissionsPolicy": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/permissionsPolicy": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/forceSTSHeader": "true",
|
"traefik/http/middlewares/Middleware09/headers/forceSTSHeader": "true",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/sslRedirect": "true",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/sslHost": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/sslForceHost": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/sslProxyHeaders/name1": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/sslProxyHeaders/name1": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/sslProxyHeaders/name0": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/sslProxyHeaders/name0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/allowedHosts/0": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/allowedHosts/0": "foobar",
|
||||||
|
@ -125,6 +133,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware09/headers/addVaryHeader": "true",
|
"traefik/http/middlewares/Middleware09/headers/addVaryHeader": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/hostsProxyHeaders/0": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/hostsProxyHeaders/0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/hostsProxyHeaders/1": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/hostsProxyHeaders/1": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware09/headers/sslTemporaryRedirect": "true",
|
||||||
"traefik/http/middlewares/Middleware09/headers/customBrowserXSSValue": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/customBrowserXSSValue": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/referrerPolicy": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/referrerPolicy": "foobar",
|
||||||
"traefik/http/middlewares/Middleware09/headers/accessControlExposeHeaders/0": "foobar",
|
"traefik/http/middlewares/Middleware09/headers/accessControlExposeHeaders/0": "foobar",
|
||||||
|
@ -201,6 +210,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware18/retry/attempts": "42",
|
"traefik/http/middlewares/Middleware18/retry/attempts": "42",
|
||||||
"traefik/http/middlewares/Middleware19/stripPrefix/prefixes/0": "foobar",
|
"traefik/http/middlewares/Middleware19/stripPrefix/prefixes/0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware19/stripPrefix/prefixes/1": "foobar",
|
"traefik/http/middlewares/Middleware19/stripPrefix/prefixes/1": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware19/stripPrefix/forceSlash": "true",
|
||||||
"traefik/tcp/routers/TCPRouter0/entryPoints/0": "foobar",
|
"traefik/tcp/routers/TCPRouter0/entryPoints/0": "foobar",
|
||||||
"traefik/tcp/routers/TCPRouter0/entryPoints/1": "foobar",
|
"traefik/tcp/routers/TCPRouter0/entryPoints/1": "foobar",
|
||||||
"traefik/tcp/routers/TCPRouter0/service": "foobar",
|
"traefik/tcp/routers/TCPRouter0/service": "foobar",
|
||||||
|
@ -227,6 +237,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/tcp/routers/TCPRouter1/tls/passthrough": "true",
|
"traefik/tcp/routers/TCPRouter1/tls/passthrough": "true",
|
||||||
"traefik/tcp/routers/TCPRouter1/tls/options": "foobar",
|
"traefik/tcp/routers/TCPRouter1/tls/options": "foobar",
|
||||||
"traefik/tcp/routers/TCPRouter1/tls/certResolver": "foobar",
|
"traefik/tcp/routers/TCPRouter1/tls/certResolver": "foobar",
|
||||||
|
"traefik/tcp/services/TCPService01/loadBalancer/terminationDelay": "42",
|
||||||
"traefik/tcp/services/TCPService01/loadBalancer/servers/0/address": "foobar",
|
"traefik/tcp/services/TCPService01/loadBalancer/servers/0/address": "foobar",
|
||||||
"traefik/tcp/services/TCPService01/loadBalancer/servers/1/address": "foobar",
|
"traefik/tcp/services/TCPService01/loadBalancer/servers/1/address": "foobar",
|
||||||
"traefik/tcp/services/TCPService02/weighted/services/0/name": "foobar",
|
"traefik/tcp/services/TCPService02/weighted/services/0/name": "foobar",
|
||||||
|
@ -371,6 +382,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
},
|
},
|
||||||
|
ForceSlash: Bool(true),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware00": {
|
"Middleware00": {
|
||||||
|
@ -404,11 +416,12 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"Middleware08": {
|
"Middleware08": {
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "foobar",
|
Address: "foobar",
|
||||||
TLS: &types.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
CA: "foobar",
|
CA: "foobar",
|
||||||
Cert: "foobar",
|
Cert: "foobar",
|
||||||
Key: "foobar",
|
Key: "foobar",
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
|
CAOptional: Bool(true),
|
||||||
},
|
},
|
||||||
TrustForwardHeader: true,
|
TrustForwardHeader: true,
|
||||||
AuthResponseHeaders: []string{
|
AuthResponseHeaders: []string{
|
||||||
|
@ -581,10 +594,14 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"foobar",
|
"foobar",
|
||||||
"foobar",
|
"foobar",
|
||||||
},
|
},
|
||||||
|
SSLRedirect: Bool(true),
|
||||||
|
SSLTemporaryRedirect: Bool(true),
|
||||||
|
SSLHost: String("foobar"),
|
||||||
SSLProxyHeaders: map[string]string{
|
SSLProxyHeaders: map[string]string{
|
||||||
"name1": "foobar",
|
"name1": "foobar",
|
||||||
"name0": "foobar",
|
"name0": "foobar",
|
||||||
},
|
},
|
||||||
|
SSLForceHost: Bool(true),
|
||||||
STSSeconds: 42,
|
STSSeconds: 42,
|
||||||
STSIncludeSubdomains: true,
|
STSIncludeSubdomains: true,
|
||||||
STSPreload: true,
|
STSPreload: true,
|
||||||
|
@ -597,6 +614,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
ContentSecurityPolicy: "foobar",
|
ContentSecurityPolicy: "foobar",
|
||||||
PublicKey: "foobar",
|
PublicKey: "foobar",
|
||||||
ReferrerPolicy: "foobar",
|
ReferrerPolicy: "foobar",
|
||||||
|
FeaturePolicy: String("foobar"),
|
||||||
PermissionsPolicy: "foobar",
|
PermissionsPolicy: "foobar",
|
||||||
IsDevelopment: true,
|
IsDevelopment: true,
|
||||||
},
|
},
|
||||||
|
@ -757,6 +775,7 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"TCPService01": {
|
"TCPService01": {
|
||||||
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
TerminationDelay: func(v int) *int { return &v }(42),
|
||||||
Servers: []dynamic.TCPServer{
|
Servers: []dynamic.TCPServer{
|
||||||
{Address: "foobar"},
|
{Address: "foobar"},
|
||||||
{Address: "foobar"},
|
{Address: "foobar"},
|
||||||
|
|
|
@ -263,7 +263,7 @@ func init() {
|
||||||
},
|
},
|
||||||
ForwardAuth: &dynamic.ForwardAuth{
|
ForwardAuth: &dynamic.ForwardAuth{
|
||||||
Address: "127.0.0.1",
|
Address: "127.0.0.1",
|
||||||
TLS: &types.ClientTLS{
|
TLS: &dynamic.ClientTLS{
|
||||||
CA: "ca.pem",
|
CA: "ca.pem",
|
||||||
Cert: "cert.pem",
|
Cert: "cert.pem",
|
||||||
Key: "cert.pem",
|
Key: "cert.pem",
|
||||||
|
|
|
@ -184,7 +184,7 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (
|
||||||
return nil, badConf
|
return nil, badConf
|
||||||
}
|
}
|
||||||
middleware = func(next http.Handler) (http.Handler, error) {
|
middleware = func(next http.Handler) (http.Handler, error) {
|
||||||
return contenttype.New(ctx, next, middlewareName)
|
return contenttype.New(ctx, next, *config.ContentType, middlewareName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +240,8 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (
|
||||||
|
|
||||||
// IPWhiteList
|
// IPWhiteList
|
||||||
if config.IPWhiteList != nil {
|
if config.IPWhiteList != nil {
|
||||||
log.Warn().Msg("IPWhiteList is deprecated, please use IPAllowList instead.")
|
qualifiedName := provider.GetQualifiedName(ctx, middlewareName)
|
||||||
|
log.Warn().Msgf("Middleware %q of type IPWhiteList is deprecated, please use IPAllowList instead.", qualifiedName)
|
||||||
|
|
||||||
if middleware != nil {
|
if middleware != nil {
|
||||||
return nil, badConf
|
return nil, badConf
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/traefik/traefik/v3/pkg/logs"
|
"github.com/traefik/traefik/v3/pkg/logs"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/provider"
|
"github.com/traefik/traefik/v3/pkg/server/provider"
|
||||||
"github.com/traefik/traefik/v3/pkg/tcp"
|
"github.com/traefik/traefik/v3/pkg/tcp"
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Manager is the TCPHandlers factory.
|
// Manager is the TCPHandlers factory.
|
||||||
|
@ -53,6 +54,10 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han
|
||||||
case conf.LoadBalancer != nil:
|
case conf.LoadBalancer != nil:
|
||||||
loadBalancer := tcp.NewWRRLoadBalancer()
|
loadBalancer := tcp.NewWRRLoadBalancer()
|
||||||
|
|
||||||
|
if conf.LoadBalancer.TerminationDelay != nil {
|
||||||
|
log.Ctx(ctx).Warn().Msgf("Service %q load balancer uses `TerminationDelay`, but this option is deprecated, please use ServersTransport configuration instead.", serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
if len(conf.LoadBalancer.ServersTransport) > 0 {
|
if len(conf.LoadBalancer.ServersTransport) > 0 {
|
||||||
conf.LoadBalancer.ServersTransport = provider.GetQualifiedName(ctx, conf.LoadBalancer.ServersTransport)
|
conf.LoadBalancer.ServersTransport = provider.GetQualifiedName(ctx, conf.LoadBalancer.ServersTransport)
|
||||||
}
|
}
|
||||||
|
@ -72,6 +77,14 @@ func (m *Manager) BuildTCP(rootCtx context.Context, serviceName string) (tcp.Han
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle TerminationDelay deprecated option.
|
||||||
|
if conf.LoadBalancer.ServersTransport == "" && conf.LoadBalancer.TerminationDelay != nil {
|
||||||
|
dialer = &dialerWrapper{
|
||||||
|
Dialer: dialer,
|
||||||
|
terminationDelay: time.Duration(*conf.LoadBalancer.TerminationDelay),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handler, err := tcp.NewProxy(server.Address, conf.LoadBalancer.ProxyProtocol, dialer)
|
handler, err := tcp.NewProxy(server.Address, conf.LoadBalancer.ProxyProtocol, dialer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
srvLogger.Error().Err(err).Msg("Failed to create server")
|
srvLogger.Error().Err(err).Msg("Failed to create server")
|
||||||
|
@ -113,3 +126,13 @@ func shuffle[T any](values []T, r *rand.Rand) []T {
|
||||||
|
|
||||||
return shuffled
|
return shuffled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dialerWrapper is only used to handle TerminationDelay deprecated option on TCPServersLoadBalancer.
|
||||||
|
type dialerWrapper struct {
|
||||||
|
proxy.Dialer
|
||||||
|
terminationDelay time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d dialerWrapper) TerminationDelay() time.Duration {
|
||||||
|
return d.terminationDelay
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ type Options struct {
|
||||||
ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"`
|
ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"`
|
||||||
SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"`
|
SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"`
|
||||||
ALPNProtocols []string `json:"alpnProtocols,omitempty" toml:"alpnProtocols,omitempty" yaml:"alpnProtocols,omitempty" export:"true"`
|
ALPNProtocols []string `json:"alpnProtocols,omitempty" toml:"alpnProtocols,omitempty" yaml:"alpnProtocols,omitempty" export:"true"`
|
||||||
|
|
||||||
|
// Deprecated: https://github.com/golang/go/issues/45430
|
||||||
|
PreferServerCipherSuites *bool `json:"preferServerCipherSuites,omitempty" toml:"preferServerCipherSuites,omitempty" yaml:"preferServerCipherSuites,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values for an Options struct.
|
// SetDefaults sets the default values for an Options struct.
|
||||||
|
|
|
@ -68,6 +68,13 @@ func (m *Manager) UpdateConfigs(ctx context.Context, stores map[string]Store, co
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
m.configs = configs
|
m.configs = configs
|
||||||
|
for optionName, option := range m.configs {
|
||||||
|
// Handle `PreferServerCipherSuites` depreciation
|
||||||
|
if option.PreferServerCipherSuites != nil {
|
||||||
|
log.Ctx(ctx).Warn().Msgf("TLSOption %q uses `PreferServerCipherSuites` option, but this option is deprecated and ineffective, please remove this option.", optionName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m.storesConfig = stores
|
m.storesConfig = stores
|
||||||
m.certs = certs
|
m.certs = certs
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,11 @@ func (in *Options) DeepCopyInto(out *Options) {
|
||||||
*out = make([]string, len(*in))
|
*out = make([]string, len(*in))
|
||||||
copy(*out, *in)
|
copy(*out, *in)
|
||||||
}
|
}
|
||||||
|
if in.PreferServerCipherSuites != nil {
|
||||||
|
in, out := &in.PreferServerCipherSuites, &out.PreferServerCipherSuites
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue