Merge current v2.5 into master

This commit is contained in:
Tom Moulard 2021-09-23 15:30:01 +02:00
commit 380514941c
No known key found for this signature in database
GPG key ID: 521ABE0C1A0DEAF6
35 changed files with 773 additions and 161 deletions

View file

@ -7,7 +7,7 @@ on:
env: env:
GO_VERSION: 1.17 GO_VERSION: 1.17
GOLANGCI_LINT_VERSION: v1.41.1 GOLANGCI_LINT_VERSION: v1.42.1
MISSSPELL_VERSION: v0.3.4 MISSSPELL_VERSION: v0.3.4
PRE_TARGET: "" PRE_TARGET: ""

View file

@ -16,9 +16,6 @@
[linters-settings.gocyclo] [linters-settings.gocyclo]
min-complexity = 14.0 min-complexity = 14.0
[linters-settings.maligned]
suggest-new = true
[linters-settings.goconst] [linters-settings.goconst]
min-len = 3.0 min-len = 3.0
min-occurrences = 4.0 min-occurrences = 4.0

View file

@ -25,7 +25,7 @@ global_job_config:
- export "PATH=${GOPATH}/bin:${PATH}" - export "PATH=${GOPATH}/bin:${PATH}"
- mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin" - mkdir -vp "${SEMAPHORE_GIT_DIR}" "${GOPATH}/bin"
- export GOPROXY=https://proxy.golang.org,direct - export GOPROXY=https://proxy.golang.org,direct
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.41.1 - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOPATH}/bin" v1.42.1
- curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | bash -s -- -b "${GOPATH}/bin" - curl -sfL https://install.goreleaser.com/github.com/goreleaser/goreleaser.sh | bash -s -- -b "${GOPATH}/bin"
- checkout - checkout
- cache restore traefik-$(checksum go.sum) - cache restore traefik-$(checksum go.sum)

View file

@ -1,3 +1,21 @@
## [v2.5.3](https://github.com/traefik/traefik/tree/v2.5.3) (2021-09-20)
[All Commits](https://github.com/traefik/traefik/compare/v2.5.2...v2.5.3)
**Bug fixes:**
- **[consulcatalog]** Fix certChan defaulting on consul catalog provider ([#8439](https://github.com/traefik/traefik/pull/8439) by [tomMoulard](https://github.com/tomMoulard))
- **[k8s/crd,k8s]** Fix peerCertURI config for k8s crd provider ([#8454](https://github.com/traefik/traefik/pull/8454) by [kevinpollet](https://github.com/kevinpollet))
- **[k8s/crd,k8s]** Ensure disableHTTP2 works with k8s crd ([#8448](https://github.com/traefik/traefik/pull/8448) by [ssboisen](https://github.com/ssboisen))
- **[k8s/crd,k8s]** Fix ServersTransport reference from IngressRoute service definition ([#8431](https://github.com/traefik/traefik/pull/8431) by [rtribotte](https://github.com/rtribotte))
- **[k8s/crd,k8s]** Add cross namespace verification in Kubernetes CRD ([#8422](https://github.com/traefik/traefik/pull/8422) by [tomMoulard](https://github.com/tomMoulard))
- **[metrics]** Fix Prometheus router's metrics ([#8425](https://github.com/traefik/traefik/pull/8425) by [tomMoulard](https://github.com/tomMoulard))
- **[plugins]** Update yaegi to v0.10.0 ([#8452](https://github.com/traefik/traefik/pull/8452) by [ldez](https://github.com/ldez))
**Documentation:**
- **[middleware,file]** Fix TCP middleware whitelist example ([#8421](https://github.com/traefik/traefik/pull/8421) by [tribal2](https://github.com/tribal2))
- **[middleware]** Add default proxy headers list ([#8418](https://github.com/traefik/traefik/pull/8418) by [aaronraff](https://github.com/aaronraff))
- Add Tom Moulard in maintainers team ([#8442](https://github.com/traefik/traefik/pull/8442) by [jbdoumenjou](https://github.com/jbdoumenjou))
- Fix golang doc URLs ([#8434](https://github.com/traefik/traefik/pull/8434) by [jbdoumenjou](https://github.com/jbdoumenjou))
## [v2.5.2](https://github.com/traefik/traefik/tree/v2.5.2) (2021-09-02) ## [v2.5.2](https://github.com/traefik/traefik/tree/v2.5.2) (2021-09-02)
[All Commits](https://github.com/traefik/traefik/compare/v2.5.1...v2.5.2) [All Commits](https://github.com/traefik/traefik/compare/v2.5.1...v2.5.2)

View file

@ -14,7 +14,7 @@ RUN mkdir -p /usr/local/bin \
| tar -xzC /usr/local/bin --transform 's#^.+/##x' | tar -xzC /usr/local/bin --transform 's#^.+/##x'
# Download golangci-lint binary to bin folder in $GOPATH # Download golangci-lint binary to bin folder in $GOPATH
RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.41.1 RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.42.1
# Download misspell binary to bin folder in $GOPATH # Download misspell binary to bin folder in $GOPATH
RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4 RUN curl -sfL https://raw.githubusercontent.com/client9/misspell/master/install-misspell.sh | bash -s -- -b $GOPATH/bin v0.3.4

View file

@ -258,7 +258,7 @@ type fileWriter struct {
} }
func (f fileWriter) Write(files map[string]*File) error { func (f fileWriter) Write(files map[string]*File) error {
err := os.MkdirAll(f.baseDir, 0755) err := os.MkdirAll(f.baseDir, 0o755)
if err != nil { if err != nil {
return err return err
} }

View file

@ -83,7 +83,7 @@ func run(dest string) error {
return err return err
} }
return ioutil.WriteFile(filepath.Join(dest, "marshaler.go"), []byte(fmt.Sprintf(marsh, destPkg)), 0666) return ioutil.WriteFile(filepath.Join(dest, "marshaler.go"), []byte(fmt.Sprintf(marsh, destPkg)), 0o666)
} }
func cleanType(typ types.Type, base string) string { func cleanType(typ types.Type, base string) string {

View file

@ -19,6 +19,7 @@
* Romain Tribotté [@rtribotte](https://github.com/rtribotte) * Romain Tribotté [@rtribotte](https://github.com/rtribotte)
* Kevin Pollet [@kevinpollet](https://github.com/kevinpollet) * Kevin Pollet [@kevinpollet](https://github.com/kevinpollet)
* Harold Ozouf [@jspdown](https://github.com/jspdown) * Harold Ozouf [@jspdown](https://github.com/jspdown)
* Tom Moulard [@tommoulard](https://github.com/tommoulard)
## Maintainer's Guidelines ## Maintainer's Guidelines

View file

@ -125,7 +125,7 @@ http:
the principle of the above example above (a catchall router) still stands, the principle of the above example above (a catchall router) still stands,
but the `unavailable` service should be adapted to fit such a need. but the `unavailable` service should be adapted to fit such a need.
## Why Is My TLS Certificate Not Reloaded When Its Contents Change ? ## Why Is My TLS Certificate Not Reloaded When Its Contents Change?
With the file provider, With the file provider,
a configuration update is only triggered when one of the [watched](../providers/file.md#provider-configuration) configuration files is modified. a configuration update is only triggered when one of the [watched](../providers/file.md#provider-configuration) configuration files is modified.
@ -137,3 +137,18 @@ a configuration update is _not_ triggered.
To take into account the new certificate contents, the update of the dynamic configuration must be forced. To take into account the new certificate contents, the update of the dynamic configuration must be forced.
One way to achieve that, is to trigger a file notification, One way to achieve that, is to trigger a file notification,
for example, by using the `touch` command on the configuration file. for example, by using the `touch` command on the configuration file.
## What Are the Forwarded Headers When Proxying HTTP Requests?
By default, the following headers are automatically added when proxying requests:
| Property | HTTP Header |
|---------------------------|----------------------------|
| Client's IP | X-Forwarded-For, X-Real-Ip |
| Host | X-Forwarded-Host |
| Port | X-Forwarded-Port |
| Protocol | X-Forwarded-Proto |
| Proxy Server's Hostname | X-Forwarded-Server |
For more details,
please check out the [forwarded header](../routing/entrypoints.md#forwarded-headers) documentation.

View file

@ -7,6 +7,8 @@ Managing Request/Response headers
The Headers middleware manages the headers of requests and responses. The Headers middleware manages the headers of requests and responses.
A set of forwarded headers are automatically added by default. See the [FAQ](../../getting-started/faq.md#what-are-the-forwarded-headers-when-proxying-http-requests) for more information.
## Configuration Examples ## Configuration Examples
### Adding Headers to the Request and the Response ### Adding Headers to the Request and the Response

View file

@ -337,7 +337,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
responseForwarding: responseForwarding:
flushInterval: 1ms flushInterval: 1ms
scheme: https scheme: https
serversTransport: transport serversTransport: transport # [10]
sticky: sticky:
cookie: cookie:
httpOnly: true httpOnly: true
@ -346,39 +346,40 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
sameSite: none sameSite: none
strategy: RoundRobin strategy: RoundRobin
weight: 10 weight: 10
tls: # [10] tls: # [11]
secretName: supersecret # [11] secretName: supersecret # [12]
options: # [12] options: # [13]
name: opt # [13] name: opt # [14]
namespace: default # [14] namespace: default # [15]
certResolver: foo # [15] certResolver: foo # [16]
domains: # [16] domains: # [17]
- main: example.net # [17] - main: example.net # [18]
sans: # [18] sans: # [19]
- a.example.net - a.example.net
- b.example.net - b.example.net
``` ```
| Ref | Attribute | Purpose | | Ref | Attribute | Purpose |
|------|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |------|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) names | | [1] | `entryPoints` | List of [entry points](../routers/index.md#entrypoints) names |
| [2] | `routes` | List of routes | | [2] | `routes` | List of routes |
| [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule) corresponding to an underlying router. | | [3] | `routes[n].match` | Defines the [rule](../routers/index.md#rule) corresponding to an underlying router. |
| [4] | `routes[n].priority` | [Disambiguate](../routers/index.md#priority) rules of the same length, for route matching | | [4] | `routes[n].priority` | [Disambiguate](../routers/index.md#priority) rules of the same length, for route matching |
| [5] | `routes[n].middlewares` | List of reference to [Middleware](#kind-middleware) | | [5] | `routes[n].middlewares` | List of reference to [Middleware](#kind-middleware) |
| [6] | `middlewares[n].name` | Defines the [Middleware](#kind-middleware) name | | [6] | `middlewares[n].name` | Defines the [Middleware](#kind-middleware) name |
| [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace | | [7] | `middlewares[n].namespace` | Defines the [Middleware](#kind-middleware) namespace |
| [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) | | [8] | `routes[n].services` | List of any combination of [TraefikService](#kind-traefikservice) and reference to a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) (See below for `ExternalName Service` setup) |
| [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. | | [9] | `services[n].port` | Defines the port of a [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/). This can be a reference to a named port. |
| [10] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration | | [10] | `services[n].serversTransport` | Defines the reference to a [ServersTransport](#kind-serverstransport). The ServersTransport namespace is assumed to be the [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace (see [ServersTransport reference](#serverstransport-reference)). |
| [11] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) | | [11] | `tls` | Defines [TLS](../routers/index.md#tls) certificate configuration |
| [12] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) | | [12] | `tls.secretName` | Defines the [secret](https://kubernetes.io/docs/concepts/configuration/secret/) name used to store the certificate (in the `IngressRoute` namespace) |
| [13] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name | | [13] | `tls.options` | Defines the reference to a [TLSOption](#kind-tlsoption) |
| [14] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace | | [14] | `options.name` | Defines the [TLSOption](#kind-tlsoption) name |
| [15] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) | | [15] | `options.namespace` | Defines the [TLSOption](#kind-tlsoption) namespace |
| [16] | `tls.domains` | List of [domains](../routers/index.md#domains) | | [16] | `tls.certResolver` | Defines the reference to a [CertResolver](../routers/index.md#certresolver) |
| [17] | `domains[n].main` | Defines the main domain name | | [17] | `tls.domains` | List of [domains](../routers/index.md#domains) |
| [18] | `domains[n].sans` | List of SANs (alternative domains) | | [18] | `domains[n].main` | Defines the main domain name |
| [19] | `domains[n].sans` | List of SANs (alternative domains) |
??? example "Declaring an IngressRoute" ??? example "Declaring an IngressRoute"
@ -476,7 +477,7 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
!!! important "Using Kubernetes ExternalName Service" !!! important "Using Kubernetes ExternalName Service"
Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/fr/docs/concepts/services-networking/service/#externalname) could be defined without any port. Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) could be defined without any port.
Accordingly, Traefik supports defining a port in two ways: Accordingly, Traefik supports defining a port in two ways:
- only on `IngressRoute` service - only on `IngressRoute` service
@ -1199,7 +1200,7 @@ Register the `IngressRouteTCP` [kind](../../reference/dynamic-configuration/kube
!!! important "Using Kubernetes ExternalName Service" !!! important "Using Kubernetes ExternalName Service"
Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/fr/docs/concepts/services-networking/service/#externalname) could be defined without any port. Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) could be defined without any port.
Accordingly, Traefik supports defining a port in two ways: Accordingly, Traefik supports defining a port in two ways:
- only on `IngressRouteTCP` service - only on `IngressRouteTCP` service
@ -1378,7 +1379,7 @@ Register the `IngressRouteUDP` [kind](../../reference/dynamic-configuration/kube
!!! important "Using Kubernetes ExternalName Service" !!! important "Using Kubernetes ExternalName Service"
Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/fr/docs/concepts/services-networking/service/#externalname) could be defined without any port. Traefik backends creation needs a port to be set, however Kubernetes [ExternalName Service](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) could be defined without any port.
Accordingly, Traefik supports defining a port in two ways: Accordingly, Traefik supports defining a port in two ways:
- only on `IngressRouteUDP` service - only on `IngressRouteUDP` service
@ -1687,7 +1688,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres
!!! info "ServersTransport Attributes" !!! info "ServersTransport Attributes"
```yaml tab="TLSStore" ```yaml tab="ServersTransport"
apiVersion: traefik.containo.us/v1alpha1 apiVersion: traefik.containo.us/v1alpha1
kind: ServersTransport kind: ServersTransport
metadata: metadata:
@ -1709,20 +1710,22 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres
responseHeaderTimeout: 42s # [8] responseHeaderTimeout: 42s # [8]
idleConnTimeout: 42s # [9] idleConnTimeout: 42s # [9]
peerCertURI: foobar # [10] peerCertURI: foobar # [10]
disableHTTP2: true # [11]
``` ```
| Ref | Attribute | Purpose | | Ref | Attribute | Purpose |
|------|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| |------|-------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [1] | `serverName` | ServerName used to contact the server. | | [1] | `serverName` | ServerName used to contact the server. |
| [2] | `insecureSkipVerify` | Disable SSL certificate verification. | | [2] | `insecureSkipVerify` | Controls whether the server's certificate chain and host name is verified. |
| [3] | `rootCAsSecrets` | Add cert file for self-signed certificate. The secret must contain a certificate under either a tls.ca or a ca.crt key. | | [3] | `rootCAsSecrets` | Defines the set of root certificate authorities to use when verifying server certificates. The secret must contain a certificate under either a tls.ca or a ca.crt key. |
| [4] | `certificatesSecrets` | Certificates for mTLS. | | [4] | `certificatesSecrets` | Certificates to present to the server for mTLS. |
| [5] | `maxIdleConnsPerHost` | If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, `defaultMaxIdleConnsPerHost` is used. | | [5] | `maxIdleConnsPerHost` | Controls the maximum idle (keep-alive) connections to keep per-host. If zero, `defaultMaxIdleConnsPerHost` is used. |
| [6] | `forwardingTimeouts` | Timeouts for requests forwarded to the backend servers. | | [6] | `forwardingTimeouts` | Timeouts for requests forwarded to the servers. |
| [7] | `dialTimeout` | The amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists. | | [7] | `dialTimeout` | The amount of time to wait until a connection to a server can be established. If zero, no timeout exists. |
| [8] | `responseHeaderTimeout` | The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists. | | [8] | `responseHeaderTimeout` | The amount of time to wait for a server's response headers after fully writing the request (including its body, if any). If zero, no timeout exists. |
| [9] | `idleConnTimeout` | The maximum period for which an idle HTTP keep-alive connection will remain open before closing itself. | | [9] | `idleConnTimeout` | The maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. If zero, no timeout exists. |
| [10] | `peerCertURI` | URI used to match with service certificate. | | [10] | `peerCertURI` | URI used to match against SAN URIs during the server's certificate verification. |
| [11] | `disableHTTP2` | Disables HTTP/2 for connections with servers. |
!!! info "CA Secret" !!! info "CA Secret"
@ -1761,6 +1764,16 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres
serversTransport: mytransport serversTransport: mytransport
``` ```
#### ServersTransport reference
By default, the referenced ServersTransport CRD must be defined in the same [Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/service/) namespace.
To reference a ServersTransport CRD from another namespace,
the value must be of form `namespace-name@kubernetescrd`,
and the [cross-namespace](../../../providers/kubernetes-crd/#allowcrossnamespace) option must be enabled.
If the ServersTransport CRD is defined in another provider the cross-provider format `name@provider` should be used.
## Further ## Further
Also see the [full example](../../user-guides/crd-acme/index.md) with Let's Encrypt. Also see the [full example](../../user-guides/crd-acme/index.md) with Let's Encrypt.

View file

@ -606,7 +606,7 @@ metadata:
_Optional_ _Optional_
`insecureSkipVerify` disables SSL certificate verification. `insecureSkipVerify` controls whether the server's certificate chain and host name is verified.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
@ -637,8 +637,7 @@ spec:
_Optional_ _Optional_
`rootCAs` is the list of certificates (as file paths, or data bytes) `rootCAs` defines the set of root certificate authorities (as file paths, or data bytes) to use when verifying server certificates.
that will be set as Root Certificate Authorities when using a self-signed TLS certificate.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
## Dynamic configuration ## Dynamic configuration
@ -711,7 +710,7 @@ spec:
_Optional, Default=false_ _Optional, Default=false_
`disableHTTP2` disables HTTP/2 for connections with backend servers. `disableHTTP2` disables HTTP/2 for connections with servers.
```toml tab="File (TOML)" ```toml tab="File (TOML)"
## Dynamic configuration ## Dynamic configuration
@ -742,7 +741,7 @@ spec:
_Optional, Default=false_ _Optional, Default=false_
`peerCertURI` defines the URI used to match against SAN URI during the peer certificate verification. `peerCertURI` defines the URI used to match against SAN URIs during the server's certificate verification.
```toml tab="File (TOML)" ```toml tab="File (TOML)"
## Dynamic configuration ## Dynamic configuration
@ -771,7 +770,7 @@ spec:
#### `forwardingTimeouts` #### `forwardingTimeouts`
`forwardingTimeouts` is about a number of timeouts relevant to when forwarding requests to the backend servers. `forwardingTimeouts` are the timeouts applied when forwarding requests to the servers.
##### `forwardingTimeouts.dialTimeout` ##### `forwardingTimeouts.dialTimeout`
@ -847,8 +846,7 @@ spec:
_Optional, Default=90s_ _Optional, Default=90s_
`idleConnTimeout`, is the maximum amount of time an idle (keep-alive) connection `idleConnTimeout` is the maximum amount of time an idle (keep-alive) connection will remain idle before closing itself.
will remain idle before closing itself.
Zero means no limit. Zero means no limit.
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"

2
go.mod
View file

@ -72,7 +72,7 @@ require (
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154 github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
github.com/tinylib/msgp v1.0.2 // indirect github.com/tinylib/msgp v1.0.2 // indirect
github.com/traefik/paerser v0.1.4 github.com/traefik/paerser v0.1.4
github.com/traefik/yaegi v0.9.23 github.com/traefik/yaegi v0.10.0
github.com/uber/jaeger-client-go v2.29.1+incompatible github.com/uber/jaeger-client-go v2.29.1+incompatible
github.com/uber/jaeger-lib v2.2.0+incompatible github.com/uber/jaeger-lib v2.2.0+incompatible
github.com/unrolled/render v1.0.2 github.com/unrolled/render v1.0.2

4
go.sum
View file

@ -1137,8 +1137,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/traefik/paerser v0.1.4 h1:/IXjV04Gf6di51H8Jl7jyS3OylsLjIasrwXIIwj1aT8= github.com/traefik/paerser v0.1.4 h1:/IXjV04Gf6di51H8Jl7jyS3OylsLjIasrwXIIwj1aT8=
github.com/traefik/paerser v0.1.4/go.mod h1:FIdQ4Y92ulQUGSeZgxchtBKEcLw1o551PMNg9PoIq/4= github.com/traefik/paerser v0.1.4/go.mod h1:FIdQ4Y92ulQUGSeZgxchtBKEcLw1o551PMNg9PoIq/4=
github.com/traefik/yaegi v0.9.23 h1:QM2DZCZZJBwAxiST2JhHnL1yze2XkeNZcnUPlB+2fCE= github.com/traefik/yaegi v0.10.0 h1:c/0rhUcj5+KJhJX++eCrPeKXnJaOZ17X8gYCznU9Xxc=
github.com/traefik/yaegi v0.9.23/go.mod h1:FAYnRlZyuVlEkvnkHq3bvJ1lW5be6XuwgLdkYgYG6Lk= github.com/traefik/yaegi v0.10.0/go.mod h1:RuCwD8/wsX7b6KoQHOaIFUfuH3gQIK4KWnFFmJMw5VA=
github.com/transip/gotransip/v6 v6.2.0 h1:0Z+qVsyeiQdWfcAUeJyF0IEKAPvhJwwpwPi2WGtBIiE= github.com/transip/gotransip/v6 v6.2.0 h1:0Z+qVsyeiQdWfcAUeJyF0IEKAPvhJwwpwPi2WGtBIiE=
github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=

View file

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package integration package integration

View file

@ -333,21 +333,24 @@ func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) {
err = try.GetRequest("http://127.0.0.1:8000/whoami2", 1*time.Second, try.StatusCodeIs(http.StatusOK)) err = try.GetRequest("http://127.0.0.1:8000/whoami2", 1*time.Second, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil) // adding a loop to test if metrics are not deleted
c.Assert(err, checker.IsNil) for i := 0; i < 10; i++ {
request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil)
c.Assert(err, checker.IsNil)
response, err := http.DefaultClient.Do(request) response, err := http.DefaultClient.Do(request)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, http.StatusOK) c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
body, err := io.ReadAll(response.Body) body, err := io.ReadAll(response.Body)
c.Assert(err, checker.IsNil) c.Assert(err, checker.IsNil)
// Reqs count of 1 for both routers // Reqs count of 1 for both routers
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-integrationtestbase\"} 1") c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router1@docker\",service=\"whoami1-integrationtestbase@docker\"} 1")
c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-integrationtestbase\"} 1") c.Assert(string(body), checker.Contains, "traefik_router_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",router=\"router2@docker\",service=\"whoami1-integrationtestbase@docker\"} 1")
// Reqs count of 2 for service behind both routers // Reqs count of 2 for service behind both routers
c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-integrationtestbase@docker\"} 2") c.Assert(string(body), checker.Contains, "traefik_service_requests_total{code=\"200\",method=\"GET\",protocol=\"http\",service=\"whoami1-integrationtestbase@docker\"} 2")
}
} }
func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) { func (s *SimpleSuite) TestMultipleProviderSameBackendName(c *check.C) {

View file

@ -180,7 +180,7 @@
} }
], ],
"passHostHeader": true, "passHostHeader": true,
"serversTransport": "mytransport@kubernetescrd" "serversTransport": "default-mytransport@kubernetescrd"
}, },
"status": "enabled", "status": "enabled",
"usedBy": [ "usedBy": [

View file

@ -468,7 +468,7 @@ func TestDo_dynamicConfiguration(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
require.NoError(t, os.WriteFile("testdata/anonymized-dynamic-config.json", []byte(cleanJSON), 0666)) require.NoError(t, os.WriteFile("testdata/anonymized-dynamic-config.json", []byte(cleanJSON), 0o666))
} }
expected := strings.TrimSuffix(string(expectedConfiguration), "\n") expected := strings.TrimSuffix(string(expectedConfiguration), "\n")
@ -963,7 +963,7 @@ func TestDo_staticConfiguration(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
if *updateExpected { if *updateExpected {
require.NoError(t, os.WriteFile("testdata/anonymized-static-config.json", []byte(cleanJSON), 0666)) require.NoError(t, os.WriteFile("testdata/anonymized-static-config.json", []byte(cleanJSON), 0o666))
} }
expected := strings.TrimSuffix(string(expectedConfiguration), "\n") expected := strings.TrimSuffix(string(expectedConfiguration), "\n")

View file

@ -68,7 +68,7 @@ func Test_ContentSecurityPolicy(t *testing.T) {
desc: "OK", desc: "OK",
handler: Handler{ handler: Handler{
assets: fstest.MapFS{"foobar.html": &fstest.MapFile{ assets: fstest.MapFS{"foobar.html": &fstest.MapFile{
Mode: 0755, Mode: 0o755,
ModTime: time.Now(), ModTime: time.Now(),
}}, }},
}, },

View file

@ -380,6 +380,12 @@ func (ps *prometheusState) isOutdated(collector *collector) bool {
return true return true
} }
if routerName, ok := labels["router"]; ok {
if !ps.dynamicConfig.hasRouter(routerName) {
return true
}
}
if serviceName, ok := labels["service"]; ok { if serviceName, ok := labels["service"]; ok {
if !ps.dynamicConfig.hasService(serviceName) { if !ps.dynamicConfig.hasService(serviceName) {
return true return true
@ -420,6 +426,11 @@ func (d *dynamicConfig) hasService(serviceName string) bool {
return ok return ok
} }
func (d *dynamicConfig) hasRouter(routerName string) bool {
_, ok := d.routers[routerName]
return ok
}
func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool { func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool {
if service, hasService := d.services[serviceName]; hasService { if service, hasService := d.services[serviceName]; hasService {
_, ok := service[serverURL] _, ok := service[serverURL]

View file

@ -364,7 +364,7 @@ func TestPrometheusMetricRemoval(t *testing.T) {
// Reset state of global promState. // Reset state of global promState.
defer promState.reset() defer promState.reset()
prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true}) prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true, AddRoutersLabels: true})
defer promRegistry.Unregister(promState) defer promRegistry.Unregister(promState)
conf := dynamic.Configuration{ conf := dynamic.Configuration{
@ -401,11 +401,14 @@ func TestPrometheusMetricRemoval(t *testing.T) {
ServiceServerUpGauge(). ServiceServerUpGauge().
With("service", "service1", "url", "http://localhost:9999"). With("service", "service1", "url", "http://localhost:9999").
Set(1) Set(1)
prometheusRegistry.
delayForTrackingCompletion() RouterReqsCounter().
With("router", "router2", "service", "service2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
Add(1)
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName) assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName)
assertMetricsAbsent(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName) assertMetricsAbsent(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName)
assertMetricsAbsent(t, mustScrape(), routerReqsTotalName, routerReqDurationName, routerOpenConnsName)
// To verify that metrics belonging to active configurations are not removed // To verify that metrics belonging to active configurations are not removed
// here the counter examples. // here the counter examples.
@ -413,11 +416,17 @@ func TestPrometheusMetricRemoval(t *testing.T) {
EntryPointReqsCounter(). EntryPointReqsCounter().
With("entrypoint", "entrypoint1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http"). With("entrypoint", "entrypoint1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
Add(1) Add(1)
prometheusRegistry.
RouterReqsCounter().
With("router", "foo@providerName", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
Add(1)
delayForTrackingCompletion() delayForTrackingCompletion()
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName) assertMetricsExist(t, mustScrape(), entryPointReqsTotalName)
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName) assertMetricsExist(t, mustScrape(), entryPointReqsTotalName)
assertMetricsExist(t, mustScrape(), routerReqsTotalName)
assertMetricsExist(t, mustScrape(), routerReqsTotalName)
} }
func TestPrometheusRemovedMetricsReset(t *testing.T) { func TestPrometheusRemovedMetricsReset(t *testing.T) {

View file

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package acme package acme

View file

@ -87,7 +87,6 @@ func (p *Provider) SetDefaults() {
p.ExposedByDefault = true p.ExposedByDefault = true
p.DefaultRule = DefaultTemplateRule p.DefaultRule = DefaultTemplateRule
p.ServiceName = "traefik" p.ServiceName = "traefik"
p.certChan = make(chan *connectCert)
} }
// Init the provider. // Init the provider.
@ -98,6 +97,7 @@ func (p *Provider) Init() error {
} }
p.defaultRuleTpl = defaultRuleTpl p.defaultRuleTpl = defaultRuleTpl
p.certChan = make(chan *connectCert)
return nil return nil
} }

View file

@ -0,0 +1,30 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: HostSNI(`foo.com`)
services:
- name: whoamitcp
port: 8000
tls:
options:
name: tls-options-cn
namespace: cross-ns
---
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: tls-options-cn
namespace: cross-ns
spec:
minVersion: VersionTLS12

View file

@ -9,23 +9,31 @@ spec:
- foo - foo
routes: routes:
- match: Host(`foo.com`) && PathPrefix(`/bar`) - match: Host(`foo.com`) && PathPrefix(`/bar`)
kind: Rule kind: Rule
priority: 12 priority: 12
services: services:
- name: whoami-svc - name: whoami-svc
namespace: cross-ns namespace: cross-ns
port: 80 port: 80
- name: tr-svc-wrr1 - name: tr-svc-wrr1
kind: TraefikService kind: TraefikService
- name: tr-svc-wrr2 - name: tr-svc-wrr2
namespace: cross-ns namespace: cross-ns
kind: TraefikService kind: TraefikService
- name: tr-svc-mirror1 - name: tr-svc-mirror1
kind: TraefikService kind: TraefikService
- name: tr-svc-mirror2 - name: tr-svc-mirror2
namespace: cross-ns namespace: cross-ns
kind: TraefikService kind: TraefikService
- match: Host(`bar.com`) && PathPrefix(`/foo`)
kind: Rule
services:
- name: whoami-svc
namespace: cross-ns
port: 80
serversTransport: foo-test@kubernetescrd
--- ---
apiVersion: traefik.containo.us/v1alpha1 apiVersion: traefik.containo.us/v1alpha1
@ -89,3 +97,13 @@ spec:
namespace: cross-ns namespace: cross-ns
percent: 20 percent: 20
port: 80 port: 80
---
apiVersion: traefik.containo.us/v1alpha1
kind: ServersTransport
metadata:
name: test
namespace: foo
spec:
serverName: "test"

View file

@ -93,18 +93,53 @@ spec:
serverName: "test" serverName: "test"
insecureSkipVerify: true insecureSkipVerify: true
maxIdleConnsPerHost: 42 maxIdleConnsPerHost: 42
disableHTTP2: true
peerCertURI: foo://bar
rootCAsSecrets: rootCAsSecrets:
- root-ca0 - root-ca0
- root-ca1 - root-ca1
- root-ca2 - root-ca2
- root-ca3 - root-ca3
- root-ca4 - root-ca4
- allcerts - allcerts
certificatesSecrets: certificatesSecrets:
- mtls1 - mtls1
- mtls2 - mtls2
- allcerts - allcerts
forwardingTimeouts: forwardingTimeouts:
dialTimeout: 42 dialTimeout: 42
responseHeaderTimeout: 42s responseHeaderTimeout: 42s
idleConnTimeout: 42ms idleConnTimeout: 42ms
---
apiVersion: traefik.containo.us/v1alpha1
kind: ServersTransport
metadata:
name: test
namespace: default
spec:
serverName: "test"
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: Host(`foo.com`)
kind: Rule
services:
- name: external-svc-with-https
port: 443
serversTransport: test
- name: whoamitls
port: 443
serversTransport: default-test

View file

@ -0,0 +1,29 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: Host(`foo.com`) && PathPrefix(`/bar`)
kind: Rule
priority: 12
services:
- name: whoami
port: 80
serversTransport: cross-ns-st-cross-ns@kubernetescrd
---
apiVersion: traefik.containo.us/v1alpha1
kind: ServersTransport
metadata:
name: st-cross-ns
namespace: cross-ns
spec:
disableHTTP2: true

View file

@ -0,0 +1,31 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test.route
namespace: default
spec:
entryPoints:
- foo
routes:
- match: Host(`foo.com`) && PathPrefix(`/bar`)
kind: Rule
priority: 12
services:
- name: whoami
port: 80
tls:
options:
name: tls-options-cn
namespace: cross-ns
---
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: tls-options-cn
namespace: cross-ns
spec:
minVersion: VersionTLS12

View file

@ -341,13 +341,16 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
} }
} }
conf.HTTP.ServersTransports[serversTransport.Name] = &dynamic.ServersTransport{ id := provider.Normalize(makeID(serversTransport.Namespace, serversTransport.Name))
conf.HTTP.ServersTransports[id] = &dynamic.ServersTransport{
ServerName: serversTransport.Spec.ServerName, ServerName: serversTransport.Spec.ServerName,
InsecureSkipVerify: serversTransport.Spec.InsecureSkipVerify, InsecureSkipVerify: serversTransport.Spec.InsecureSkipVerify,
RootCAs: rootCAs, RootCAs: rootCAs,
Certificates: certs, Certificates: certs,
DisableHTTP2: serversTransport.Spec.DisableHTTP2,
MaxIdleConnsPerHost: serversTransport.Spec.MaxIdleConnsPerHost, MaxIdleConnsPerHost: serversTransport.Spec.MaxIdleConnsPerHost,
ForwardingTimeouts: forwardingTimeout, ForwardingTimeouts: forwardingTimeout,
PeerCertURI: serversTransport.Spec.PeerCertURI,
} }
} }

View file

@ -104,7 +104,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
} }
} }
conf.Routers[normalized] = &dynamic.Router{ r := &dynamic.Router{
Middlewares: mds, Middlewares: mds,
Priority: route.Priority, Priority: route.Priority,
EntryPoints: ingressRoute.Spec.EntryPoints, EntryPoints: ingressRoute.Spec.EntryPoints,
@ -113,7 +113,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
} }
if ingressRoute.Spec.TLS != nil { if ingressRoute.Spec.TLS != nil {
tlsConf := &dynamic.RouterTLSConfig{ r.TLS = &dynamic.RouterTLSConfig{
CertResolver: ingressRoute.Spec.TLS.CertResolver, CertResolver: ingressRoute.Spec.TLS.CertResolver,
Domains: ingressRoute.Spec.TLS.Domains, Domains: ingressRoute.Spec.TLS.Domains,
} }
@ -129,14 +129,21 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
tlsOptionsName = makeID(ns, tlsOptionsName) tlsOptionsName = makeID(ns, tlsOptionsName)
} else if len(ns) > 0 { } else if len(ns) > 0 {
logger. logger.
WithField("TLSoptions", ingressRoute.Spec.TLS.Options.Name). WithField("TLSOption", ingressRoute.Spec.TLS.Options.Name).
Warnf("namespace %q is ignored in cross-provider context", ns) Warnf("Namespace %q is ignored in cross-provider context", ns)
} }
tlsConf.Options = tlsOptionsName if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRoute.Namespace, ns) {
logger.Errorf("TLSOption %s/%s is not in the IngressRoute namespace %s",
ns, ingressRoute.Spec.TLS.Options.Name, ingressRoute.Namespace)
continue
}
r.TLS.Options = tlsOptionsName
} }
conf.Routers[normalized].TLS = tlsConf
} }
conf.Routers[normalized] = r
} }
} }
@ -297,11 +304,34 @@ func (c configBuilder) buildServersLB(namespace string, svc v1alpha1.LoadBalance
lb.ResponseForwarding = conf.ResponseForwarding lb.ResponseForwarding = conf.ResponseForwarding
lb.Sticky = svc.Sticky lb.Sticky = svc.Sticky
lb.ServersTransport = svc.ServersTransport
lb.ServersTransport, err = c.makeServersTransportKey(namespace, svc.ServersTransport)
if err != nil {
return nil, err
}
return &dynamic.Service{LoadBalancer: lb}, nil return &dynamic.Service{LoadBalancer: lb}, nil
} }
func (c *configBuilder) makeServersTransportKey(parentNamespace string, serversTransportName string) (string, error) {
if serversTransportName == "" {
return "", nil
}
if !c.allowCrossNamespace && strings.HasSuffix(serversTransportName, providerNamespaceSeparator+providerName) {
// Since we are not able to know if another namespace is in the name (namespace-name@kubernetescrd),
// if the provider namespace kubernetescrd is used,
// we don't allow this format to avoid cross namespace references.
return "", fmt.Errorf("invalid reference to serversTransport %s: namespace-name@kubernetescrd format is not allowed when crossnamespace is disallowed", serversTransportName)
}
if strings.Contains(serversTransportName, providerNamespaceSeparator) {
return serversTransportName, nil
}
return provider.Normalize(makeID(parentNamespace, serversTransportName)), nil
}
func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) { func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) {
strategy := svc.Strategy strategy := svc.Strategy
if strategy == "" { if strategy == "" {

View file

@ -93,7 +93,7 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
conf.Services[serviceName].Weighted.Services = append(conf.Services[serviceName].Weighted.Services, srv) conf.Services[serviceName].Weighted.Services = append(conf.Services[serviceName].Weighted.Services, srv)
} }
conf.Routers[serviceName] = &dynamic.TCPRouter{ r := &dynamic.TCPRouter{
EntryPoints: ingressRouteTCP.Spec.EntryPoints, EntryPoints: ingressRouteTCP.Spec.EntryPoints,
Middlewares: mds, Middlewares: mds,
Rule: route.Match, Rule: route.Match,
@ -101,32 +101,38 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client
} }
if ingressRouteTCP.Spec.TLS != nil { if ingressRouteTCP.Spec.TLS != nil {
conf.Routers[serviceName].TLS = &dynamic.RouterTCPTLSConfig{ r.TLS = &dynamic.RouterTCPTLSConfig{
Passthrough: ingressRouteTCP.Spec.TLS.Passthrough, Passthrough: ingressRouteTCP.Spec.TLS.Passthrough,
CertResolver: ingressRouteTCP.Spec.TLS.CertResolver, CertResolver: ingressRouteTCP.Spec.TLS.CertResolver,
Domains: ingressRouteTCP.Spec.TLS.Domains, Domains: ingressRouteTCP.Spec.TLS.Domains,
} }
if ingressRouteTCP.Spec.TLS.Options == nil || len(ingressRouteTCP.Spec.TLS.Options.Name) == 0 { if ingressRouteTCP.Spec.TLS.Options != nil && len(ingressRouteTCP.Spec.TLS.Options.Name) > 0 {
continue tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name
} // Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name if !strings.Contains(tlsOptionsName, providerNamespaceSeparator) {
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference) if len(ns) == 0 {
ns := ingressRouteTCP.Spec.TLS.Options.Namespace ns = ingressRouteTCP.Namespace
if !strings.Contains(tlsOptionsName, "@") { }
if len(ns) == 0 { tlsOptionsName = makeID(ns, tlsOptionsName)
ns = ingressRouteTCP.Namespace } else if len(ns) > 0 {
logger.
WithField("TLSOption", ingressRouteTCP.Spec.TLS.Options.Name).
Warnf("Namespace %q is ignored in cross-provider context", ns)
} }
tlsOptionsName = makeID(ns, tlsOptionsName)
} else if len(ns) > 0 {
logger.
WithField("TLSoptions", ingressRouteTCP.Spec.TLS.Options.Name).
Warnf("namespace %q is ignored in cross-provider context", ns)
}
conf.Routers[serviceName].TLS.Options = tlsOptionsName if !isNamespaceAllowed(p.AllowCrossNamespace, ingressRouteTCP.Namespace, ns) {
logger.Errorf("TLSOption %s/%s is not in the IngressRouteTCP namespace %s",
ns, ingressRouteTCP.Spec.TLS.Options.Name, ingressRouteTCP.Namespace)
continue
}
r.TLS.Options = tlsOptionsName
}
} }
conf.Routers[serviceName] = r
} }
} }

View file

@ -1332,10 +1332,11 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
func TestLoadIngressRoutes(t *testing.T) { func TestLoadIngressRoutes(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
ingressClass string ingressClass string
paths []string paths []string
expected *dynamic.Configuration expected *dynamic.Configuration
AllowCrossNamespace bool
}{ }{
{ {
desc: "Empty", desc: "Empty",
@ -1402,8 +1403,9 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
{ {
desc: "Simple Ingress Route with middleware", desc: "Simple Ingress Route with middleware",
paths: []string{"services.yml", "with_middleware.yml"}, AllowCrossNamespace: true,
paths: []string{"services.yml", "with_middleware.yml"},
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{ UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{}, Routers: map[string]*dynamic.UDPRouter{},
@ -1457,8 +1459,9 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
{ {
desc: "Simple Ingress Route with middleware crossprovider", desc: "Simple Ingress Route with middleware crossprovider",
paths: []string{"services.yml", "with_middleware_crossprovider.yml"}, AllowCrossNamespace: true,
paths: []string{"services.yml", "with_middleware_crossprovider.yml"},
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{ UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{}, Routers: map[string]*dynamic.UDPRouter{},
@ -2026,8 +2029,9 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
{ {
desc: "services lb, servers lb, and mirror service, all in a wrr with different namespaces", desc: "services lb, servers lb, and mirror service, all in a wrr with different namespaces",
paths: []string{"with_namespaces.yml"}, AllowCrossNamespace: true,
paths: []string{"with_namespaces.yml"},
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{ UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{}, Routers: map[string]*dynamic.UDPRouter{},
@ -2730,8 +2734,9 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
{ {
desc: "TLS with tls options and specific namespace", desc: "TLS with tls options and specific namespace",
paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"},
AllowCrossNamespace: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{ UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{}, Routers: map[string]*dynamic.UDPRouter{},
@ -2924,8 +2929,9 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
{ {
desc: "TLS with unknown tls options namespace", desc: "TLS with unknown tls options namespace",
paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"},
AllowCrossNamespace: true,
expected: &dynamic.Configuration{ expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{ UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{}, Routers: map[string]*dynamic.UDPRouter{},
@ -3497,7 +3503,7 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
HTTP: &dynamic.HTTPConfiguration{ HTTP: &dynamic.HTTPConfiguration{
ServersTransports: map[string]*dynamic.ServersTransport{ ServersTransports: map[string]*dynamic.ServersTransport{
"test": { "foo-test": {
ServerName: "test", ServerName: "test",
InsecureSkipVerify: true, InsecureSkipVerify: true,
RootCAs: []tls.FileOrContent{"TESTROOTCAS0", "TESTROOTCAS1", "TESTROOTCAS2", "TESTROOTCAS3", "TESTROOTCAS5", "TESTALLCERTS"}, RootCAs: []tls.FileOrContent{"TESTROOTCAS0", "TESTROOTCAS1", "TESTROOTCAS2", "TESTROOTCAS3", "TESTROOTCAS5", "TESTALLCERTS"},
@ -3507,16 +3513,71 @@ func TestLoadIngressRoutes(t *testing.T) {
{CertFile: "TESTCERT3", KeyFile: "TESTKEY3"}, {CertFile: "TESTCERT3", KeyFile: "TESTKEY3"},
}, },
MaxIdleConnsPerHost: 42, MaxIdleConnsPerHost: 42,
DisableHTTP2: true,
ForwardingTimeouts: &dynamic.ForwardingTimeouts{ ForwardingTimeouts: &dynamic.ForwardingTimeouts{
DialTimeout: types.Duration(42 * time.Second), DialTimeout: types.Duration(42 * time.Second),
ResponseHeaderTimeout: types.Duration(42 * time.Second), ResponseHeaderTimeout: types.Duration(42 * time.Second),
IdleConnTimeout: types.Duration(42 * time.Millisecond), IdleConnTimeout: types.Duration(42 * time.Millisecond),
}, },
PeerCertURI: "foo://bar",
},
"default-test": {
ServerName: "test",
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
DialTimeout: types.Duration(30 * time.Second),
IdleConnTimeout: types.Duration(90 * time.Second),
},
},
},
Routers: map[string]*dynamic.Router{
"default-test-route-6f97418635c7e18853da": {
EntryPoints: []string{"foo"},
Service: "default-test-route-6f97418635c7e18853da",
Rule: "Host(`foo.com`)",
}, },
}, },
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{}, Services: map[string]*dynamic.Service{
"default-external-svc-with-https-443": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "https://external.domain:443",
},
},
PassHostHeader: Bool(true),
ServersTransport: "default-test",
},
},
"default-whoamitls-443": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "https://10.10.0.5:8443",
},
{
URL: "https://10.10.0.6:8443",
},
},
PassHostHeader: Bool(true),
ServersTransport: "default-default-test",
},
},
"default-test-route-6f97418635c7e18853da": {
Weighted: &dynamic.WeightedRoundRobin{
Services: []dynamic.WRRService{
{
Name: "default-external-svc-with-https-443",
Weight: Int(1),
},
{
Name: "default-whoamitls-443",
Weight: Int(1),
},
},
},
},
},
}, },
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
@ -3532,7 +3593,7 @@ func TestLoadIngressRoutes(t *testing.T) {
return return
} }
p := Provider{IngressClass: test.ingressClass, AllowCrossNamespace: true, AllowExternalNameServices: true} p := Provider{IngressClass: test.ingressClass, AllowCrossNamespace: test.AllowCrossNamespace, AllowExternalNameServices: true}
clientMock := newClientMock(test.paths...) clientMock := newClientMock(test.paths...)
conf := p.loadConfigurationFromCRD(context.Background(), clientMock) conf := p.loadConfigurationFromCRD(context.Background(), clientMock)
@ -4474,6 +4535,11 @@ func TestCrossNamespace(t *testing.T) {
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)", Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
Priority: 12, Priority: 12,
}, },
"default-cross-ns-route-1bc3efa892379bb93c6e": {
EntryPoints: []string{"foo"},
Service: "default-cross-ns-route-1bc3efa892379bb93c6e",
Rule: "Host(`bar.com`) && PathPrefix(`/foo`)",
},
}, },
Middlewares: map[string]*dynamic.Middleware{}, Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{ Services: map[string]*dynamic.Service{
@ -4503,6 +4569,20 @@ func TestCrossNamespace(t *testing.T) {
}, },
}, },
}, },
"default-cross-ns-route-1bc3efa892379bb93c6e": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: Bool(true),
ServersTransport: "foo-test@kubernetescrd",
},
},
"cross-ns-whoami-svc-80": { "cross-ns-whoami-svc-80": {
LoadBalancer: &dynamic.ServersLoadBalancer{ LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{ Servers: []dynamic.Server{
@ -4647,6 +4727,189 @@ func TestCrossNamespace(t *testing.T) {
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
}, },
{
desc: "HTTP ServersTransport cross namespace allowed",
paths: []string{"services.yml", "with_servers_transport_cross_namespace.yml"},
allowCrossNamespace: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-test-route-6b204d94623b3df4370c": {
EntryPoints: []string{"foo"},
Service: "default-test-route-6b204d94623b3df4370c",
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
Priority: 12,
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-test-route-6b204d94623b3df4370c": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: Bool(true),
ServersTransport: "cross-ns-st-cross-ns@kubernetescrd",
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{
"cross-ns-st-cross-ns": {
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
DialTimeout: 30000000000,
ResponseHeaderTimeout: 0,
IdleConnTimeout: 90000000000,
},
DisableHTTP2: true,
},
},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "HTTP ServersTransport cross namespace disallowed",
paths: []string{"services.yml", "with_servers_transport_cross_namespace.yml"},
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{
"cross-ns-st-cross-ns": {
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
DialTimeout: 30000000000,
ResponseHeaderTimeout: 0,
IdleConnTimeout: 90000000000,
},
DisableHTTP2: true,
},
},
},
TLS: &dynamic.TLSConfiguration{},
},
},
{
desc: "HTTP TLSOption cross namespace allowed",
paths: []string{"services.yml", "with_tls_options_cross_namespace.yml"},
allowCrossNamespace: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"default-test-route-6b204d94623b3df4370c": {
EntryPoints: []string{"foo"},
Service: "default-test-route-6b204d94623b3df4370c",
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
Priority: 12,
TLS: &dynamic.RouterTLSConfig{
Options: "cross-ns-tls-options-cn",
},
},
},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-test-route-6b204d94623b3df4370c": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: Bool(true),
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Options: map[string]tls.Options{
"cross-ns-tls-options-cn": {
MinVersion: "VersionTLS12",
ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"},
},
},
},
},
},
{
desc: "HTTP TLSOption cross namespace disallowed",
paths: []string{"services.yml", "with_tls_options_cross_namespace.yml"},
allowCrossNamespace: false,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{
"default-test-route-6b204d94623b3df4370c": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: "http://10.10.0.1:80",
},
{
URL: "http://10.10.0.2:80",
},
},
PassHostHeader: Bool(true),
},
},
},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TLS: &dynamic.TLSConfiguration{
Options: map[string]tls.Options{
"cross-ns-tls-options-cn": {
MinVersion: "VersionTLS12",
ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"},
},
},
},
},
},
{ {
desc: "TCP middleware cross namespace disallowed", desc: "TCP middleware cross namespace disallowed",
paths: []string{"tcp/services.yml", "tcp/with_middleware_with_cross_namespace.yml"}, paths: []string{"tcp/services.yml", "tcp/with_middleware_with_cross_namespace.yml"},
@ -4843,6 +5106,101 @@ func TestCrossNamespace(t *testing.T) {
TLS: &dynamic.TLSConfiguration{}, TLS: &dynamic.TLSConfiguration{},
}, },
}, },
{
desc: "TCP TLSOption cross namespace allowed",
paths: []string{"tcp/services.yml", "tcp/with_tls_options_cross_namespace.yml"},
allowCrossNamespace: true,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{
"default-test.route-fdd3e9338e47a45efefc": {
EntryPoints: []string{"foo"},
Service: "default-test.route-fdd3e9338e47a45efefc",
Rule: "HostSNI(`foo.com`)",
TLS: &dynamic.RouterTCPTLSConfig{
Options: "cross-ns-tls-options-cn",
},
},
},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{
"default-test.route-fdd3e9338e47a45efefc": {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: "10.10.0.1:8000",
},
{
Address: "10.10.0.2:8000",
},
},
},
},
},
},
TLS: &dynamic.TLSConfiguration{
Options: map[string]tls.Options{
"cross-ns-tls-options-cn": {
MinVersion: "VersionTLS12",
ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"},
},
},
},
},
},
{
desc: "TCP TLSOption cross namespace disallowed",
paths: []string{"tcp/services.yml", "tcp/with_tls_options_cross_namespace.yml"},
allowCrossNamespace: false,
expected: &dynamic.Configuration{
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{},
Services: map[string]*dynamic.UDPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{
"default-test.route-fdd3e9338e47a45efefc": {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: "10.10.0.1:8000",
},
{
Address: "10.10.0.2:8000",
},
},
},
},
},
},
TLS: &dynamic.TLSConfiguration{
Options: map[string]tls.Options{
"cross-ns-tls-options-cn": {
MinVersion: "VersionTLS12",
ALPNProtocols: []string{"h2", "http/1.1", "acme-tls/1"},
},
},
},
},
},
{ {
desc: "UDP cross namespace allowed", desc: "UDP cross namespace allowed",
paths: []string{"udp/services.yml", "udp/with_cross_namespace.yml"}, paths: []string{"udp/services.yml", "udp/with_cross_namespace.yml"},
@ -4949,6 +5307,8 @@ func TestCrossNamespace(t *testing.T) {
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.TLSStore: case *v1alpha1.TLSStore:
crdObjects = append(crdObjects, o) crdObjects = append(crdObjects, o)
case *v1alpha1.ServersTransport:
crdObjects = append(crdObjects, o)
default: default:
} }
} }

View file

@ -184,7 +184,7 @@ func (m *Manager) buildHTTPHandler(ctx context.Context, router *runtime.RouterIn
chain := alice.New() chain := alice.New()
if m.metricsRegistry != nil && m.metricsRegistry.IsRouterEnabled() { if m.metricsRegistry != nil && m.metricsRegistry.IsRouterEnabled() {
chain = chain.Append(metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, router.Service)) chain = chain.Append(metricsMiddle.WrapRouterHandler(ctx, m.metricsRegistry, routerName, provider.GetQualifiedName(ctx, router.Service)))
} }
return chain.Extend(*mHandler).Append(tHandler).Then(sHandler) return chain.Extend(*mHandler).Append(tHandler).Then(sHandler)

View file

@ -1,3 +1,4 @@
//go:build !windows
// +build !windows // +build !windows
package server package server

View file

@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file" OutputType = "file"
FileName = "traefik_changelog.md" FileName = "traefik_changelog.md"
# example new bugfix v2.5.2 # example new bugfix v2.5.3
CurrentRef = "v2.5" CurrentRef = "v2.5"
PreviousRef = "v2.5.1" PreviousRef = "v2.5.2"
BaseBranch = "v2.5" BaseBranch = "v2.5"
FutureCurrentRefName = "v2.5.2" FutureCurrentRefName = "v2.5.3"
ThresholdPreviousRef = 10 ThresholdPreviousRef = 10
ThresholdCurrentRef = 10 ThresholdCurrentRef = 10