Allow deleting dynamically all TLS certificates from an entryPoint
This commit is contained in:
parent
89a79d0f1b
commit
1e44e339ad
3 changed files with 101 additions and 6 deletions
|
@ -6,6 +6,9 @@ defaultEntryPoints = ["https"]
|
||||||
[entryPoints.https]
|
[entryPoints.https]
|
||||||
address = ":4443"
|
address = ":4443"
|
||||||
[entryPoints.https.tls]
|
[entryPoints.https.tls]
|
||||||
|
[entryPoints.https02]
|
||||||
|
address = ":8443"
|
||||||
|
[entryPoints.https02.tls]
|
||||||
|
|
||||||
[web]
|
[web]
|
||||||
address = ":8080"
|
address = ":8080"
|
||||||
|
|
|
@ -353,7 +353,7 @@ func startTestServer(port string, statusCode int) (ts *httptest.Server) {
|
||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWithSNIConfigRoute involves a client sending HTTPS requests with
|
// TestWithSNIDynamicConfigRouteWithNoChange involves a client sending HTTPS requests with
|
||||||
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
||||||
// that traefik routes the requests to the expected backends thanks to given certificate if possible
|
// that traefik routes the requests to the expected backends thanks to given certificate if possible
|
||||||
// otherwise thanks to the default one.
|
// otherwise thanks to the default one.
|
||||||
|
@ -424,7 +424,7 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithNoChange(c *check.C) {
|
||||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNoContent)
|
c.Assert(resp.StatusCode, checker.Equals, http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWithSNIConfigRoute involves a client sending HTTPS requests with
|
// TestWithSNIDynamicConfigRouteWithChange involves a client sending HTTPS requests with
|
||||||
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
||||||
// that traefik updates its configuration when the HTTPS configuration is modified and
|
// 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
|
// it routes the requests to the expected backends thanks to given certificate if possible
|
||||||
|
@ -479,7 +479,7 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithChange(c *check.C) {
|
||||||
req.Header.Set("Accept", "*/*")
|
req.Header.Set("Accept", "*/*")
|
||||||
|
|
||||||
// Change certificates configuration file content
|
// Change certificates configuration file content
|
||||||
modifyCertificateConfFileContent(c, tr1.TLSClientConfig.ServerName, dynamicConfFileName)
|
modifyCertificateConfFileContent(c, tr1.TLSClientConfig.ServerName, dynamicConfFileName, "https")
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
err = try.Do(30*time.Second, func() error {
|
err = try.Do(30*time.Second, func() error {
|
||||||
resp, err = client.Do(req)
|
resp, err = client.Do(req)
|
||||||
|
@ -525,8 +525,96 @@ func (s *HTTPSSuite) TestWithSNIDynamicConfigRouteWithChange(c *check.C) {
|
||||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestWithSNIDynamicConfigRouteWithChangeForEmptyTlsConfiguration involves a client sending HTTPS requests with
|
||||||
|
// SNI hostnames of "snitest.org" and "snitest.com". The test verifies
|
||||||
|
// 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(c *check.C) {
|
||||||
|
dynamicConfFileName := s.adaptFile(c, "fixtures/https/dynamic_https.toml", struct{}{})
|
||||||
|
defer os.Remove(dynamicConfFileName)
|
||||||
|
confFileName := s.adaptFile(c, "fixtures/https/dynamic_https_sni.toml", struct {
|
||||||
|
DynamicConfFileName string
|
||||||
|
}{
|
||||||
|
DynamicConfFileName: dynamicConfFileName,
|
||||||
|
})
|
||||||
|
defer os.Remove(confFileName)
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile(confFileName))
|
||||||
|
defer display(c)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
tr2 := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
ServerName: "snitest.org",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for Traefik
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8080/api/providers", 1*time.Second, try.BodyContains("Host:"+tr2.TLSClientConfig.ServerName))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
backend2 := startTestServer("9020", http.StatusResetContent)
|
||||||
|
|
||||||
|
defer backend2.Close()
|
||||||
|
|
||||||
|
err = try.GetRequest(backend2.URL, 500*time.Millisecond, try.StatusCodeIs(http.StatusResetContent))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://127.0.0.1:4443/", nil)
|
||||||
|
client := &http.Client{Transport: tr2}
|
||||||
|
req.Host = tr2.TLSClientConfig.ServerName
|
||||||
|
req.Header.Set("Host", tr2.TLSClientConfig.ServerName)
|
||||||
|
req.Header.Set("Accept", "*/*")
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
err = try.Do(30*time.Second, func() error {
|
||||||
|
resp, err = client.Do(req)
|
||||||
|
|
||||||
|
// /!\ If connection is not closed, SSLHandshake will only be done during the first trial /!\
|
||||||
|
req.Close = true
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cn := resp.TLS.PeerCertificates[0].Subject.CommonName
|
||||||
|
if cn != tr2.TLSClientConfig.ServerName {
|
||||||
|
return fmt.Errorf("domain %s found in place of %s", cn, tr2.TLSClientConfig.ServerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(resp.StatusCode, checker.Equals, http.StatusResetContent)
|
||||||
|
// Change certificates configuration file content
|
||||||
|
modifyCertificateConfFileContent(c, "snitest.com", dynamicConfFileName, "https02")
|
||||||
|
|
||||||
|
err = try.Do(60*time.Second, func() error {
|
||||||
|
resp, err = client.Do(req)
|
||||||
|
|
||||||
|
// /!\ If connection is not closed, SSLHandshake will only be done during the first trial /!\
|
||||||
|
req.Close = true
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cn := resp.TLS.PeerCertificates[0].Subject.CommonName
|
||||||
|
if cn == tr2.TLSClientConfig.ServerName {
|
||||||
|
return fmt.Errorf("domain %s found in place of default one", tr2.TLSClientConfig.ServerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
|
// modifyCertificateConfFileContent replaces the content of a HTTPS configuration file.
|
||||||
func modifyCertificateConfFileContent(c *check.C, certFileName, confFileName string) {
|
func modifyCertificateConfFileContent(c *check.C, certFileName, confFileName, entryPoint string) {
|
||||||
tlsConf := types.Configuration{
|
tlsConf := types.Configuration{
|
||||||
TLSConfiguration: []*traefikTls.Configuration{
|
TLSConfiguration: []*traefikTls.Configuration{
|
||||||
{
|
{
|
||||||
|
@ -534,7 +622,7 @@ func modifyCertificateConfFileContent(c *check.C, certFileName, confFileName str
|
||||||
CertFile: traefikTls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
|
CertFile: traefikTls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
|
||||||
KeyFile: traefikTls.FileOrContent("fixtures/https/" + certFileName + ".key"),
|
KeyFile: traefikTls.FileOrContent("fixtures/https/" + certFileName + ".key"),
|
||||||
},
|
},
|
||||||
EntryPoints: []string{"https"},
|
EntryPoints: []string{entryPoint},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,7 +439,11 @@ func (s *Server) loadConfiguration(configMsg types.ConfigMessage) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for newServerEntryPointName, newServerEntryPoint := range newServerEntryPoints {
|
for newServerEntryPointName, newServerEntryPoint := range newServerEntryPoints {
|
||||||
s.serverEntryPoints[newServerEntryPointName].httpRouter.UpdateHandler(newServerEntryPoint.httpRouter.GetHandler())
|
s.serverEntryPoints[newServerEntryPointName].httpRouter.UpdateHandler(newServerEntryPoint.httpRouter.GetHandler())
|
||||||
if &newServerEntryPoint.certs != nil {
|
if s.globalConfiguration.EntryPoints[newServerEntryPointName].TLS == nil {
|
||||||
|
if newServerEntryPoint.certs.Get() != nil {
|
||||||
|
log.Debugf("Certificates not added to non-TLS entryPoint %s.", newServerEntryPointName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
s.serverEntryPoints[newServerEntryPointName].certs.Set(newServerEntryPoint.certs.Get())
|
s.serverEntryPoints[newServerEntryPointName].certs.Set(newServerEntryPoint.certs.Get())
|
||||||
}
|
}
|
||||||
log.Infof("Server configuration reloaded on %s", s.serverEntryPoints[newServerEntryPointName].httpServer.Addr)
|
log.Infof("Server configuration reloaded on %s", s.serverEntryPoints[newServerEntryPointName].httpServer.Addr)
|
||||||
|
|
Loading…
Reference in a new issue