1
0
Fork 0

Print access logs for rejected requests and warn about new behavior

This commit is contained in:
Romain 2025-12-16 16:20:05 +01:00 committed by GitHub
parent e0e49533ab
commit 60b19b7b81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 371 additions and 147 deletions

View file

@ -13,6 +13,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/config/runtime"
"github.com/traefik/traefik/v2/pkg/config/static"
"github.com/traefik/traefik/v2/pkg/metrics"
"github.com/traefik/traefik/v2/pkg/middlewares/accesslog"
"github.com/traefik/traefik/v2/pkg/middlewares/capture"
@ -319,7 +320,7 @@ func TestRouterManager_Get(t *testing.T) {
chainBuilder := middleware.NewChainBuilder(nil, nil, nil)
tlsManager := tls.NewManager()
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, nil)
handlers := routerManager.BuildHandlers(t.Context(), test.entryPoints, false)
@ -426,7 +427,7 @@ func TestAccessLog(t *testing.T) {
chainBuilder := middleware.NewChainBuilder(nil, nil, nil)
tlsManager := tls.NewManager()
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, nil)
handlers := routerManager.BuildHandlers(t.Context(), test.entryPoints, false)
@ -814,7 +815,7 @@ func TestRuntimeConfiguration(t *testing.T) {
tlsManager := tls.NewManager()
tlsManager.UpdateConfigs(t.Context(), nil, test.tlsOptions, nil)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, nil)
_ = routerManager.BuildHandlers(t.Context(), entryPoints, false)
_ = routerManager.BuildHandlers(t.Context(), entryPoints, true)
@ -891,7 +892,7 @@ func TestProviderOnMiddlewares(t *testing.T) {
chainBuilder := middleware.NewChainBuilder(nil, nil, nil)
tlsManager := tls.NewManager()
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, nil)
_ = routerManager.BuildHandlers(t.Context(), entryPoints, false)
@ -901,6 +902,124 @@ func TestProviderOnMiddlewares(t *testing.T) {
assert.Equal(t, []string{"m1@docker", "m2@docker", "m1@file"}, rtConf.Middlewares["chain@docker"].Chain.Middlewares)
}
func TestManager_BuildHandlers_Deny(t *testing.T) {
testCases := []struct {
desc string
routers map[string]*dynamic.Router
services map[string]*dynamic.Service
requestPath string
encodedCharacters static.EncodedCharacters
expectedStatusCode int
}{
{
desc: "unallowed request with encoded slash",
requestPath: "/foo%2F",
routers: map[string]*dynamic.Router{
"parent": {
EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)",
Service: "service",
},
},
services: map[string]*dynamic.Service{
"service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{{URL: "http://localhost:8080"}},
},
},
},
expectedStatusCode: http.StatusBadRequest,
},
{
desc: "allowed request with encoded slash",
requestPath: "/foo%2F",
routers: map[string]*dynamic.Router{
"parent": {
EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)",
Service: "service",
},
},
services: map[string]*dynamic.Service{
"service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{{URL: "http://localhost:8080"}},
},
},
},
encodedCharacters: static.EncodedCharacters{
AllowEncodedSlash: true,
},
expectedStatusCode: http.StatusBadGateway,
},
{
desc: "unallowed request with fragment",
requestPath: "/foo#",
routers: map[string]*dynamic.Router{
"parent": {
EntryPoints: []string{"web"},
Rule: "PathPrefix(`/`)",
Service: "service",
},
},
services: map[string]*dynamic.Service{
"service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{{URL: "http://localhost:8080"}},
},
},
},
expectedStatusCode: http.StatusBadRequest,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
// Create runtime routers
runtimeRouters := make(map[string]*runtime.RouterInfo)
for name, router := range test.routers {
runtimeRouters[name] = &runtime.RouterInfo{
Router: router,
}
}
// Create runtime services
runtimeServices := make(map[string]*runtime.ServiceInfo)
for name, service := range test.services {
runtimeServices[name] = &runtime.ServiceInfo{
Service: service,
}
}
conf := &runtime.Configuration{
Routers: runtimeRouters,
Services: runtimeServices,
}
deniedEncodedPathCharacters := map[string]map[string]struct{}{"web": test.encodedCharacters.Map()}
roundTripperManager := service.NewRoundTripperManager()
roundTripperManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
serviceManager := service.NewManager(conf.Services, nil, nil, roundTripperManager)
middlewaresBuilder := middleware.NewBuilder(conf.Middlewares, serviceManager, nil)
chainBuilder := middleware.NewChainBuilder(nil, nil, nil)
tlsManager := tls.NewManager()
routerManager := NewManager(conf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, deniedEncodedPathCharacters)
// Build handlers
ctx := t.Context()
handlers := routerManager.BuildHandlers(ctx, []string{"web"}, false)
recorder := httptest.NewRecorder()
request := httptest.NewRequest(http.MethodGet, test.requestPath, http.NoBody)
handlers["web"].ServeHTTP(recorder, request)
assert.Equal(t, test.expectedStatusCode, recorder.Code)
})
}
}
type staticRoundTripperGetter struct {
res *http.Response
}
@ -960,7 +1079,7 @@ func BenchmarkRouterServe(b *testing.B) {
chainBuilder := middleware.NewChainBuilder(nil, nil, nil)
tlsManager := tls.NewManager()
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, chainBuilder, metrics.NewVoidRegistry(), tlsManager, nil)
handlers := routerManager.BuildHandlers(b.Context(), entryPoints, false)