mirror of
https://github.com/traefik/traefik.git
synced 2026-06-17 19:09:29 +03:00
Add wildcard host in Host and HostSNI matchers
This commit is contained in:
+106
-19
@@ -30,6 +30,41 @@ func TestHTTPSSuite(t *testing.T) {
|
||||
suite.Run(t, &HTTPSSuite{})
|
||||
}
|
||||
|
||||
// TestWithWildcardHost verifies that a wildcard Host rule Host(`*.snitest.com`)
|
||||
// routes HTTPS requests for any matching subdomain to the configured service.
|
||||
func (s *SimpleSuite) TestWithWildcardHost() {
|
||||
backend := startTestServer("9040", http.StatusOK, "")
|
||||
defer backend.Close()
|
||||
|
||||
file := s.adaptFile("fixtures/https/https_wildcard_host.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
|
||||
// Wait for Traefik to load the wildcard router.
|
||||
err := try.GetRequest("http://127.0.0.1:8080/api/rawdata", 5*time.Second,
|
||||
try.BodyContains("Host(`*.snitest.com`)"))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
|
||||
// foo.snitest.com matches the wildcard and must be routed to the backend.
|
||||
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "foo.snitest.com"
|
||||
err = try.RequestWithTransport(req, 5*time.Second, tr, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
// bar.snitest.com also matches the wildcard and must be routed to the backend.
|
||||
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = "bar.snitest.com"
|
||||
err = try.RequestWithTransport(req, 3*time.Second, tr, try.StatusCodeIs(http.StatusOK))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// TestWithSNIConfigHandshake involves a client sending a SNI hostname of
|
||||
// "snitest.com", which happens to match the CN of 'snitest.com.crt'. The test
|
||||
// verifies that traefik presents the correct certificate.
|
||||
@@ -115,7 +150,6 @@ func (s *HTTPSSuite) TestWithSNIConfigRoute() {
|
||||
}
|
||||
|
||||
// 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))
|
||||
@@ -196,8 +230,71 @@ func (s *HTTPSSuite) TestWithTLSOptions() {
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// TestWithConflictingTLSOptions checks that routers with same SNI but different TLS options get fallbacked to the default TLS options.
|
||||
func (s *HTTPSSuite) TestWithTLSOptionsAndWildcard() {
|
||||
backend := startTestServer("0", http.StatusNoContent, "")
|
||||
defer backend.Close()
|
||||
|
||||
err := try.GetRequest(backend.URL, 1*time.Second, try.StatusCodeIs(http.StatusNoContent))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
file := s.adaptFile("fixtures/https/https_wildcard_tls_options.toml", struct{ BackendURL string }{backend.URL})
|
||||
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)
|
||||
|
||||
tr1 := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
MaxVersion: tls.VersionTLS12,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
ServerName: "bar.snitest.com",
|
||||
},
|
||||
}
|
||||
|
||||
tr2 := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
MaxVersion: tls.VersionTLS13,
|
||||
MinVersion: tls.VersionTLS13,
|
||||
ServerName: "foo.snitest.com",
|
||||
},
|
||||
}
|
||||
|
||||
tr3 := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
MaxVersion: tls.VersionTLS11,
|
||||
MinVersion: tls.VersionTLS11,
|
||||
ServerName: "other.snitest.com",
|
||||
},
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = tr1.TLSClientConfig.ServerName
|
||||
|
||||
err = try.RequestWithTransport(req, 30*time.Second, tr1, try.StatusCodeIs(http.StatusNoContent))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = tr2.TLSClientConfig.ServerName
|
||||
|
||||
err = try.RequestWithTransport(req, 3*time.Second, tr2, try.StatusCodeIs(http.StatusNoContent))
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
req, err = http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||
require.NoError(s.T(), err)
|
||||
req.Host = tr3.TLSClientConfig.ServerName
|
||||
|
||||
err = try.RequestWithTransport(req, 3*time.Second, tr3, try.StatusCodeIs(http.StatusNoContent))
|
||||
require.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
// TestWithConflictingTLSOptions checks that routers with same SNI but different TLS options get fallbacked to the
|
||||
// default TLS options.
|
||||
func (s *HTTPSSuite) TestWithConflictingTLSOptions() {
|
||||
file := s.adaptFile("fixtures/https/https_tls_options.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -262,7 +359,6 @@ func (s *HTTPSSuite) TestWithConflictingTLSOptions() {
|
||||
// TestWithSNIStrictNotMatchedRequest involves a client sending a SNI hostname of
|
||||
// "snitest.org", which does not match the CN of 'snitest.com.crt'. The test
|
||||
// verifies that traefik closes the connection.
|
||||
|
||||
func (s *HTTPSSuite) TestWithSNIStrictNotMatchedRequest() {
|
||||
file := s.adaptFile("fixtures/https/https_sni_strict.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -284,7 +380,6 @@ func (s *HTTPSSuite) TestWithSNIStrictNotMatchedRequest() {
|
||||
// TestWithDefaultCertificate involves a client sending a SNI hostname of
|
||||
// "snitest.org", which does not match the CN of 'snitest.com.crt'. The test
|
||||
// verifies that traefik returns the default certificate.
|
||||
|
||||
func (s *HTTPSSuite) TestWithDefaultCertificate() {
|
||||
file := s.adaptFile("fixtures/https/https_sni_default_cert.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -316,7 +411,6 @@ func (s *HTTPSSuite) TestWithDefaultCertificate() {
|
||||
// TestWithDefaultCertificateNoSNI involves a client sending a request with no ServerName
|
||||
// which does not match the CN of 'snitest.com.crt'. The test
|
||||
// verifies that traefik returns the default certificate.
|
||||
|
||||
func (s *HTTPSSuite) TestWithDefaultCertificateNoSNI() {
|
||||
file := s.adaptFile("fixtures/https/https_sni_default_cert.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -348,7 +442,6 @@ func (s *HTTPSSuite) TestWithDefaultCertificateNoSNI() {
|
||||
// "www.snitest.com", which matches the CN of two static certificates:
|
||||
// 'wildcard.snitest.com.crt', and `www.snitest.com.crt`. The test
|
||||
// verifies that traefik returns the non-wildcard certificate.
|
||||
|
||||
func (s *HTTPSSuite) TestWithOverlappingStaticCertificate() {
|
||||
file := s.adaptFile("fixtures/https/https_sni_default_cert.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -381,7 +474,6 @@ func (s *HTTPSSuite) TestWithOverlappingStaticCertificate() {
|
||||
// "www.snitest.com", which matches the CN of two dynamic certificates:
|
||||
// 'wildcard.snitest.com.crt', and `www.snitest.com.crt`. The test
|
||||
// verifies that traefik returns the non-wildcard certificate.
|
||||
|
||||
func (s *HTTPSSuite) TestWithOverlappingDynamicCertificate() {
|
||||
file := s.adaptFile("fixtures/https/dynamic_https_sni_default_cert.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -410,9 +502,8 @@ func (s *HTTPSSuite) TestWithOverlappingDynamicCertificate() {
|
||||
assert.Equal(s.T(), "h2", proto)
|
||||
}
|
||||
|
||||
// TestWithClientCertificateAuthentication
|
||||
// The client can send a certificate signed by a CA trusted by the server but it's optional.
|
||||
|
||||
// TestWithClientCertificateAuthentication tests that a client can send a certificate signed by a CA trusted by the server
|
||||
// but it's optional.
|
||||
func (s *HTTPSSuite) TestWithClientCertificateAuthentication() {
|
||||
file := s.adaptFile("fixtures/https/clientca/https_1ca1config.toml", struct{}{})
|
||||
s.traefikCmd(withConfigFile(file))
|
||||
@@ -464,9 +555,8 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthentication() {
|
||||
assert.NoError(s.T(), err, "should be allowed to connect to server")
|
||||
}
|
||||
|
||||
// TestWithClientCertificateAuthentication
|
||||
// Use two CA:s and test that clients with client signed by either of them can connect.
|
||||
|
||||
// TestWithClientCertificateAuthenticationMultipleCAs uses two CA:s
|
||||
// and test that clients with client signed by either of them can connect.
|
||||
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAs() {
|
||||
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
||||
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
||||
@@ -557,9 +647,8 @@ func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAs() {
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
||||
// TestWithClientCertificateAuthentication
|
||||
// Use two CA:s in two different files and test that clients with client signed by either of them can connect.
|
||||
|
||||
// TestWithClientCertificateAuthenticationMultipleCAsMultipleFiles uses two CA:s in two different files
|
||||
// and test that clients with client signed by either of them can connect.
|
||||
func (s *HTTPSSuite) TestWithClientCertificateAuthenticationMultipleCAsMultipleFiles() {
|
||||
server1 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server1")) }))
|
||||
server2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) { _, _ = rw.Write([]byte("server2")) }))
|
||||
@@ -768,7 +857,6 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithNoChange() {
|
||||
// that traefik updates its configuration when the HTTPS configuration is modified and
|
||||
// it routes the requests to the expected backends thanks to given certificate if possible
|
||||
// otherwise thanks to the default one.
|
||||
|
||||
func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithChange() {
|
||||
dynamicConfFileName := s.adaptFile("fixtures/https/dynamic_https.toml", struct{}{})
|
||||
confFileName := s.adaptFile("fixtures/https/dynamic_https_sni.toml", struct {
|
||||
@@ -833,7 +921,6 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithChange() {
|
||||
// that traefik updates its configuration when the HTTPS configuration is modified, even if it totally deleted, and
|
||||
// it routes the requests to the expected backends thanks to given certificate if possible
|
||||
// otherwise thanks to the default one.
|
||||
|
||||
func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithTlsConfigurationDeletion() {
|
||||
dynamicConfFileName := s.adaptFile("fixtures/https/dynamic_https.toml", struct{}{})
|
||||
confFileName := s.adaptFile("fixtures/https/dynamic_https_sni.toml", struct {
|
||||
@@ -1143,7 +1230,7 @@ func (s *HTTPSSuite) TestWithInvalidTLSOption() {
|
||||
}
|
||||
}
|
||||
|
||||
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
|
||||
// modifyCertificateConfFileContent replaces the content of an HTTPS configuration file.
|
||||
func (s *HTTPSSuite) modifyCertificateConfFileContent(certFileName, confFileName string) {
|
||||
file, err := os.OpenFile("./"+confFileName, os.O_WRONLY, os.ModeExclusive)
|
||||
require.NoError(s.T(), err)
|
||||
|
||||
Reference in New Issue
Block a user