Improve ACME account registration URI management

This commit is contained in:
NicoMen 2018-05-28 14:40:03 +02:00 committed by Traefiker Bot
parent 2d946d7ee7
commit 3f5772c62a
6 changed files with 44 additions and 24 deletions

View file

@ -8,12 +8,14 @@ import (
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"reflect" "reflect"
"regexp"
"sort" "sort"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/types" "github.com/containous/traefik/types"
acme "github.com/xenolf/lego/acmev2" acme "github.com/xenolf/lego/acmev2"
) )
@ -42,6 +44,11 @@ func (a *Account) Init() error {
return err return err
} }
err = a.RemoveAccountV1Values()
if err != nil {
log.Errorf("Unable to remove ACME Account V1 values during account initialization: %v", err)
}
for _, cert := range a.ChallengeCerts { for _, cert := range a.ChallengeCerts {
if cert.certificate == nil { if cert.certificate == nil {
certificate, err := tls.X509KeyPair(cert.Certificate, cert.PrivateKey) certificate, err := tls.X509KeyPair(cert.Certificate, cert.PrivateKey)
@ -103,6 +110,29 @@ func (a *Account) GetPrivateKey() crypto.PrivateKey {
return nil return nil
} }
// RemoveAccountV1Values removes ACME account V1 values
func (a *Account) RemoveAccountV1Values() error {
// Check if ACME Account is in ACME V1 format
if a.Registration != nil {
isOldRegistration, err := regexp.MatchString(acmeprovider.RegistrationURLPathV1Regexp, a.Registration.URI)
if err != nil {
return err
}
if isOldRegistration {
a.reset()
}
}
return nil
}
func (a *Account) reset() {
log.Debug("Reset ACME account object.")
a.Email = ""
a.Registration = nil
a.PrivateKey = nil
}
// Certificate is used to store certificate info // Certificate is used to store certificate info
type Certificate struct { type Certificate struct {
Domain string Domain string

View file

@ -178,6 +178,10 @@ func (a *ACME) leadershipListener(elected bool) error {
account := object.(*Account) account := object.(*Account)
account.Init() account.Init()
// Reset Account values if caServer changed, thus registration URI can be updated
if account != nil && account.Registration != nil && !strings.HasPrefix(account.Registration.URI, a.CAServer) {
account.reset()
}
var needRegister bool var needRegister bool
if account == nil || len(account.Email) == 0 { if account == nil || len(account.Email) == 0 {

View file

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"os" "os"
"regexp"
"github.com/containous/traefik/log" "github.com/containous/traefik/log"
"github.com/containous/traefik/provider/acme" "github.com/containous/traefik/provider/acme"
@ -51,24 +50,6 @@ func (s *LocalStore) Get() (*Account, error) {
return account, nil return account, nil
} }
// RemoveAccountV1Values removes ACME account V1 values
func RemoveAccountV1Values(account *Account) error {
// Check if ACME Account is in ACME V1 format
if account != nil && account.Registration != nil {
isOldRegistration, err := regexp.MatchString(acme.RegistrationURLPathV1Regexp, account.Registration.URI)
if err != nil {
return err
}
if isOldRegistration {
account.Email = ""
account.Registration = nil
account.PrivateKey = nil
}
}
return nil
}
// ConvertToNewFormat converts old acme.json format to the new one and store the result into the file (used for the backward compatibility) // ConvertToNewFormat converts old acme.json format to the new one and store the result into the file (used for the backward compatibility)
func ConvertToNewFormat(fileName string) { func ConvertToNewFormat(fileName string) {
localStore := acme.NewLocalStore(fileName) localStore := acme.NewLocalStore(fileName)
@ -99,13 +80,13 @@ func ConvertToNewFormat(fileName string) {
if account != nil && len(account.Email) > 0 { if account != nil && len(account.Email) > 0 {
err = backupACMEFile(fileName, account) err = backupACMEFile(fileName, account)
if err != nil { if err != nil {
log.Errorf("Unable to create a backup for the V1 formatted ACME file: %s", err.Error()) log.Errorf("Unable to create a backup for the V1 formatted ACME file: %v", err)
return return
} }
err = RemoveAccountV1Values(account) err = account.RemoveAccountV1Values()
if err != nil { if err != nil {
log.Errorf("Unable to remove ACME Account V1 values: %s", err.Error()) log.Errorf("Unable to remove ACME Account V1 values during format conversion: %v", err)
return return
} }

View file

@ -140,7 +140,7 @@ func migrateACMEData(fileName string) (*acme.Account, error) {
return nil, err return nil, err
} }
err = acme.RemoveAccountV1Values(account) err = account.RemoveAccountV1Values()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -60,6 +60,7 @@ func (s *LocalStore) get() (*StoredData, error) {
return nil, err return nil, err
} }
if isOldRegistration { if isOldRegistration {
log.Debug("Reset ACME account.")
s.storedData.Account = nil s.storedData.Account = nil
s.SaveDataChan <- s.storedData s.SaveDataChan <- s.storedData
} }

View file

@ -114,6 +114,11 @@ func (p *Provider) init() error {
return fmt.Errorf("unable to get ACME account : %v", err) return fmt.Errorf("unable to get ACME account : %v", err)
} }
// Reset Account if caServer changed, thus registration URI can be updated
if p.account != nil && p.account.Registration != nil && !strings.HasPrefix(p.account.Registration.URI, p.CAServer) {
p.account = nil
}
p.certificates, err = p.Store.GetCertificates() p.certificates, err = p.Store.GetCertificates()
if err != nil { if err != nil {
return fmt.Errorf("unable to get ACME certificates : %v", err) return fmt.Errorf("unable to get ACME certificates : %v", err)
@ -315,7 +320,6 @@ func (p *Provider) getClient() (*acme.Client, error) {
} }
p.client = client p.client = client
} }
return p.client, nil return p.client, nil
} }