Merge current v2.5 into master
This commit is contained in:
commit
380514941c
35 changed files with 773 additions and 161 deletions
2
.github/workflows/validate.yaml
vendored
2
.github/workflows/validate.yaml
vendored
|
@ -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: ""
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,21 +346,21 @@ 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. |
|
||||||
|
@ -370,15 +370,16 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||||
| [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.
|
||||||
|
|
|
@ -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
2
go.mod
|
@ -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
4
go.sum
|
@ -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=
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package integration
|
package integration
|
||||||
|
|
|
@ -333,6 +333,8 @@ 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)
|
||||||
|
|
||||||
|
// adding a loop to test if metrics are not deleted
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil)
|
request, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:8080/metrics", nil)
|
||||||
c.Assert(err, checker.IsNil)
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
@ -344,11 +346,12 @@ func (s *SimpleSuite) TestMetricsPrometheusTwoRoutersOneService(c *check.C) {
|
||||||
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) {
|
||||||
s.createComposeProject(c, "base")
|
s.createComposeProject(c, "base")
|
||||||
|
|
2
integration/testdata/rawdata-crd.json
vendored
2
integration/testdata/rawdata-crd.json
vendored
|
@ -180,7 +180,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"passHostHeader": true,
|
"passHostHeader": true,
|
||||||
"serversTransport": "mytransport@kubernetescrd"
|
"serversTransport": "default-mytransport@kubernetescrd"
|
||||||
},
|
},
|
||||||
"status": "enabled",
|
"status": "enabled",
|
||||||
"usedBy": [
|
"usedBy": [
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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(),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package acme
|
package acme
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -27,6 +27,14 @@ spec:
|
||||||
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
|
||||||
kind: TraefikService
|
kind: TraefikService
|
||||||
|
@ -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"
|
||||||
|
|
|
@ -93,6 +93,8 @@ 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
|
||||||
|
@ -108,3 +110,36 @@ spec:
|
||||||
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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,15 +129,22 @@ 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
|
||||||
}
|
}
|
||||||
conf.Routers[normalized].TLS = tlsConf
|
|
||||||
|
r.TLS.Options = tlsOptionsName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conf.Routers[normalized] = r
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return conf
|
return conf
|
||||||
|
@ -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 == "" {
|
||||||
|
|
|
@ -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
|
tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name
|
||||||
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
|
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
|
||||||
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
|
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
|
||||||
if !strings.Contains(tlsOptionsName, "@") {
|
if !strings.Contains(tlsOptionsName, providerNamespaceSeparator) {
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = ingressRouteTCP.Namespace
|
ns = ingressRouteTCP.Namespace
|
||||||
}
|
}
|
||||||
tlsOptionsName = makeID(ns, tlsOptionsName)
|
tlsOptionsName = makeID(ns, tlsOptionsName)
|
||||||
} else if len(ns) > 0 {
|
} else if len(ns) > 0 {
|
||||||
logger.
|
logger.
|
||||||
WithField("TLSoptions", ingressRouteTCP.Spec.TLS.Options.Name).
|
WithField("TLSOption", ingressRouteTCP.Spec.TLS.Options.Name).
|
||||||
Warnf("namespace %q is ignored in cross-provider context", ns)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1336,6 +1336,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
ingressClass string
|
ingressClass string
|
||||||
paths []string
|
paths []string
|
||||||
expected *dynamic.Configuration
|
expected *dynamic.Configuration
|
||||||
|
AllowCrossNamespace bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "Empty",
|
desc: "Empty",
|
||||||
|
@ -1403,6 +1404,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Simple Ingress Route with middleware",
|
desc: "Simple Ingress Route with middleware",
|
||||||
|
AllowCrossNamespace: true,
|
||||||
paths: []string{"services.yml", "with_middleware.yml"},
|
paths: []string{"services.yml", "with_middleware.yml"},
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
UDP: &dynamic.UDPConfiguration{
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
@ -1458,6 +1460,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Simple Ingress Route with middleware crossprovider",
|
desc: "Simple Ingress Route with middleware crossprovider",
|
||||||
|
AllowCrossNamespace: true,
|
||||||
paths: []string{"services.yml", "with_middleware_crossprovider.yml"},
|
paths: []string{"services.yml", "with_middleware_crossprovider.yml"},
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
UDP: &dynamic.UDPConfiguration{
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
@ -2027,6 +2030,7 @@ 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",
|
||||||
|
AllowCrossNamespace: true,
|
||||||
paths: []string{"with_namespaces.yml"},
|
paths: []string{"with_namespaces.yml"},
|
||||||
expected: &dynamic.Configuration{
|
expected: &dynamic.Configuration{
|
||||||
UDP: &dynamic.UDPConfiguration{
|
UDP: &dynamic.UDPConfiguration{
|
||||||
|
@ -2732,6 +2736,7 @@ 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{},
|
||||||
|
@ -2926,6 +2931,7 @@ 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:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package server
|
package server
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue