Reserve priority range for internal routers

Co-authored-by: Romain <rtribotte@users.noreply.github.com>
This commit is contained in:
Baptiste Mayelle 2024-04-02 17:04:05 +02:00 committed by GitHub
parent c31f5df854
commit 2bc3fa7b4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 116 additions and 0 deletions

View file

@ -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)
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.

View file

@ -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.
??? 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"
```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.
??? 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"
```yaml tab="File (YAML)"

View file

@ -4,7 +4,9 @@ import (
"context"
"errors"
"fmt"
"math"
"net/http"
"strings"
"github.com/containous/alice"
"github.com/traefik/traefik/v2/pkg/config/runtime"
@ -21,6 +23,8 @@ import (
"github.com/traefik/traefik/v2/pkg/tls"
)
const maxUserPriority = math.MaxInt - 1000
type middlewareBuilder interface {
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))
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)
if err != nil {
routerConfig.AddError(err, true)

View file

@ -3,6 +3,7 @@ package router
import (
"context"
"io"
"math"
"net/http"
"net/http/httptest"
"strings"
@ -698,6 +699,32 @@ func TestRuntimeConfiguration(t *testing.T) {
},
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",
serviceConfig: map[string]*dynamic.Service{

View file

@ -5,7 +5,9 @@ import (
"crypto/tls"
"errors"
"fmt"
"math"
"net/http"
"strings"
"github.com/traefik/traefik/v2/pkg/config/runtime"
"github.com/traefik/traefik/v2/pkg/log"
@ -18,6 +20,8 @@ import (
traefiktls "github.com/traefik/traefik/v2/pkg/tls"
)
const maxUserPriority = math.MaxInt - 1000
type middlewareBuilder interface {
BuildChain(ctx context.Context, names []string) *tcp.Chain
}
@ -291,6 +295,13 @@ func (m *Manager) addTCPHandlers(ctx context.Context, configs map[string]*runtim
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
if routerConfig.TLS == nil || routerConfig.TLS.Passthrough {
handler, err = m.buildTCPHandler(ctxRouter, routerConfig)

View file

@ -3,6 +3,7 @@ package tcp
import (
"context"
"crypto/tls"
"math"
"net/http"
"net/http/httptest"
"testing"
@ -270,6 +271,39 @@ func TestRuntimeConfiguration(t *testing.T) {
},
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",
tcpServiceConfig: map[string]*runtime.TCPServiceInfo{