Merge branch v3.6 into v3.7

This commit is contained in:
romain
2026-06-04 14:06:26 +02:00
9 changed files with 192 additions and 15 deletions
+18 -6
View File
@@ -31,10 +31,11 @@
- **[k8s/ingress-nginx]** Add nginx.ingress.kubernetes.io/enable-global-auth to the list of supported annotations ([#13219](https://github.com/traefik/traefik/pull/13219) @filip2mac) - **[k8s/ingress-nginx]** Add nginx.ingress.kubernetes.io/enable-global-auth to the list of supported annotations ([#13219](https://github.com/traefik/traefik/pull/13219) @filip2mac)
- **[k8s/ingress-nginx]** Capitalize NGINX in kubernetesIngressNGINX ([#13236](https://github.com/traefik/traefik/pull/13236) @smellems) - **[k8s/ingress-nginx]** Capitalize NGINX in kubernetesIngressNGINX ([#13236](https://github.com/traefik/traefik/pull/13236) @smellems)
## [v3.6.18](https://github.com/traefik/traefik/tree/v3.6.18) (2026-06-03) ## [v3.6.19](https://github.com/traefik/traefik/tree/v3.6.19) (2026-06-04)
[All Commits](https://github.com/traefik/traefik/compare/v3.6.17...v3.6.18) [All Commits](https://github.com/traefik/traefik/compare/v3.6.17...v3.6.19)
**Bug fixes:** **Bug fixes:**
- **[tls]** Compute resolved tlsOptions after applying models ([#13291](https://github.com/traefik/traefik/pull/13291) @rtribotte)
- **[accesslogs]** Escape double quotes in quoted log fields ([#13180](https://github.com/traefik/traefik/pull/13180) @KaanSimsek) - **[accesslogs]** Escape double quotes in quoted log fields ([#13180](https://github.com/traefik/traefik/pull/13180) @KaanSimsek)
- **[k8s/gatewayapi]** Escape exact gRPC method matches ([#13201](https://github.com/traefik/traefik/pull/13201) @nickmnt) - **[k8s/gatewayapi]** Escape exact gRPC method matches ([#13201](https://github.com/traefik/traefik/pull/13201) @nickmnt)
- **[logs, middleware]** Allow query parameters to be dropped from RequestPath in access log ([#13091](https://github.com/traefik/traefik/pull/13091) @calinelson) - **[logs, middleware]** Allow query parameters to be dropped from RequestPath in access log ([#13091](https://github.com/traefik/traefik/pull/13091) @calinelson)
@@ -51,17 +52,18 @@
**Documentation:** **Documentation:**
- **[file]** Replace generated File routing reference page ([#13170](https://github.com/traefik/traefik/pull/13170) @sheddy-traefik) - **[file]** Replace generated File routing reference page ([#13170](https://github.com/traefik/traefik/pull/13170) @sheddy-traefik)
- **[middleware]** Remove whitespace in HTML tag ([#13160](https://github.com/traefik/traefik/pull/13160) @marbon87)
- **[k8s/crd]** Fix typo in accesslogs field name ([#13177](https://github.com/traefik/traefik/pull/13177) @PlayMTL) - **[k8s/crd]** Fix typo in accesslogs field name ([#13177](https://github.com/traefik/traefik/pull/13177) @PlayMTL)
- **[k8s/ingress-nginx]** Surface the Ingress status race condition during NGINX coexistence ([#13205](https://github.com/traefik/traefik/pull/13205) @emilevauge) - **[k8s/ingress-nginx]** Surface the Ingress status race condition during NGINX coexistence ([#13205](https://github.com/traefik/traefik/pull/13205) @emilevauge)
- **[k8s/ingress-nginx]** Capitalize NGINX in kubernetesIngressNGINX ([#13236](https://github.com/traefik/traefik/pull/13236) @smellems)
- Polish grammar in migration guides ([#13174](https://github.com/traefik/traefik/pull/13174) @quyentonndbs) - Polish grammar in migration guides ([#13174](https://github.com/traefik/traefik/pull/13174) @quyentonndbs)
- **[middleware]** Remove whitespace in HTML tag ([#13160](https://github.com/traefik/traefik/pull/13160) @marbon87)
- Add @LBF38 as a current maintainer ([#13225](https://github.com/traefik/traefik/pull/13225) @emilevauge) - Add @LBF38 as a current maintainer ([#13225](https://github.com/traefik/traefik/pull/13225) @emilevauge)
- **[k8s/ingress-nginx]** Capitalize NGINX in kubernetesIngressNGINX ([#13236](https://github.com/traefik/traefik/pull/13236) @smellems)
## [v2.11.47](https://github.com/traefik/traefik/tree/v2.11.47) (2026-06-03) ## [v2.11.48](https://github.com/traefik/traefik/tree/v2.11.48) (2026-06-04)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.46...v2.11.47) [All Commits](https://github.com/traefik/traefik/compare/v2.11.46...v2.11.48)
**Bug fixes:** **Bug fixes:**
- **[tls]** Compute resolved tlsOptions after applying models ([#13291](https://github.com/traefik/traefik/pull/13291) @rtribotte)
- **[middleware, authentication]** Add error on basic auth build if users is empty ([#13195](https://github.com/traefik/traefik/pull/13195) @rtribotte) - **[middleware, authentication]** Add error on basic auth build if users is empty ([#13195](https://github.com/traefik/traefik/pull/13195) @rtribotte)
- **[k8s/ingress]** Avoid ingress path matcher injection and backport 11d251415 ([#13227](https://github.com/traefik/traefik/pull/13227) @rtribotte) - **[k8s/ingress]** Avoid ingress path matcher injection and backport 11d251415 ([#13227](https://github.com/traefik/traefik/pull/13227) @rtribotte)
- **[server]** Move snicheck to ctx instead of simulated routing ([#13214](https://github.com/traefik/traefik/pull/13214) @juliens) - **[server]** Move snicheck to ctx instead of simulated routing ([#13214](https://github.com/traefik/traefik/pull/13214) @juliens)
@@ -69,6 +71,16 @@
- **[server]** Bump golang.org/x/net to v0.55.0 ([#13251](https://github.com/traefik/traefik/pull/13251) @kevinpollet) - **[server]** Bump golang.org/x/net to v0.55.0 ([#13251](https://github.com/traefik/traefik/pull/13251) @kevinpollet)
- **[server]** Bump golang.org/x/crypto to v0.52.0 ([#13276](https://github.com/traefik/traefik/pull/13276) @rtribotte) - **[server]** Bump golang.org/x/crypto to v0.52.0 ([#13276](https://github.com/traefik/traefik/pull/13276) @rtribotte)
## [v3.6.18](https://github.com/traefik/traefik/tree/v3.6.18) (2026-06-03)
[All Commits](https://github.com/traefik/traefik/compare/v3.6.17...v3.6.18)
Release canceled.
## [v2.11.47](https://github.com/traefik/traefik/tree/v2.11.47) (2026-06-03)
[All Commits](https://github.com/traefik/traefik/compare/v2.11.46...v2.11.47)
Release canceled.
## [v3.7.1](https://github.com/traefik/traefik/tree/v3.7.1) (2026-05-11) ## [v3.7.1](https://github.com/traefik/traefik/tree/v3.7.1) (2026-05-11)
[All Commits](https://github.com/traefik/traefik/compare/v3.7.0...v3.7.1) [All Commits](https://github.com/traefik/traefik/compare/v3.7.0...v3.7.1)
+4 -4
View File
@@ -144,11 +144,11 @@ Note: TLSOptions for `HostRegexp` matchers remains unsupported. Use wildcard `Ho
--- ---
## v3.6.18 ## v3.6.19
### Kubernetes Gateway API Provider ### Kubernetes Gateway API Provider
Starting with `v3.6.18`, the QPS and Burst values of the Kubernetes client used by the Kubernetes Gateway API provider have been increased to `50` and `100` respectively (10x the default values of the Kubernetes client). Starting with `v3.6.19`, the QPS and Burst values of the Kubernetes client used by the Kubernetes Gateway API provider have been increased to `50` and `100` respectively (10x the default values of the Kubernetes client).
The Kubernetes Gateway API provider writes status updates intensively to comply with the Kubernetes Gateway API specification. The Kubernetes Gateway API provider writes status updates intensively to comply with the Kubernetes Gateway API specification.
This change helps avoid performance issues related to Kubernetes API rate limiting, which can increase the setup time when a new routing configuration is built. This change helps avoid performance issues related to Kubernetes API rate limiting, which can increase the setup time when a new routing configuration is built.
@@ -158,13 +158,13 @@ and [`kubernetesGateway.burst`](../reference/install-configuration/providers/kub
### BasicAuth Middleware ### BasicAuth Middleware
From version `v3.6.18` onwards, the BasicAuth middleware requires a non-empty users configuration in order to be built successfully. From version `v3.6.19` onwards, the BasicAuth middleware requires a non-empty users configuration in order to be built successfully.
Previously, the middleware would be built successfully but always return a 401 status code for any request. Previously, the middleware would be built successfully but always return a 401 status code for any request.
Now, an error occurs and any routers using it will be unmounted. For the same request, a 404 status code is served instead of a 401 status code. Now, an error occurs and any routers using it will be unmounted. For the same request, a 404 status code is served instead of a 401 status code.
### StripPrefix and StripPrefixRegex Middleware ### StripPrefix and StripPrefixRegex Middleware
From version `v3.6.18` onwards, the StripPrefix middleware and the StripPrefixRegex middleware reject requests (`400 Bad Request`) From version `v3.6.19` onwards, the StripPrefix middleware and the StripPrefixRegex middleware reject requests (`400 Bad Request`)
when stripping the configured prefix produces a path that differs from its normalised form when stripping the configured prefix produces a path that differs from its normalised form
(i.e. a path containing `.` or `..` segments that would be collapsed by normalisation). (i.e. a path containing `.` or `..` segments that would be collapsed by normalisation).
+1 -1
View File
@@ -22,7 +22,7 @@ require (
github.com/docker/cli v29.4.0+incompatible github.com/docker/cli v29.4.0+incompatible
github.com/docker/go-connections v0.6.0 github.com/docker/go-connections v0.6.0
github.com/fatih/structs v1.1.0 github.com/fatih/structs v1.1.0
github.com/fsnotify/fsnotify v1.9.0 github.com/fsnotify/fsnotify v1.10.1
github.com/go-acme/lego/v4 v4.35.2 github.com/go-acme/lego/v4 v4.35.2
github.com/go-kit/kit v0.13.0 github.com/go-kit/kit v0.13.0
github.com/go-kit/log v0.2.1 github.com/go-kit/log v0.2.1
+2 -2
View File
@@ -1004,8 +1004,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
@@ -0,0 +1,53 @@
[global]
checkNewVersion = false
sendAnonymousUsage = false
[log]
level = "DEBUG"
[entryPoints]
[entryPoints.websecure]
address = ":4443"
[entryPoints.websecure.http.tls]
[entryPoints.websecure-options]
address = ":4444"
[entryPoints.websecure-options.http.tls]
options = "foo"
[api]
insecure = true
[providers.file]
filename = "{{ .SelfFilename }}"
## dynamic configuration ##
[http.routers]
[http.routers.router1]
entryPoints = ["websecure"]
service = "service1"
rule = "Host(`snitest.com`)"
[http.routers.router2]
entryPoints = ["websecure-options"]
service = "service1"
rule = "Host(`snitest.org`)"
[http.services]
[http.services.service1]
[http.services.service1.loadBalancer]
[[http.services.service1.loadBalancer.servers]]
url = "http://127.0.0.1:9010"
[[tls.certificates]]
certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key"
[[tls.certificates]]
certFile = "fixtures/https/snitest.org.cert"
keyFile = "fixtures/https/snitest.org.key"
[tls.options]
[tls.options.foo]
maxVersion = "VersionTLS12"
+63 -1
View File
@@ -150,7 +150,69 @@ func (s *HTTPSSuite) TestWithSNIConfigRoute() {
require.NoError(s.T(), err) require.NoError(s.T(), err)
} }
// TestWithTLSOptions verifies that traefik routes the requests with the associated tls options. // TestWithEntryPointTLSConfig verifies that a router relying on the entry point
// TLS configuration (without an explicit router TLS section) is served over HTTPS,
// including when the entry point references user-defined TLS options.
// Regression test for https://github.com/traefik/traefik/issues/13289.
func (s *HTTPSSuite) TestWithEntryPointTLSConfig() {
file := s.adaptFile("fixtures/https/https_entrypoint_tls.toml", struct{}{})
s.traefikCmd(withConfigFile(file))
// wait for Traefik
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("Host(`snitest.com`)"))
require.NoError(s.T(), err)
backend := startTestServer("9010", http.StatusNoContent, "")
defer backend.Close()
err = try.GetRequest(backend.URL, 1*time.Second, try.StatusCodeIs(http.StatusNoContent))
require.NoError(s.T(), err)
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: "snitest.com",
},
}
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
require.NoError(s.T(), err)
req.Host = tr.TLSClientConfig.ServerName
req.Header.Set("Host", tr.TLSClientConfig.ServerName)
req.Header.Set("Accept", "*/*")
err = try.RequestWithTransport(req, 30*time.Second, tr, try.HasCn(tr.TLSClientConfig.ServerName), try.StatusCodeIs(http.StatusNoContent))
require.NoError(s.T(), err)
// The websecure-options entry point references the user-defined "foo" TLS options (maxVersion VersionTLS12).
// A request with no router-level TLS must still have these options resolved and applied.
trOptions := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: "snitest.org",
},
}
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:4444/", nil)
require.NoError(s.T(), err)
req.Host = trOptions.TLSClientConfig.ServerName
req.Header.Set("Host", trOptions.TLSClientConfig.ServerName)
req.Header.Set("Accept", "*/*")
err = try.RequestWithTransport(req, 30*time.Second, trOptions, try.HasCn(trOptions.TLSClientConfig.ServerName), try.StatusCodeIs(http.StatusNoContent))
require.NoError(s.T(), err)
// A TLS 1.3-only client must fail the handshake, proving the "foo" options
// (resolved from the entry point) are effectively enforced.
_, err = tls.Dial("tcp", "127.0.0.1:4444", &tls.Config{
InsecureSkipVerify: true,
ServerName: "snitest.org",
MinVersion: tls.VersionTLS13,
})
assert.Error(s.T(), err)
}
// TestWithTLSOptions verifies that traefik routes the requests with the associated tls options.
func (s *HTTPSSuite) TestWithTLSOptions() { func (s *HTTPSSuite) TestWithTLSOptions() {
file := s.adaptFile("fixtures/https/https_tls_options.toml", struct{}{}) file := s.adaptFile("fixtures/https/https_tls_options.toml", struct{}{})
s.traefikCmd(withConfigFile(file)) s.traefikCmd(withConfigFile(file))
+1 -1
View File
@@ -170,7 +170,7 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint
delete(conf.TLS.Options, traefiktls.DefaultTLSConfigName) delete(conf.TLS.Options, traefiktls.DefaultTLSConfigName)
} }
return resolveHTTPTLSOptions(conf) return conf
} }
func resolveHTTPTLSOptions(cfg dynamic.Configuration) dynamic.Configuration { func resolveHTTPTLSOptions(cfg dynamic.Configuration) dynamic.Configuration {
+1
View File
@@ -176,6 +176,7 @@ func (c *ConfigurationWatcher) applyConfigurations(ctx context.Context) {
conf := mergeConfiguration(newConfigs.DeepCopy(), c.defaultEntryPoints) conf := mergeConfiguration(newConfigs.DeepCopy(), c.defaultEntryPoints)
conf = applyModel(conf) conf = applyModel(conf)
conf = resolveHTTPTLSOptions(conf)
for _, listener := range c.configurationListeners { for _, listener := range c.configurationListeners {
listener(conf) listener(conf)
+49
View File
@@ -992,3 +992,52 @@ func TestConfigurationWatcher_MultipleTransformers(t *testing.T) {
assert.Equal(t, 1, callCount1) assert.Equal(t, 1, callCount1)
assert.Equal(t, 1, callCount2) assert.Equal(t, 1, callCount2)
} }
// TestEntryPointTLSResolvedOptions is a regression test for
// https://github.com/traefik/traefik/issues/13289: a router whose TLS
// configuration comes from the entry point (and not from an explicit router TLS
// section) must still have its TLS options resolved in the published configuration.
func TestEntryPointTLSResolvedOptions(t *testing.T) {
routinesPool := safe.NewPool(t.Context())
t.Cleanup(routinesPool.Stop)
pvd := &mockProvider{
messages: []dynamic.Message{{
ProviderName: "internal",
Configuration: &dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"foo": {
EntryPoints: []string{"websecure"},
Rule: "Host(`foo.example.com`)",
Service: "service",
},
},
Models: map[string]*dynamic.Model{
"websecure": {
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
}},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, []string{}, "")
run := make(chan struct{})
watcher.AddListener(func(conf dynamic.Configuration) {
router := conf.HTTP.Routers["foo@internal"]
if router == nil || router.TLS == nil {
return
}
assert.Equal(t, "default", router.TLS.ResolvedOptions)
close(run)
})
watcher.Start()
t.Cleanup(watcher.Stop)
<-run
}