func (a *ACME) retrieveCertificates() { log.Infof("Retrieving ACME certificates...") for _, domain := range a.Domains { // check if cert isn't already loaded account := a.store.Get().(*Account) if _, exists := account.DomainsCertificate.exists(domain); !exists { domains := []string{} domains = append(domains, domain.Main) domains = append(domains, domain.SANs...) certificateResource, err := a.getDomainsCertificates(domains) if err != nil { log.Errorf("Error getting ACME certificate for domain %s: %s", domains, err.Error()) continue } transaction, object, err := a.store.Begin() if err != nil { log.Errorf("Error creating ACME store transaction from domain %s: %s", domain, err.Error()) continue } account = object.(*Account) _, err = account.DomainsCertificate.addCertificateForDomains(certificateResource, domain) if err != nil { log.Errorf("Error adding ACME certificate for domain %s: %s", domains, err.Error()) continue } if err = transaction.Commit(account); err != nil { log.Errorf("Error Saving ACME account %+v: %s", account, err.Error()) continue } } } log.Infof("Retrieved ACME certificates") }
func (server *Server) prepareServer(entryPointName string, router *middlewares.HandlerSwitcher, entryPoint *EntryPoint, oldServer *manners.GracefulServer, middlewares ...negroni.Handler) (*manners.GracefulServer, error) { log.Infof("Preparing server %s %+v", entryPointName, entryPoint) // middlewares var negroni = negroni.New() for _, middleware := range middlewares { negroni.Use(middleware) } negroni.UseHandler(router) tlsConfig, err := server.createTLSConfig(entryPointName, entryPoint.TLS, router) if err != nil { log.Errorf("Error creating TLS config %s", err) return nil, err } if oldServer == nil { return manners.NewWithServer( &http.Server{ Addr: entryPoint.Address, Handler: negroni, TLSConfig: tlsConfig, }), nil } gracefulServer, err := oldServer.HijackListener(&http.Server{ Addr: entryPoint.Address, Handler: negroni, TLSConfig: tlsConfig, }, tlsConfig) if err != nil { log.Errorf("Error hijacking server %s", err) return nil, err } return gracefulServer, nil }
func (server *Server) listenConfigurations(stop chan bool) { for { select { case <-stop: return case configMsg, ok := <-server.configurationValidatedChan: if !ok { return } currentConfigurations := server.currentConfigurations.Get().(configs) // Copy configurations to new map so we don't change current if LoadConfig fails newConfigurations := make(configs) for k, v := range currentConfigurations { newConfigurations[k] = v } newConfigurations[configMsg.ProviderName] = configMsg.Configuration newServerEntryPoints, err := server.loadConfig(newConfigurations, server.globalConfiguration) if err == nil { for newServerEntryPointName, newServerEntryPoint := range newServerEntryPoints { server.serverEntryPoints[newServerEntryPointName].httpRouter.UpdateHandler(newServerEntryPoint.httpRouter.GetHandler()) log.Infof("Server configuration reloaded on %s", server.serverEntryPoints[newServerEntryPointName].httpServer.Addr) } server.currentConfigurations.Set(newConfigurations) server.postLoadConfig() } else { log.Error("Error loading new configuration, aborted ", err) } } } }
func (provider *Kubernetes) newK8sClient() (k8s.Client, error) { if provider.Endpoint != "" { log.Infof("Creating in cluster Kubernetes client with endpoint %", provider.Endpoint) return k8s.NewInClusterClientWithEndpoint(provider.Endpoint) } log.Info("Creating in cluster Kubernetes client") return k8s.NewInClusterClient() }
func (l *Leadership) onElection(elected bool) { if elected { log.Infof("Node %s elected leader ♚", l.Cluster.Node) l.leader.Set(true) l.Start() } else { log.Infof("Node %s elected slave ♝", l.Cluster.Node) l.leader.Set(false) l.Stop() } for _, listener := range l.listeners { err := listener(elected) if err != nil { log.Errorf("Error calling Leadership listener: %s", err) } } }
func (server *Server) listenProviders(stop chan bool) { lastReceivedConfiguration := safe.New(time.Unix(0, 0)) lastConfigs := cmap.New() for { select { case <-stop: return case configMsg, ok := <-server.configurationChan: if !ok { return } server.defaultConfigurationValues(configMsg.Configuration) currentConfigurations := server.currentConfigurations.Get().(configs) jsonConf, _ := json.Marshal(configMsg.Configuration) log.Debugf("Configuration received from provider %s: %s", configMsg.ProviderName, string(jsonConf)) if configMsg.Configuration == nil || configMsg.Configuration.Backends == nil && configMsg.Configuration.Frontends == nil { log.Infof("Skipping empty Configuration for provider %s", configMsg.ProviderName) } else if reflect.DeepEqual(currentConfigurations[configMsg.ProviderName], configMsg.Configuration) { log.Infof("Skipping same configuration for provider %s", configMsg.ProviderName) } else { lastConfigs.Set(configMsg.ProviderName, &configMsg) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(server.globalConfiguration.ProvidersThrottleDuration))) { log.Debugf("Last %s config received more than %s, OK", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) // last config received more than n s ago server.configurationValidatedChan <- configMsg } else { log.Debugf("Last %s config received less than %s, waiting...", configMsg.ProviderName, server.globalConfiguration.ProvidersThrottleDuration.String()) safe.Go(func() { <-time.After(server.globalConfiguration.ProvidersThrottleDuration) lastReceivedConfigurationValue := lastReceivedConfiguration.Get().(time.Time) if time.Now().After(lastReceivedConfigurationValue.Add(time.Duration(server.globalConfiguration.ProvidersThrottleDuration))) { log.Debugf("Waited for %s config, OK", configMsg.ProviderName) if lastConfig, ok := lastConfigs.Get(configMsg.ProviderName); ok { server.configurationValidatedChan <- *lastConfig.(*types.ConfigMessage) } } }) } lastReceivedConfiguration.Set(time.Now()) } } } }
func (server *Server) startServer(srv *manners.GracefulServer, globalConfiguration GlobalConfiguration) { log.Infof("Starting server on %s", srv.Addr) if srv.TLSConfig != nil { if err := srv.ListenAndServeTLSWithConfig(srv.TLSConfig); err != nil { log.Fatal("Error creating server: ", err) } } else { if err := srv.ListenAndServe(); err != nil { log.Fatal("Error creating server: ", err) } } log.Info("Server stopped") }
func (server *Server) startProviders() { // start providers for _, provider := range server.providers { jsonConf, _ := json.Marshal(provider) log.Infof("Starting provider %v %s", reflect.TypeOf(provider), jsonConf) currentProvider := provider safe.Go(func() { err := currentProvider.Provide(server.configurationChan, server.routinesPool, server.globalConfiguration.Constraints) if err != nil { log.Errorf("Error starting provider %s", err) } }) } }
// Load loads file into store func (s *LocalStore) Load() (cluster.Object, error) { s.storageLock.Lock() defer s.storageLock.Unlock() account := &Account{} file, err := ioutil.ReadFile(s.file) if err != nil { return nil, err } if err := json.Unmarshal(file, &account); err != nil { return nil, err } account.Init() s.account = account log.Infof("Loaded ACME config from store %s", s.file) return account, nil }
func (server *Server) listenSignals() { sig := <-server.signals log.Infof("I have to go... %+v", sig) log.Info("Stopping server") server.Stop() }
func run(traefikConfiguration *TraefikConfiguration) { fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags) // load global configuration globalConfiguration := traefikConfiguration.GlobalConfiguration http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = globalConfiguration.MaxIdleConnsPerHost if globalConfiguration.InsecureSkipVerify { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} } loggerMiddleware := middlewares.NewLogger(globalConfiguration.AccessLogsFile) defer loggerMiddleware.Close() if globalConfiguration.File != nil && len(globalConfiguration.File.Filename) == 0 { // no filename, setting to global config file if len(traefikConfiguration.ConfigFile) != 0 { globalConfiguration.File.Filename = traefikConfiguration.ConfigFile } else { log.Errorln("Error using file configuration backend, no filename defined") } } if len(globalConfiguration.EntryPoints) == 0 { globalConfiguration.EntryPoints = map[string]*EntryPoint{"http": {Address: ":80"}} globalConfiguration.DefaultEntryPoints = []string{"http"} } if globalConfiguration.Debug { globalConfiguration.LogLevel = "DEBUG" } // logging level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel)) if err != nil { log.Error("Error getting level", err) } log.SetLevel(level) if len(globalConfiguration.TraefikLogsFile) > 0 { fi, err := os.OpenFile(globalConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) defer func() { if err := fi.Close(); err != nil { log.Error("Error closing file", err) } }() if err != nil { log.Error("Error opening file", err) } else { log.SetOutput(fi) log.SetFormatter(&logrus.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true}) } } else { log.SetFormatter(&logrus.TextFormatter{FullTimestamp: true, DisableSorting: true}) } jsonConf, _ := json.Marshal(globalConfiguration) log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) if globalConfiguration.CheckNewVersion { ticker := time.NewTicker(24 * time.Hour) safe.Go(func() { version.CheckNewVersion() for { select { case <-ticker.C: version.CheckNewVersion() } } }) } if len(traefikConfiguration.ConfigFile) != 0 { log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile) } log.Debugf("Global configuration loaded %s", string(jsonConf)) server := NewServer(globalConfiguration) server.Start() defer server.Close() sent, err := daemon.SdNotify("READY=1") if !sent && err != nil { log.Error("Fail to notify", err) } server.Wait() log.Info("Shutting down") }
// CreateLocalConfig creates a tls.config using local ACME configuration func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, checkOnDemandDomain func(domain string) bool) error { err := a.init() if err != nil { return err } if len(a.Storage) == 0 { return errors.New("Empty Store, please provide a filename for certs storage") } a.checkOnDemandDomain = checkOnDemandDomain tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate) tlsConfig.GetCertificate = a.getCertificate localStore := NewLocalStore(a.Storage) a.store = localStore a.challengeProvider = &challengeProvider{store: a.store} var needRegister bool var account *Account if fileInfo, fileErr := os.Stat(a.Storage); fileErr == nil && fileInfo.Size() != 0 { log.Infof("Loading ACME Account...") // load account object, err := localStore.Load() if err != nil { return err } account = object.(*Account) } else { log.Infof("Generating ACME Account...") account, err = NewAccount(a.Email) if err != nil { return err } needRegister = true } a.client, err = a.buildACMEClient(account) if err != nil { return err } if needRegister { // New users will need to register; be sure to save it log.Infof("Register...") reg, err := a.client.Register() if err != nil { return err } account.Registration = reg } // The client has a URL to the current Let's Encrypt Subscriber // Agreement. The user will need to agree to it. log.Debugf("AgreeToTOS...") err = a.client.AgreeToTOS() if err != nil { // Let's Encrypt Subscriber Agreement renew ? reg, err := a.client.QueryRegistration() if err != nil { return err } account.Registration = reg err = a.client.AgreeToTOS() if err != nil { log.Errorf("Error sending ACME agreement to TOS: %+v: %s", account, err.Error()) } } // save account transaction, _, err := a.store.Begin() if err != nil { return err } err = transaction.Commit(account) if err != nil { return err } safe.Go(func() { a.retrieveCertificates() if err := a.renewCertificates(); err != nil { log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error()) } }) ticker := time.NewTicker(24 * time.Hour) safe.Go(func() { for range ticker.C { if err := a.renewCertificates(); err != nil { log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error()) } } }) return nil }
// CreateClusterConfig creates a tls.config using ACME configuration in cluster mode func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tls.Config, checkOnDemandDomain func(domain string) bool) error { err := a.init() if err != nil { return err } if len(a.Storage) == 0 { return errors.New("Empty Store, please provide a key for certs storage") } a.checkOnDemandDomain = checkOnDemandDomain tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate) tlsConfig.GetCertificate = a.getCertificate listener := func(object cluster.Object) error { account := object.(*Account) account.Init() if !leadership.IsLeader() { a.client, err = a.buildACMEClient(account) if err != nil { log.Errorf("Error building ACME client %+v: %s", object, err.Error()) } } return nil } datastore, err := cluster.NewDataStore( leadership.Pool.Ctx(), staert.KvSource{ Store: leadership.Store, Prefix: a.Storage, }, &Account{}, listener) if err != nil { return err } a.store = datastore a.challengeProvider = &challengeProvider{store: a.store} ticker := time.NewTicker(24 * time.Hour) leadership.Pool.AddGoCtx(func(ctx context.Context) { log.Infof("Starting ACME renew job...") defer log.Infof("Stopped ACME renew job...") for { select { case <-ctx.Done(): return case <-ticker.C: if err := a.renewCertificates(); err != nil { log.Errorf("Error renewing ACME certificate: %s", err.Error()) } } } }) leadership.AddListener(func(elected bool) error { if elected { object, err := a.store.Load() if err != nil { return err } transaction, object, err := a.store.Begin() if err != nil { return err } account := object.(*Account) account.Init() var needRegister bool if account == nil || len(account.Email) == 0 { account, err = NewAccount(a.Email) if err != nil { return err } needRegister = true } if err != nil { return err } a.client, err = a.buildACMEClient(account) if err != nil { return err } if needRegister { // New users will need to register; be sure to save it log.Debugf("Register...") reg, err := a.client.Register() if err != nil { return err } account.Registration = reg } // The client has a URL to the current Let's Encrypt Subscriber // Agreement. The user will need to agree to it. log.Debugf("AgreeToTOS...") err = a.client.AgreeToTOS() if err != nil { // Let's Encrypt Subscriber Agreement renew ? reg, err := a.client.QueryRegistration() if err != nil { return err } account.Registration = reg err = a.client.AgreeToTOS() if err != nil { log.Errorf("Error sending ACME agreement to TOS: %+v: %s", account, err.Error()) } } err = transaction.Commit(account) if err != nil { return err } safe.Go(func() { a.retrieveCertificates() if err := a.renewCertificates(); err != nil { log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error()) } }) } return nil }) return nil }
// Resign resigns from being a leader func (l *Leadership) Resign() { l.candidate.Resign() log.Infof("Node %s resigned", l.Cluster.Node) }