Merge branch v2.11 into v3.6

This commit is contained in:
romain 2026-06-04 11:00:28 +02:00
commit 4c71ee3d18
6 changed files with 179 additions and 9 deletions

View file

@ -1,3 +1,15 @@
## [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.48)
**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)
- **[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)
- **[middleware]** Reject requests with different paths after StripPrefix and StripPrefixRegex normalisation ([#13215](https://github.com/traefik/traefik/pull/13215) @rtribotte)
- **[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)
## [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)
@ -28,13 +40,7 @@
## [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)
**Bug fixes:**
- **[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)
- **[server]** Move snicheck to ctx instead of simulated routing ([#13214](https://github.com/traefik/traefik/pull/13214) @juliens)
- **[middleware]** Reject requests with different paths after StripPrefix and StripPrefixRegex normalisation ([#13215](https://github.com/traefik/traefik/pull/13215) @rtribotte)
- **[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)
Release canceled.
## [v3.6.17](https://github.com/traefik/traefik/tree/v3.6.17) (2026-05-11)
[All Commits](https://github.com/traefik/traefik/compare/v3.6.16...v3.6.17)

View file

@ -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"

View file

@ -115,8 +115,69 @@ func (s *HTTPSSuite) TestWithSNIConfigRoute() {
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() {
file := s.adaptFile("fixtures/https/https_tls_options.toml", struct{}{})
s.traefikCmd(withConfigFile(file))

View file

@ -170,7 +170,7 @@ func mergeConfiguration(configurations dynamic.Configurations, defaultEntryPoint
delete(conf.TLS.Options, traefiktls.DefaultTLSConfigName)
}
return resolveHTTPTLSOptions(conf)
return conf
}
func resolveHTTPTLSOptions(cfg dynamic.Configuration) dynamic.Configuration {

View file

@ -167,6 +167,7 @@ func (c *ConfigurationWatcher) applyConfigurations(ctx context.Context) {
conf := mergeConfiguration(newConfigs.DeepCopy(), c.defaultEntryPoints)
conf = applyModel(conf)
conf = resolveHTTPTLSOptions(conf)
for _, listener := range c.configurationListeners {
listener(conf)

View file

@ -908,3 +908,52 @@ func TestPublishConfigUpdatedByConfigWatcherListener(t *testing.T) {
assert.Equal(t, 1, publishedConfigCount)
}
// 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
}