Delete TLS-SNI-01 challenge from ACME
This commit is contained in:
parent
d3edccb839
commit
c4529820f2
8 changed files with 61 additions and 230 deletions
11
acme/acme.go
11
acme/acme.go
|
@ -36,6 +36,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ACME allows to connect to lets encrypt and retrieve certs
|
// ACME allows to connect to lets encrypt and retrieve certs
|
||||||
|
// Deprecated Please use provider/acme/Provider
|
||||||
type ACME struct {
|
type ACME struct {
|
||||||
Email string `description:"Email address used for registration"`
|
Email string `description:"Email address used for registration"`
|
||||||
Domains []types.Domain `description:"SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='main.net,san1.net,san2.net'"`
|
Domains []types.Domain `description:"SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='main.net,san1.net,san2.net'"`
|
||||||
|
@ -53,7 +54,6 @@ type ACME struct {
|
||||||
client *acme.Client
|
client *acme.Client
|
||||||
defaultCertificate *tls.Certificate
|
defaultCertificate *tls.Certificate
|
||||||
store cluster.Store
|
store cluster.Store
|
||||||
challengeTLSProvider *challengeTLSProvider
|
|
||||||
challengeHTTPProvider *challengeHTTPProvider
|
challengeHTTPProvider *challengeHTTPProvider
|
||||||
checkOnDemandDomain func(domain string) bool
|
checkOnDemandDomain func(domain string) bool
|
||||||
jobs *channels.InfiniteChannel
|
jobs *channels.InfiniteChannel
|
||||||
|
@ -159,7 +159,6 @@ func (a *ACME) CreateClusterConfig(leadership *cluster.Leadership, tlsConfig *tl
|
||||||
}
|
}
|
||||||
|
|
||||||
a.store = datastore
|
a.store = datastore
|
||||||
a.challengeTLSProvider = &challengeTLSProvider{store: a.store}
|
|
||||||
|
|
||||||
ticker := time.NewTicker(24 * time.Hour)
|
ticker := time.NewTicker(24 * time.Hour)
|
||||||
leadership.Pool.AddGoCtx(func(ctx context.Context) {
|
leadership.Pool.AddGoCtx(func(ctx context.Context) {
|
||||||
|
@ -249,10 +248,6 @@ func (a *ACME) getCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificat
|
||||||
return providedCertificate, nil
|
return providedCertificate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if challengeCert, ok := a.challengeTLSProvider.getCertificate(domain); ok {
|
|
||||||
log.Debugf("ACME got challenge %s", domain)
|
|
||||||
return challengeCert, nil
|
|
||||||
}
|
|
||||||
if domainCert, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
|
if domainCert, ok := account.DomainsCertificate.getCertificateForDomain(domain); ok {
|
||||||
log.Debugf("ACME got domain cert %s", domain)
|
log.Debugf("ACME got domain cert %s", domain)
|
||||||
return domainCert.tlsCert, nil
|
return domainCert.tlsCert, nil
|
||||||
|
@ -431,9 +426,7 @@ func (a *ACME) buildACMEClient(account *Account) (*acme.Client, error) {
|
||||||
a.challengeHTTPProvider = &challengeHTTPProvider{store: a.store}
|
a.challengeHTTPProvider = &challengeHTTPProvider{store: a.store}
|
||||||
err = client.SetChallengeProvider(acme.HTTP01, a.challengeHTTPProvider)
|
err = client.SetChallengeProvider(acme.HTTP01, a.challengeHTTPProvider)
|
||||||
} else {
|
} else {
|
||||||
log.Debug("Using TLS Challenge provider.")
|
return nil, errors.New("ACME challenge not specified, please select HTTP or DNS Challenge")
|
||||||
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
|
|
||||||
err = client.SetChallengeProvider(acme.TLSSNI01, a.challengeTLSProvider)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
package acme
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cenk/backoff"
|
|
||||||
"github.com/containous/traefik/cluster"
|
|
||||||
"github.com/containous/traefik/log"
|
|
||||||
"github.com/containous/traefik/safe"
|
|
||||||
"github.com/containous/traefik/tls/generate"
|
|
||||||
"github.com/xenolf/lego/acme"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ acme.ChallengeProviderTimeout = (*challengeTLSProvider)(nil)
|
|
||||||
|
|
||||||
type challengeTLSProvider struct {
|
|
||||||
store cluster.Store
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *challengeTLSProvider) getCertificate(domain string) (cert *tls.Certificate, exists bool) {
|
|
||||||
log.Debugf("Looking for an existing ACME challenge for %s...", domain)
|
|
||||||
if !strings.HasSuffix(domain, ".acme.invalid") {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
c.lock.RLock()
|
|
||||||
defer c.lock.RUnlock()
|
|
||||||
account := c.store.Get().(*Account)
|
|
||||||
if account.ChallengeCerts == nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
account.Init()
|
|
||||||
var result *tls.Certificate
|
|
||||||
operation := func() error {
|
|
||||||
for _, cert := range account.ChallengeCerts {
|
|
||||||
for _, dns := range cert.certificate.Leaf.DNSNames {
|
|
||||||
if domain == dns {
|
|
||||||
result = cert.certificate
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("cannot find challenge cert for domain %s", domain)
|
|
||||||
}
|
|
||||||
notify := func(err error, time time.Duration) {
|
|
||||||
log.Errorf("Error getting cert: %v, retrying in %s", err, time)
|
|
||||||
}
|
|
||||||
ebo := backoff.NewExponentialBackOff()
|
|
||||||
ebo.MaxElapsedTime = 60 * time.Second
|
|
||||||
err := backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Error getting cert: %v", err)
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return result, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *challengeTLSProvider) Present(domain, token, keyAuth string) error {
|
|
||||||
log.Debugf("Challenge Present %s", domain)
|
|
||||||
cert, _, err := tlsSNI01ChallengeCert(keyAuth)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
transaction, object, err := c.store.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
account := object.(*Account)
|
|
||||||
if account.ChallengeCerts == nil {
|
|
||||||
account.ChallengeCerts = map[string]*ChallengeCert{}
|
|
||||||
}
|
|
||||||
account.ChallengeCerts[domain] = &cert
|
|
||||||
return transaction.Commit(account)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *challengeTLSProvider) CleanUp(domain, token, keyAuth string) error {
|
|
||||||
log.Debugf("Challenge CleanUp %s", domain)
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
transaction, object, err := c.store.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
account := object.(*Account)
|
|
||||||
delete(account.ChallengeCerts, domain)
|
|
||||||
return transaction.Commit(account)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *challengeTLSProvider) Timeout() (timeout, interval time.Duration) {
|
|
||||||
return 60 * time.Second, 5 * time.Second
|
|
||||||
}
|
|
||||||
|
|
||||||
// tlsSNI01ChallengeCert returns a certificate and target domain for the `tls-sni-01` challenge
|
|
||||||
func tlsSNI01ChallengeCert(keyAuth string) (ChallengeCert, string, error) {
|
|
||||||
// generate a new RSA key for the certificates
|
|
||||||
var tempPrivKey crypto.PrivateKey
|
|
||||||
tempPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return ChallengeCert{}, "", err
|
|
||||||
}
|
|
||||||
rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
|
|
||||||
rsaPrivPEM := pemEncode(rsaPrivKey)
|
|
||||||
|
|
||||||
zBytes := sha256.Sum256([]byte(keyAuth))
|
|
||||||
z := hex.EncodeToString(zBytes[:sha256.Size])
|
|
||||||
domain := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:])
|
|
||||||
tempCertPEM, err := generate.PemCert(rsaPrivKey, domain, time.Time{})
|
|
||||||
if err != nil {
|
|
||||||
return ChallengeCert{}, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
certificate, err := tls.X509KeyPair(tempCertPEM, rsaPrivPEM)
|
|
||||||
if err != nil {
|
|
||||||
return ChallengeCert{}, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ChallengeCert{Certificate: tempCertPEM, PrivateKey: rsaPrivPEM, certificate: &certificate}, domain, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func pemEncode(data interface{}) []byte {
|
|
||||||
var pemBlock *pem.Block
|
|
||||||
switch key := data.(type) {
|
|
||||||
case *ecdsa.PrivateKey:
|
|
||||||
keyBytes, _ := x509.MarshalECPrivateKey(key)
|
|
||||||
pemBlock = &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}
|
|
||||||
case *rsa.PrivateKey:
|
|
||||||
pemBlock = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}
|
|
||||||
case *x509.CertificateRequest:
|
|
||||||
pemBlock = &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: key.Raw}
|
|
||||||
case []byte:
|
|
||||||
pemBlock = &pem.Block{Type: "CERTIFICATE", Bytes: data.([]byte)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pem.EncodeToMemory(pemBlock)
|
|
||||||
}
|
|
|
@ -38,23 +38,20 @@ storage = "acme.json"
|
||||||
# or `storage = "traefik/acme/account"` if using KV store.
|
# or `storage = "traefik/acme/account"` if using KV store.
|
||||||
|
|
||||||
# Entrypoint to proxy acme apply certificates to.
|
# Entrypoint to proxy acme apply certificates to.
|
||||||
# WARNING, if the TLS-SNI-01 challenge is used, it must point to an entrypoint on port 443
|
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
entryPoint = "https"
|
entryPoint = "https"
|
||||||
|
|
||||||
# Use a DNS-01 acme challenge rather than TLS-SNI-01 challenge
|
# Deprecated, replaced by [acme.dnsChallenge].
|
||||||
#
|
#
|
||||||
# Optional (Deprecated, replaced by [acme.dnsChallenge])
|
# Optional.
|
||||||
#
|
#
|
||||||
# dnsProvider = "digitalocean"
|
# dnsProvider = "digitalocean"
|
||||||
|
|
||||||
# By default, the dnsProvider will verify the TXT DNS challenge record before letting ACME verify.
|
# Deprecated, replaced by [acme.dnsChallenge.delayBeforeCheck].
|
||||||
# If delayDontCheckDNS is greater than zero, avoid this & instead just wait so many seconds.
|
|
||||||
# Useful if internal networks block external DNS queries.
|
|
||||||
#
|
#
|
||||||
# Optional (Deprecated, replaced by [acme.dnsChallenge])
|
# Optional
|
||||||
# Default: 0
|
# Default: 0
|
||||||
#
|
#
|
||||||
# delayDontCheckDNS = 0
|
# delayDontCheckDNS = 0
|
||||||
|
@ -102,19 +99,19 @@ entryPoint = "https"
|
||||||
# [[acme.domains]]
|
# [[acme.domains]]
|
||||||
# main = "local4.com"
|
# main = "local4.com"
|
||||||
|
|
||||||
# Use a HTTP-01 acme challenge rather than TLS-SNI-01 challenge
|
# Use a HTTP-01 acme challenge.
|
||||||
#
|
#
|
||||||
# Optional but recommend
|
# Optional but recommend
|
||||||
#
|
#
|
||||||
[acme.httpChallenge]
|
[acme.httpChallenge]
|
||||||
|
|
||||||
# EntryPoint to use for the challenges.
|
# EntryPoint to use for the HTTP-01 challenges.
|
||||||
#
|
#
|
||||||
# Required
|
# Required
|
||||||
#
|
#
|
||||||
entryPoint = "http"
|
entryPoint = "http"
|
||||||
|
|
||||||
# Use a DNS-01 acme challenge rather than TLS-SNI-01 challenge
|
# Use a DNS-01 acme challenge rather than HTTP-01 challenge.
|
||||||
#
|
#
|
||||||
# Optional
|
# Optional
|
||||||
#
|
#
|
||||||
|
@ -137,11 +134,6 @@ entryPoint = "https"
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Even if `TLS-SNI-01` challenge is [disabled](https://community.letsencrypt.org/t/2018-01-11-update-regarding-acme-tls-sni-and-shared-hosting-infrastructure/50188) for the moment, it stays the _by default_ ACME Challenge in Træfik.
|
|
||||||
If `TLS-SNI-01` challenge is not re-enabled in the future, it we will be removed from Træfik.
|
|
||||||
|
|
||||||
!!! note
|
|
||||||
If `TLS-SNI-01` challenge is used, `acme.entryPoint` has to be reachable by Let's Encrypt through the port 443.
|
|
||||||
If `HTTP-01` challenge is used, `acme.httpChallenge.entryPoint` has to be defined and reachable by Let's Encrypt through the port 80.
|
If `HTTP-01` challenge is used, `acme.httpChallenge.entryPoint` has to be defined and reachable by Let's Encrypt through the port 80.
|
||||||
These are Let's Encrypt limitations as described on the [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72).
|
These are Let's Encrypt limitations as described on the [community forum](https://community.letsencrypt.org/t/support-for-ports-other-than-80-and-443/3419/72).
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ When you use Let's Encrypt, you need to store certificates, but not only.
|
||||||
When Træfik generates a new certificate, it configures a challenge and once Let's Encrypt will verify the ownership of the domain, it will ping back the challenge.
|
When Træfik generates a new certificate, it configures a challenge and once Let's Encrypt will verify the ownership of the domain, it will ping back the challenge.
|
||||||
If the challenge is not knowing by other Træfik instances, the validation will fail.
|
If the challenge is not knowing by other Træfik instances, the validation will fail.
|
||||||
|
|
||||||
For more information about challenge: [Automatic Certificate Management Environment (ACME)](https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#tls-with-server-name-indication-tls-sni)
|
For more information about challenge: [Automatic Certificate Management Environment (ACME)](https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http-challenge)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,9 @@ const (
|
||||||
|
|
||||||
// Wildcard domain to check
|
// Wildcard domain to check
|
||||||
wildcardDomain = "*.acme.wtf"
|
wildcardDomain = "*.acme.wtf"
|
||||||
|
|
||||||
|
// Traefik default certificate
|
||||||
|
traefikDefaultDomain = "TRAEFIK DEFAULT CERT"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
func (s *AcmeSuite) SetUpSuite(c *check.C) {
|
||||||
|
@ -82,6 +85,16 @@ func (s *AcmeSuite) TestACMEProviderOnHost(c *check.C) {
|
||||||
s.retrieveAcmeCertificate(c, testCase)
|
s.retrieveAcmeCertificate(c, testCase)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test ACME provider with certificate at start and no ACME challenge
|
||||||
|
func (s *AcmeSuite) TestACMEProviderOnHostWithNoACMEChallenge(c *check.C) {
|
||||||
|
testCase := AcmeTestCase{
|
||||||
|
traefikConfFilePath: "fixtures/acme/no_challenge_acme.toml",
|
||||||
|
onDemand: false,
|
||||||
|
domainToCheck: traefikDefaultDomain}
|
||||||
|
|
||||||
|
s.retrieveAcmeCertificate(c, testCase)
|
||||||
|
}
|
||||||
|
|
||||||
// Test OnDemand option with none provided certificate and challenge HTTP-01
|
// Test OnDemand option with none provided certificate and challenge HTTP-01
|
||||||
func (s *AcmeSuite) TestOnDemandRetrieveAcmeCertificateHTTP01(c *check.C) {
|
func (s *AcmeSuite) TestOnDemandRetrieveAcmeCertificateHTTP01(c *check.C) {
|
||||||
testCase := AcmeTestCase{
|
testCase := AcmeTestCase{
|
||||||
|
|
35
integration/fixtures/acme/no_challenge_acme.toml
Normal file
35
integration/fixtures/acme/no_challenge_acme.toml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
logLevel = "DEBUG"
|
||||||
|
|
||||||
|
defaultEntryPoints = ["http", "https"]
|
||||||
|
|
||||||
|
[api]
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":8081"
|
||||||
|
[entryPoints.https]
|
||||||
|
address = ":5001"
|
||||||
|
[entryPoints.https.tls]
|
||||||
|
|
||||||
|
|
||||||
|
[acme]
|
||||||
|
email = "test@traefik.io"
|
||||||
|
storage = "/dev/null"
|
||||||
|
entryPoint = "https"
|
||||||
|
OnHostRule = true
|
||||||
|
caServer = "http://{{.BoulderHost}}:4000/directory"
|
||||||
|
# No challenge defined
|
||||||
|
|
||||||
|
[file]
|
||||||
|
|
||||||
|
[backends]
|
||||||
|
[backends.backend]
|
||||||
|
[backends.backend.servers.server1]
|
||||||
|
url = "http://127.0.0.1:9010"
|
||||||
|
|
||||||
|
|
||||||
|
[frontends]
|
||||||
|
[frontends.frontend]
|
||||||
|
backend = "backend"
|
||||||
|
[frontends.frontend.routes.test]
|
||||||
|
rule = "Host:traefik.acme.wtf"
|
|
@ -1,11 +1,6 @@
|
||||||
package acme
|
package acme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -13,7 +8,6 @@ import (
|
||||||
"github.com/containous/flaeg"
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/safe"
|
"github.com/containous/traefik/safe"
|
||||||
tlsgenerate "github.com/containous/traefik/tls/generate"
|
|
||||||
"github.com/xenolf/lego/acme"
|
"github.com/xenolf/lego/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,30 +29,6 @@ func dnsOverrideDelay(delay flaeg.Duration) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentTLSChallenge(domain, keyAuth string) ([]byte, []byte, error) {
|
|
||||||
log.Debugf("TLS Challenge Present temp certificate for %s", domain)
|
|
||||||
|
|
||||||
var tempPrivKey crypto.PrivateKey
|
|
||||||
tempPrivKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
|
|
||||||
rsaPrivPEM := tlsgenerate.PemEncode(rsaPrivKey)
|
|
||||||
|
|
||||||
zBytes := sha256.Sum256([]byte(keyAuth))
|
|
||||||
z := hex.EncodeToString(zBytes[:sha256.Size])
|
|
||||||
domainCert := fmt.Sprintf("%s.%s.acme.invalid", z[:32], z[32:])
|
|
||||||
|
|
||||||
tempCertPEM, err := tlsgenerate.PemCert(rsaPrivKey, domainCert, time.Time{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tempCertPEM, rsaPrivPEM, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTokenValue(token, domain string, store Store) []byte {
|
func getTokenValue(token, domain string, store Store) []byte {
|
||||||
log.Debugf("Looking for an existing ACME challenge for token %v...", token)
|
log.Debugf("Looking for an existing ACME challenge for token %v...", token)
|
||||||
var result []byte
|
var result []byte
|
||||||
|
|
|
@ -323,12 +323,7 @@ func (p *Provider) getClient() (*acme.Client, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Debug("Using TLS Challenge provider.")
|
return nil, errors.New("ACME challenge not specified, please select HTTP or DNS Challenge")
|
||||||
client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
|
|
||||||
err = client.SetChallengeProvider(acme.TLSSNI01, p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p.client = client
|
p.client = client
|
||||||
}
|
}
|
||||||
|
@ -338,29 +333,12 @@ func (p *Provider) getClient() (*acme.Client, error) {
|
||||||
|
|
||||||
// Present presents a challenge to obtain new ACME certificate
|
// Present presents a challenge to obtain new ACME certificate
|
||||||
func (p *Provider) Present(domain, token, keyAuth string) error {
|
func (p *Provider) Present(domain, token, keyAuth string) error {
|
||||||
if p.HTTPChallenge != nil {
|
return presentHTTPChallenge(domain, token, keyAuth, p.Store)
|
||||||
return presentHTTPChallenge(domain, token, keyAuth, p.Store)
|
|
||||||
} else if p.DNSChallenge == nil {
|
|
||||||
log.Debugf("TLS Challenge CleanUp temp certificate for %s", domain)
|
|
||||||
tempCertPEM, rsaPrivPEM, err := presentTLSChallenge(domain, keyAuth)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.addCertificateForDomain(types.Domain{Main: "TEMP-" + domain}, tempCertPEM, rsaPrivPEM)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUp cleans the challenges when certificate is obtained
|
// CleanUp cleans the challenges when certificate is obtained
|
||||||
func (p *Provider) CleanUp(domain, token, keyAuth string) error {
|
func (p *Provider) CleanUp(domain, token, keyAuth string) error {
|
||||||
if p.HTTPChallenge != nil {
|
return cleanUpHTTPChallenge(domain, token, p.Store)
|
||||||
return cleanUpHTTPChallenge(domain, token, p.Store)
|
|
||||||
} else if p.DNSChallenge == nil {
|
|
||||||
log.Debugf("TLS Challenge CleanUp temp certificate for %s", domain)
|
|
||||||
p.deleteCertificateForDomain(types.Domain{Main: "TEMP-" + domain})
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide allows the file provider to provide configurations to traefik
|
// Provide allows the file provider to provide configurations to traefik
|
||||||
|
|
Loading…
Reference in a new issue