Add a mutex on local store for HTTPChallenges

This commit is contained in:
SALLEYRON Julien 2018-07-09 23:28:03 +02:00 committed by Traefiker Bot
parent bacd58ed7b
commit f173ff02e3
4 changed files with 66 additions and 53 deletions

View file

@ -175,7 +175,7 @@ func runCmd(globalConfiguration *configuration.GlobalConfiguration, configFile s
log.Debugf("Global configuration loaded %s", string(jsonConf)) log.Debugf("Global configuration loaded %s", string(jsonConf))
if acme.IsEnabled() { if acme.IsEnabled() {
store := acme.NewLocalStore(acme.Get().Storage) store := acme.NewLocalStore(acme.Get().Storage)
acme.Get().Store = &store acme.Get().Store = store
} }
svr := server.NewServer(*globalConfiguration, configuration.NewProviderAggregator(globalConfiguration)) svr := server.NewServer(*globalConfiguration, configuration.NewProviderAggregator(globalConfiguration))
if acme.IsEnabled() && acme.Get().OnHostRule { if acme.IsEnabled() && acme.Get().OnHostRule {

View file

@ -34,15 +34,9 @@ func getTokenValue(token, domain string, store Store) []byte {
var result []byte var result []byte
operation := func() error { operation := func() error {
var ok bool var err error
httpChallenges, err := store.GetHTTPChallenges() result, err = store.GetHTTPChallengeToken(token, domain)
if err != nil { return err
return fmt.Errorf("HTTPChallenges not available : %s", err)
}
if result, ok = httpChallenges[token][domain]; !ok {
return fmt.Errorf("cannot find challenge for token %v", token)
}
return nil
} }
notify := func(err error, time time.Duration) { notify := func(err error, time time.Duration) {
@ -60,40 +54,9 @@ func getTokenValue(token, domain string, store Store) []byte {
} }
func presentHTTPChallenge(domain, token, keyAuth string, store Store) error { func presentHTTPChallenge(domain, token, keyAuth string, store Store) error {
httpChallenges, err := store.GetHTTPChallenges() return store.SetHTTPChallengeToken(token, domain, []byte(keyAuth))
if err != nil {
return fmt.Errorf("unable to get HTTPChallenges : %s", err)
}
if httpChallenges == nil {
httpChallenges = map[string]map[string][]byte{}
}
if _, ok := httpChallenges[token]; !ok {
httpChallenges[token] = map[string][]byte{}
}
httpChallenges[token][domain] = []byte(keyAuth)
return store.SaveHTTPChallenges(httpChallenges)
} }
func cleanUpHTTPChallenge(domain, token string, store Store) error { func cleanUpHTTPChallenge(domain, token string, store Store) error {
httpChallenges, err := store.GetHTTPChallenges() return store.RemoveHTTPChallengeToken(token, domain)
if err != nil {
return fmt.Errorf("unable to get HTTPChallenges : %s", err)
}
log.Debugf("Challenge CleanUp for domain %s", domain)
if _, ok := httpChallenges[token]; ok {
if _, domainOk := httpChallenges[token][domain]; domainOk {
delete(httpChallenges[token], domain)
}
if len(httpChallenges[token]) == 0 {
delete(httpChallenges, token)
}
return store.SaveHTTPChallenges(httpChallenges)
}
return nil
} }

View file

@ -2,9 +2,11 @@ package acme
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"regexp" "regexp"
"sync"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/containous/traefik/safe" "github.com/containous/traefik/safe"
@ -17,11 +19,12 @@ type LocalStore struct {
filename string filename string
storedData *StoredData storedData *StoredData
SaveDataChan chan *StoredData `json:"-"` SaveDataChan chan *StoredData `json:"-"`
lock sync.RWMutex
} }
// NewLocalStore initializes a new LocalStore with a file name // NewLocalStore initializes a new LocalStore with a file name
func NewLocalStore(filename string) LocalStore { func NewLocalStore(filename string) *LocalStore {
store := LocalStore{filename: filename, SaveDataChan: make(chan *StoredData)} store := &LocalStore{filename: filename, SaveDataChan: make(chan *StoredData)}
store.listenSaveAction() store.listenSaveAction()
return store return store
} }
@ -149,13 +152,59 @@ func (s *LocalStore) SaveCertificates(certificates []*Certificate) error {
return nil return nil
} }
// GetHTTPChallenges returns ACME HTTP Challenges list // GetHTTPChallengeToken Get the http challenge token from the store
func (s *LocalStore) GetHTTPChallenges() (map[string]map[string][]byte, error) { func (s *LocalStore) GetHTTPChallengeToken(token, domain string) ([]byte, error) {
return s.storedData.HTTPChallenges, nil s.lock.RLock()
defer s.lock.RUnlock()
if s.storedData.HTTPChallenges == nil {
s.storedData.HTTPChallenges = map[string]map[string][]byte{}
}
if _, ok := s.storedData.HTTPChallenges[token]; !ok {
return nil, fmt.Errorf("cannot find challenge for token %v", token)
}
result, ok := s.storedData.HTTPChallenges[token][domain]
if !ok {
return nil, fmt.Errorf("cannot find challenge for token %v", token)
}
return result, nil
} }
// SaveHTTPChallenges stores ACME HTTP Challenges list // SetHTTPChallengeToken Set the http challenge token in the store
func (s *LocalStore) SaveHTTPChallenges(httpChallenges map[string]map[string][]byte) error { func (s *LocalStore) SetHTTPChallengeToken(token, domain string, keyAuth []byte) error {
s.storedData.HTTPChallenges = httpChallenges s.lock.Lock()
defer s.lock.Unlock()
if s.storedData.HTTPChallenges == nil {
s.storedData.HTTPChallenges = map[string]map[string][]byte{}
}
if _, ok := s.storedData.HTTPChallenges[token]; !ok {
s.storedData.HTTPChallenges[token] = map[string][]byte{}
}
s.storedData.HTTPChallenges[token][domain] = []byte(keyAuth)
return nil
}
// RemoveHTTPChallengeToken Remove the http challenge token in the store
func (s *LocalStore) RemoveHTTPChallengeToken(token, domain string) error {
s.lock.Lock()
defer s.lock.Unlock()
if s.storedData.HTTPChallenges == nil {
return nil
}
if _, ok := s.storedData.HTTPChallenges[token]; ok {
if _, domainOk := s.storedData.HTTPChallenges[token][domain]; domainOk {
delete(s.storedData.HTTPChallenges[token], domain)
}
if len(s.storedData.HTTPChallenges[token]) == 0 {
delete(s.storedData.HTTPChallenges, token)
}
}
return nil return nil
} }

View file

@ -13,6 +13,7 @@ type Store interface {
SaveAccount(*Account) error SaveAccount(*Account) error
GetCertificates() ([]*Certificate, error) GetCertificates() ([]*Certificate, error)
SaveCertificates([]*Certificate) error SaveCertificates([]*Certificate) error
GetHTTPChallenges() (map[string]map[string][]byte, error) GetHTTPChallengeToken(token, domain string) ([]byte, error)
SaveHTTPChallenges(map[string]map[string][]byte) error SetHTTPChallengeToken(token, domain string, keyAuth []byte) error
RemoveHTTPChallengeToken(token, domain string) error
} }