Reserve priority range for internal routers
Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
parent
c31f5df854
commit
2bc3fa7b4b
6 changed files with 116 additions and 0 deletions
|
@ -560,3 +560,20 @@ To enable these ciphers, please set the option `CipherSuites` in your [TLS confi
|
||||||
> (https://go.dev/doc/go1.22#crypto/tls)
|
> (https://go.dev/doc/go1.22#crypto/tls)
|
||||||
|
|
||||||
To enable TLS 1.0, please set the option `MinVersion` to `VersionTLS10` in your [TLS configuration](https://doc.traefik.io/traefik/https/tls/#cipher-suites) or set the environment variable `GODEBUG=tls10server=1`.
|
To enable TLS 1.0, please set the option `MinVersion` to `VersionTLS10` in your [TLS configuration](https://doc.traefik.io/traefik/https/tls/#cipher-suites) or set the environment variable `GODEBUG=tls10server=1`.
|
||||||
|
|
||||||
|
## v2.11.1
|
||||||
|
|
||||||
|
### Maximum Router Priority Value
|
||||||
|
|
||||||
|
Before v2.11.1, the maximum user-defined router priority value is:
|
||||||
|
|
||||||
|
- `MaxInt32` for 32-bit platforms,
|
||||||
|
- `MaxInt64` for 64-bit platforms.
|
||||||
|
|
||||||
|
Please check out the [go documentation](https://pkg.go.dev/math#pkg-constants) for more information.
|
||||||
|
|
||||||
|
In v2.11.1, Traefik reserves a range of priorities for its internal routers and now,
|
||||||
|
the maximum user-defined router priority value is:
|
||||||
|
|
||||||
|
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||||
|
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||||
|
|
|
@ -293,6 +293,14 @@ To avoid path overlap, routes are sorted, by default, in descending order using
|
||||||
|
|
||||||
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
||||||
|
|
||||||
|
??? warning "Maximum Value"
|
||||||
|
|
||||||
|
Traefik reserves a range of priorities for its internal routers,
|
||||||
|
the maximum user-defined router priority value is:
|
||||||
|
|
||||||
|
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||||
|
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||||
|
|
||||||
??? info "How default priorities are computed"
|
??? info "How default priorities are computed"
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
|
@ -897,6 +905,14 @@ The priority is directly equal to the length of the rule, and so the longest len
|
||||||
|
|
||||||
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
A value of `0` for the priority is ignored: `priority = 0` means that the default rules length sorting is used.
|
||||||
|
|
||||||
|
??? warning "Maximum Value"
|
||||||
|
|
||||||
|
Traefik reserves a range of priorities for its internal routers,
|
||||||
|
the maximum user-defined router priority value is:
|
||||||
|
|
||||||
|
- `(MaxInt32 - 1000)` for 32-bit platforms,
|
||||||
|
- `(MaxInt64 - 1000)` for 64-bit platforms.
|
||||||
|
|
||||||
??? info "How default priorities are computed"
|
??? info "How default priorities are computed"
|
||||||
|
|
||||||
```yaml tab="File (YAML)"
|
```yaml tab="File (YAML)"
|
||||||
|
|
|
@ -4,7 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containous/alice"
|
"github.com/containous/alice"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
||||||
|
@ -21,6 +23,8 @@ import (
|
||||||
"github.com/traefik/traefik/v2/pkg/tls"
|
"github.com/traefik/traefik/v2/pkg/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxUserPriority = math.MaxInt - 1000
|
||||||
|
|
||||||
type middlewareBuilder interface {
|
type middlewareBuilder interface {
|
||||||
BuildChain(ctx context.Context, names []string) *alice.Chain
|
BuildChain(ctx context.Context, names []string) *alice.Chain
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
||||||
ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
ctxRouter := log.With(provider.AddInContext(ctx, routerName), log.Str(log.RouterName, routerName))
|
||||||
logger := log.FromContext(ctxRouter)
|
logger := log.FromContext(ctxRouter)
|
||||||
|
|
||||||
|
if routerConfig.Priority > maxUserPriority && !strings.HasSuffix(routerName, "@internal") {
|
||||||
|
err = fmt.Errorf("the router priority %d exceeds the max user-defined priority %d", routerConfig.Priority, maxUserPriority)
|
||||||
|
routerConfig.AddError(err, true)
|
||||||
|
logger.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig)
|
handler, err := m.buildRouterHandler(ctxRouter, routerName, routerConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
routerConfig.AddError(err, true)
|
routerConfig.AddError(err, true)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package router
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -698,6 +699,32 @@ func TestRuntimeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectedError: 2,
|
expectedError: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Router priority exceeding max user-defined priority",
|
||||||
|
serviceConfig: map[string]*dynamic.Service{
|
||||||
|
"foo-service": {
|
||||||
|
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||||
|
Servers: []dynamic.Server{
|
||||||
|
{
|
||||||
|
URL: "http://127.0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
middlewareConfig: map[string]*dynamic.Middleware{},
|
||||||
|
routerConfig: map[string]*dynamic.Router{
|
||||||
|
"bar": {
|
||||||
|
EntryPoints: []string{"web"},
|
||||||
|
Service: "foo-service",
|
||||||
|
Rule: "Host(`foo.bar`)",
|
||||||
|
Priority: math.MaxInt,
|
||||||
|
TLS: &dynamic.RouterTLSConfig{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tlsOptions: map[string]tls.Options{},
|
||||||
|
expectedError: 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Router with broken tlsOption",
|
desc: "Router with broken tlsOption",
|
||||||
serviceConfig: map[string]*dynamic.Service{
|
serviceConfig: map[string]*dynamic.Service{
|
||||||
|
|
|
@ -5,7 +5,9 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
||||||
"github.com/traefik/traefik/v2/pkg/log"
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
|
@ -18,6 +20,8 @@ import (
|
||||||
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxUserPriority = math.MaxInt - 1000
|
||||||
|
|
||||||
type middlewareBuilder interface {
|
type middlewareBuilder interface {
|
||||||
BuildChain(ctx context.Context, names []string) *tcp.Chain
|
BuildChain(ctx context.Context, names []string) *tcp.Chain
|
||||||
}
|
}
|
||||||
|
@ -291,6 +295,13 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if routerConfig.Priority > maxUserPriority && !strings.HasSuffix(routerName, "@internal") {
|
||||||
|
routerErr := fmt.Errorf("the router priority %d exceeds the max user-defined priority %d", routerConfig.Priority, maxUserPriority)
|
||||||
|
routerConfig.AddError(routerErr, true)
|
||||||
|
logger.Error(routerErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var handler tcp.Handler
|
var handler tcp.Handler
|
||||||
if routerConfig.TLS == nil || routerConfig.TLS.Passthrough {
|
if routerConfig.TLS == nil || routerConfig.TLS.Passthrough {
|
||||||
handler, err = m.buildTCPHandler(ctxRouter, routerConfig)
|
handler, err = m.buildTCPHandler(ctxRouter, routerConfig)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package tcp
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -270,6 +271,39 @@ func TestRuntimeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectedError: 2,
|
expectedError: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Router with priority exceeding the max user-defined priority",
|
||||||
|
tcpServiceConfig: map[string]*runtime.TCPServiceInfo{
|
||||||
|
"foo-service": {
|
||||||
|
TCPService: &dynamic.TCPService{
|
||||||
|
LoadBalancer: &dynamic.TCPServersLoadBalancer{
|
||||||
|
Servers: []dynamic.TCPServer{
|
||||||
|
{
|
||||||
|
Port: "8085",
|
||||||
|
Address: "127.0.0.1:8085",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Address: "127.0.0.1:8086",
|
||||||
|
Port: "8086",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tcpRouterConfig: map[string]*runtime.TCPRouterInfo{
|
||||||
|
"bar": {
|
||||||
|
TCPRouter: &dynamic.TCPRouter{
|
||||||
|
EntryPoints: []string{"web"},
|
||||||
|
Service: "foo-service",
|
||||||
|
Rule: "HostSNI(`foo.bar`)",
|
||||||
|
TLS: &dynamic.RouterTCPTLSConfig{},
|
||||||
|
Priority: math.MaxInt,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedError: 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Router with HostSNI but no TLS",
|
desc: "Router with HostSNI but no TLS",
|
||||||
tcpServiceConfig: map[string]*runtime.TCPServiceInfo{
|
tcpServiceConfig: map[string]*runtime.TCPServiceInfo{
|
||||||
|
|
Loading…
Reference in a new issue