Skip to content

Commit

Permalink
Add a mutex on local store for HTTPChallenges
Browse files Browse the repository at this point in the history
  • Loading branch information
juliens authored and traefiker committed Jul 9, 2018
1 parent bacd58e commit f173ff0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 53 deletions.
2 changes: 1 addition & 1 deletion cmd/traefik/traefik.go
Expand Up @@ -175,7 +175,7 @@ func runCmd(globalConfiguration *configuration.GlobalConfiguration, configFile s
log.Debugf("Global configuration loaded %s", string(jsonConf))
if acme.IsEnabled() {
store := acme.NewLocalStore(acme.Get().Storage)
acme.Get().Store = &store
acme.Get().Store = store
}
svr := server.NewServer(*globalConfiguration, configuration.NewProviderAggregator(globalConfiguration))
if acme.IsEnabled() && acme.Get().OnHostRule {
Expand Down
47 changes: 5 additions & 42 deletions provider/acme/challenge.go
Expand Up @@ -34,15 +34,9 @@ func getTokenValue(token, domain string, store Store) []byte {
var result []byte

operation := func() error {
var ok bool
httpChallenges, err := store.GetHTTPChallenges()
if err != nil {
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
var err error
result, err = store.GetHTTPChallengeToken(token, domain)
return err
}

notify := func(err error, time time.Duration) {
Expand All @@ -60,40 +54,9 @@ func getTokenValue(token, domain string, store Store) []byte {
}

func presentHTTPChallenge(domain, token, keyAuth string, store Store) error {
httpChallenges, err := store.GetHTTPChallenges()
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)
return store.SetHTTPChallengeToken(token, domain, []byte(keyAuth))
}

func cleanUpHTTPChallenge(domain, token string, store Store) error {
httpChallenges, err := store.GetHTTPChallenges()
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
return store.RemoveHTTPChallengeToken(token, domain)
}
65 changes: 57 additions & 8 deletions provider/acme/local_store.go
Expand Up @@ -2,9 +2,11 @@ package acme

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"regexp"
"sync"

"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
Expand All @@ -17,11 +19,12 @@ type LocalStore struct {
filename string
storedData *StoredData
SaveDataChan chan *StoredData `json:"-"`
lock sync.RWMutex
}

// NewLocalStore initializes a new LocalStore with a file name
func NewLocalStore(filename string) LocalStore {
store := LocalStore{filename: filename, SaveDataChan: make(chan *StoredData)}
func NewLocalStore(filename string) *LocalStore {
store := &LocalStore{filename: filename, SaveDataChan: make(chan *StoredData)}
store.listenSaveAction()
return store
}
Expand Down Expand Up @@ -149,13 +152,59 @@ func (s *LocalStore) SaveCertificates(certificates []*Certificate) error {
return nil
}

// GetHTTPChallenges returns ACME HTTP Challenges list
func (s *LocalStore) GetHTTPChallenges() (map[string]map[string][]byte, error) {
return s.storedData.HTTPChallenges, nil
// GetHTTPChallengeToken Get the http challenge token from the store
func (s *LocalStore) GetHTTPChallengeToken(token, domain string) ([]byte, error) {
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
}

// SetHTTPChallengeToken Set the http challenge token in the store
func (s *LocalStore) SetHTTPChallengeToken(token, domain string, keyAuth []byte) error {
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
}

// SaveHTTPChallenges stores ACME HTTP Challenges list
func (s *LocalStore) SaveHTTPChallenges(httpChallenges map[string]map[string][]byte) error {
s.storedData.HTTPChallenges = httpChallenges
// 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
}
5 changes: 3 additions & 2 deletions provider/acme/store.go
Expand Up @@ -13,6 +13,7 @@ type Store interface {
SaveAccount(*Account) error
GetCertificates() ([]*Certificate, error)
SaveCertificates([]*Certificate) error
GetHTTPChallenges() (map[string]map[string][]byte, error)
SaveHTTPChallenges(map[string]map[string][]byte) error
GetHTTPChallengeToken(token, domain string) ([]byte, error)
SetHTTPChallengeToken(token, domain string, keyAuth []byte) error
RemoveHTTPChallengeToken(token, domain string) error
}

0 comments on commit f173ff0

Please sign in to comment.