// creates a TLS config that allows terminating HTTPS for multiple domains using SNI func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, router *middlewares.HandlerSwitcher) (*tls.Config, error) { if tlsOption == nil { return nil, nil } config := &tls.Config{} config.Certificates = []tls.Certificate{} for _, v := range tlsOption.Certificates { cert, err := tls.LoadX509KeyPair(v.CertFile, v.KeyFile) if err != nil { return nil, err } config.Certificates = append(config.Certificates, cert) } if server.globalConfiguration.ACME != nil { if _, ok := server.serverEntryPoints[server.globalConfiguration.ACME.EntryPoint]; ok { if entryPointName == server.globalConfiguration.ACME.EntryPoint { checkOnDemandDomain := func(domain string) bool { if router.GetHandler().Match(&http.Request{URL: &url.URL{}, Host: domain}, &mux.RouteMatch{}) { return true } return false } err := server.globalConfiguration.ACME.CreateConfig(config, checkOnDemandDomain) if err != nil { return nil, err } } } else { return nil, errors.New("Unknown entrypoint " + server.globalConfiguration.ACME.EntryPoint + " for ACME configuration") } } if len(config.Certificates) == 0 { return nil, errors.New("No certificates found for TLS entrypoint " + entryPointName) } // BuildNameToCertificate parses the CommonName and SubjectAlternateName fields // in each certificate and populates the config.NameToCertificate map. config.BuildNameToCertificate() return config, nil }
// creates a TLS config that allows terminating HTTPS for multiple domains using SNI func (server *Server) createTLSConfig(entryPointName string, tlsOption *TLS, router *middlewares.HandlerSwitcher) (*tls.Config, error) { if tlsOption == nil { return nil, nil } config, err := tlsOption.Certificates.CreateTLSConfig() if err != nil { return nil, err } // ensure http2 enabled config.NextProtos = []string{"h2", "http/1.1"} if len(tlsOption.ClientCAFiles) > 0 { pool := x509.NewCertPool() for _, caFile := range tlsOption.ClientCAFiles { data, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } ok := pool.AppendCertsFromPEM(data) if !ok { return nil, errors.New("invalid certificate(s) in " + caFile) } } config.ClientCAs = pool config.ClientAuth = tls.RequireAndVerifyClientCert } if server.globalConfiguration.ACME != nil { if _, ok := server.serverEntryPoints[server.globalConfiguration.ACME.EntryPoint]; ok { if entryPointName == server.globalConfiguration.ACME.EntryPoint { checkOnDemandDomain := func(domain string) bool { routeMatch := &mux.RouteMatch{} router := router.GetHandler() match := router.Match(&http.Request{URL: &url.URL{}, Host: domain}, routeMatch) if match && routeMatch.Route != nil { return true } return false } if server.leadership == nil { err := server.globalConfiguration.ACME.CreateLocalConfig(config, checkOnDemandDomain) if err != nil { return nil, err } } else { err := server.globalConfiguration.ACME.CreateClusterConfig(server.leadership, config, checkOnDemandDomain) if err != nil { return nil, err } } } } else { return nil, errors.New("Unknown entrypoint " + server.globalConfiguration.ACME.EntryPoint + " for ACME configuration") } } if len(config.Certificates) == 0 { return nil, errors.New("No certificates found for TLS entrypoint " + entryPointName) } // BuildNameToCertificate parses the CommonName and SubjectAlternateName fields // in each certificate and populates the config.NameToCertificate map. config.BuildNameToCertificate() //Set the minimum TLS version if set in the config TOML if minConst, exists := minVersion[server.globalConfiguration.EntryPoints[entryPointName].TLS.MinVersion]; exists { config.PreferServerCipherSuites = true config.MinVersion = minConst } //Set the list of CipherSuites if set in the config TOML if server.globalConfiguration.EntryPoints[entryPointName].TLS.CipherSuites != nil { //if our list of CipherSuites is defined in the entrypoint config, we can re-initilize the suites list as empty config.CipherSuites = make([]uint16, 0) for _, cipher := range server.globalConfiguration.EntryPoints[entryPointName].TLS.CipherSuites { if cipherConst, exists := cipherSuites[cipher]; exists { config.CipherSuites = append(config.CipherSuites, cipherConst) } else { //CipherSuite listed in the toml does not exist in our listed return nil, errors.New("Invalid CipherSuite: " + cipher) } } } return config, nil }