Fix acme account deletion without provider change
This commit is contained in:
parent
91cafd1752
commit
838dd8c19f
3 changed files with 109 additions and 2 deletions
18
acme/acme.go
18
acme/acme.go
|
@ -9,6 +9,7 @@ import (
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -183,7 +184,8 @@ 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
|
// 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) {
|
if account != nil && account.Registration != nil && !isAccountMatchingCaServer(account.Registration.URI, a.CAServer) {
|
||||||
|
log.Info("Account URI does not match the current CAServer. The account will be reset")
|
||||||
account.reset()
|
account.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +232,20 @@ func (a *ACME) leadershipListener(elected bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAccountMatchingCaServer(accountURI string, serverURI string) bool {
|
||||||
|
aru, err := url.Parse(accountURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Unable to parse account.Registration URL : %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cau, err := url.Parse(serverURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Unable to parse CAServer URL : %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return cau.Hostname() == aru.Hostname()
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
domain := types.CanonicalDomain(clientHello.ServerName)
|
domain := types.CanonicalDomain(clientHello.ServerName)
|
||||||
account := a.store.Get().(*Account)
|
account := a.store.Get().(*Account)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
fmtlog "log"
|
fmtlog "log"
|
||||||
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -130,7 +131,8 @@ func (p *Provider) Init(_ types.Constraints) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Account if caServer changed, thus registration URI can be updated
|
// 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) {
|
if p.account != nil && p.account.Registration != nil && !isAccountMatchingCaServer(p.account.Registration.URI, p.CAServer) {
|
||||||
|
log.Info("Account URI does not match the current CAServer. The account will be reset")
|
||||||
p.account = nil
|
p.account = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +144,20 @@ func (p *Provider) Init(_ types.Constraints) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAccountMatchingCaServer(accountURI string, serverURI string) bool {
|
||||||
|
aru, err := url.Parse(accountURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Unable to parse account.Registration URL : %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
cau, err := url.Parse(serverURI)
|
||||||
|
if err != nil {
|
||||||
|
log.Infof("Unable to parse CAServer URL : %v", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return cau.Hostname() == aru.Hostname()
|
||||||
|
}
|
||||||
|
|
||||||
// Provide allows the file provider to provide configurations to traefik
|
// Provide allows the file provider to provide configurations to traefik
|
||||||
// using the given Configuration channel.
|
// using the given Configuration channel.
|
||||||
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
|
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool) error {
|
||||||
|
|
|
@ -429,3 +429,78 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsAccountMatchingCaServer(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
accountURI string
|
||||||
|
serverURI string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "acme staging with matching account",
|
||||||
|
accountURI: "https://acme-staging-v02.api.letsencrypt.org/acme/acct/1234567",
|
||||||
|
serverURI: "https://acme-staging-v02.api.letsencrypt.org/acme/directory",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "acme production with matching account",
|
||||||
|
accountURI: "https://acme-v02.api.letsencrypt.org/acme/acct/1234567",
|
||||||
|
serverURI: "https://acme-v02.api.letsencrypt.org/acme/directory",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "http only acme with matching account",
|
||||||
|
accountURI: "http://acme.api.letsencrypt.org/acme/acct/1234567",
|
||||||
|
serverURI: "http://acme.api.letsencrypt.org/acme/directory",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "different subdomains for account and server",
|
||||||
|
accountURI: "https://test1.example.org/acme/acct/1234567",
|
||||||
|
serverURI: "https://test2.example.org/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "different domains for account and server",
|
||||||
|
accountURI: "https://test.example1.org/acme/acct/1234567",
|
||||||
|
serverURI: "https://test.example2.org/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "different tld for account and server",
|
||||||
|
accountURI: "https://test.example.com/acme/acct/1234567",
|
||||||
|
serverURI: "https://test.example.org/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "malformed account url",
|
||||||
|
accountURI: "//|\\/test.example.com/acme/acct/1234567",
|
||||||
|
serverURI: "https://test.example.com/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "malformed server url",
|
||||||
|
accountURI: "https://test.example.com/acme/acct/1234567",
|
||||||
|
serverURI: "//|\\/test.example.com/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "malformed server and account url",
|
||||||
|
accountURI: "//|\\/test.example.com/acme/acct/1234567",
|
||||||
|
serverURI: "//|\\/test.example.com/acme/directory",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
result := isAccountMatchingCaServer(test.accountURI, test.serverURI)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue