// find certs in and is the named directory, and match them up by their base // name using '.pem' and '.key' as extensions. func loadCerts(certDir string) (*tls.Config, error) { abs, err := filepath.Abs(certDir) if err != nil { return nil, err } dir, err := ioutil.ReadDir(abs) if err != nil { return nil, err } // [cert, key] pairs pairs := make(map[string][2]string) for _, f := range dir { name := f.Name() if strings.HasSuffix(name, ".pem") { p := pairs[name[:len(name)-4]] p[0] = filepath.Join(abs, name) pairs[name[:len(name)-4]] = p } if strings.HasSuffix(name, ".key") { p := pairs[name[:len(name)-4]] p[1] = filepath.Join(abs, name) pairs[name[:len(name)-4]] = p } } tlsCfg := &tls.Config{ NextProtos: []string{"http/1.1"}, } for key, pair := range pairs { if pair[0] == "" { log.Errorf("missing cert for key: %s", pair[1]) continue } if pair[1] == "" { log.Errorf("missing key for cert: %s", pair[0]) continue } cert, err := tls.LoadX509KeyPair(pair[0], pair[1]) if err != nil { log.Error(err) continue } tlsCfg.Certificates = append(tlsCfg.Certificates, cert) log.Debugf("loaded X509KeyPair for %s", key) } if len(tlsCfg.Certificates) == 0 { return nil, fmt.Errorf("no tls certificates loaded") } tlsCfg.BuildNameToCertificate() return tlsCfg, nil }
// Update a service and/or backends. func postService(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Errorln(err) http.Error(w, err.Error(), http.StatusInternalServerError) return } defer r.Body.Close() svcCfg := client.ServiceConfig{Name: vars["service"]} err = json.Unmarshal(body, &svcCfg) if err != nil { log.Errorln(err) http.Error(w, err.Error(), http.StatusInternalServerError) return } // don't let someone update the wrong service if svcCfg.Name != vars["service"] { errMsg := "Mismatched service name in API call" log.Error(errMsg) http.Error(w, errMsg, http.StatusBadRequest) return } cfg := client.Config{ Services: []client.ServiceConfig{svcCfg}, } err = Registry.UpdateConfig(cfg) //FIXME: this doesn't return an error for an empty or broken service if err != nil { log.Error(err) http.Error(w, err.Error(), http.StatusBadRequest) return } w.Write(marshal(Registry.Config())) }
func startHTTPSServer(wg *sync.WaitGroup) { defer wg.Done() tlsCfg, err := loadCerts(certDir) if err != nil { log.Error(err) return } //TODO: configure these timeouts somewhere httpsServer := &http.Server{ Addr: httpsAddr, ReadTimeout: 10 * time.Minute, WriteTimeout: 10 * time.Minute, MaxHeaderBytes: 1 << 20, TLSConfig: tlsCfg, } httpRouter = NewHostRouter(httpsServer) httpRouter.Scheme = "https" httpRouter.Start(nil) }