Generate wildcard certificate with SANs in ACME
This commit is contained in:
parent
8168d2fdc1
commit
7109910f46
5 changed files with 271 additions and 96 deletions
88
acme/acme.go
88
acme/acme.go
|
@ -46,9 +46,9 @@ type ACME struct {
|
|||
OnHostRule bool `description:"Enable certificate generation on frontends Host rules."`
|
||||
CAServer string `description:"CA server to use."`
|
||||
EntryPoint string `description:"Entrypoint to proxy acme challenge to."`
|
||||
DNSChallenge *acmeprovider.DNSChallenge `description:"Activate DNS-02 Challenge"`
|
||||
DNSChallenge *acmeprovider.DNSChallenge `description:"Activate DNS-01 Challenge"`
|
||||
HTTPChallenge *acmeprovider.HTTPChallenge `description:"Activate HTTP-01 Challenge"`
|
||||
DNSProvider string `description:"Activate DNS-02 Challenge (Deprecated)"` // deprecated
|
||||
DNSProvider string `description:"Activate DNS-01 Challenge (Deprecated)"` // deprecated
|
||||
DelayDontCheckDNS flaeg.Duration `description:"Assume DNS propagates after a delay in seconds rather than finding and querying nameservers."` // deprecated
|
||||
ACMELogging bool `description:"Enable debug logging of ACME actions."`
|
||||
client *acme.Client
|
||||
|
@ -62,20 +62,6 @@ type ACME struct {
|
|||
}
|
||||
|
||||
func (a *ACME) init() error {
|
||||
// FIXME temporary fix, waiting for https://github.com/xenolf/lego/pull/478
|
||||
acme.HTTPClient = http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 15 * time.Second,
|
||||
ResponseHeaderTimeout: 15 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
if a.ACMELogging {
|
||||
acme.Logger = fmtlog.New(os.Stderr, "legolog: ", fmtlog.LstdFlags)
|
||||
} else {
|
||||
|
@ -651,6 +637,7 @@ func (a *ACME) runJobs() {
|
|||
|
||||
// getValidDomains checks if given domain is allowed to generate a ACME certificate and return it
|
||||
func (a *ACME) getValidDomains(domains []string, wildcardAllowed bool) ([]string, error) {
|
||||
// Check if the domains array is empty or contains only one empty value
|
||||
if len(domains) == 0 || (len(domains) == 1 && len(domains[0]) == 0) {
|
||||
return nil, errors.New("unable to generate a certificate when no domain is given")
|
||||
}
|
||||
|
@ -663,15 +650,14 @@ func (a *ACME) getValidDomains(domains []string, wildcardAllowed bool) ([]string
|
|||
if a.DNSChallenge == nil && len(a.DNSProvider) == 0 {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME needs a DNSChallenge", strings.Join(domains, ","))
|
||||
}
|
||||
|
||||
if len(domains) > 1 {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : SANs are not allowed", strings.Join(domains, ","))
|
||||
if strings.HasPrefix(domains[0], "*.*") {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ","))
|
||||
}
|
||||
} else {
|
||||
for _, san := range domains[1:] {
|
||||
if strings.HasPrefix(san, "*") {
|
||||
return nil, fmt.Errorf("unable to generate a certificate in ACME provider for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ","))
|
||||
}
|
||||
}
|
||||
for _, san := range domains[1:] {
|
||||
if strings.HasPrefix(san, "*") {
|
||||
return nil, fmt.Errorf("unable to generate a certificate for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ","))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,31 +696,37 @@ func (a *ACME) deleteUnnecessaryDomains() {
|
|||
keepDomain = false
|
||||
}
|
||||
break
|
||||
} else if strings.HasPrefix(domain.Main, "*") && domain.SANs == nil {
|
||||
// Check if domains can be validated by the wildcard domain
|
||||
|
||||
var newDomainsToCheck []string
|
||||
|
||||
// Check if domains can be validated by the wildcard domain
|
||||
domainsMap := make(map[string]*tls.Certificate)
|
||||
domainsMap[domain.Main] = &tls.Certificate{}
|
||||
|
||||
for _, domainProcessed := range domainToCheck.ToStrArray() {
|
||||
if isDomainAlreadyChecked(domainProcessed, domainsMap) {
|
||||
log.Warnf("Domain %q will not be processed by ACME because it is validated by the wildcard %q", domainProcessed, domain.Main)
|
||||
continue
|
||||
}
|
||||
newDomainsToCheck = append(newDomainsToCheck, domainProcessed)
|
||||
}
|
||||
|
||||
// Delete the domain if both Main and SANs can be validated by the wildcard domain
|
||||
// otherwise keep the unchecked values
|
||||
if newDomainsToCheck == nil {
|
||||
keepDomain = false
|
||||
break
|
||||
}
|
||||
domainToCheck.Set(newDomainsToCheck)
|
||||
}
|
||||
|
||||
var newDomainsToCheck []string
|
||||
|
||||
// Check if domains can be validated by the wildcard domain
|
||||
domainsMap := make(map[string]*tls.Certificate)
|
||||
domainsMap[domain.Main] = &tls.Certificate{}
|
||||
if len(domain.SANs) > 0 {
|
||||
domainsMap[strings.Join(domain.SANs, ",")] = &tls.Certificate{}
|
||||
}
|
||||
|
||||
for _, domainProcessed := range domainToCheck.ToStrArray() {
|
||||
if idxDomain < idxDomainToCheck && isDomainAlreadyChecked(domainProcessed, domainsMap) {
|
||||
// The domain is duplicated in a CN
|
||||
log.Warnf("Domain %q is duplicated in the configuration or validated by the domain %v. It will be processed once.", domainProcessed, domain)
|
||||
continue
|
||||
} else if domain.Main != domainProcessed && strings.HasPrefix(domain.Main, "*") && types.MatchDomain(domainProcessed, domain.Main) {
|
||||
// Check if a wildcard can validate the domain
|
||||
log.Warnf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main)
|
||||
continue
|
||||
}
|
||||
newDomainsToCheck = append(newDomainsToCheck, domainProcessed)
|
||||
}
|
||||
|
||||
// Delete the domain if both Main and SANs can be validated by the wildcard domain
|
||||
// otherwise keep the unchecked values
|
||||
if newDomainsToCheck == nil {
|
||||
keepDomain = false
|
||||
break
|
||||
}
|
||||
domainToCheck.Set(newDomainsToCheck)
|
||||
}
|
||||
|
||||
if keepDomain {
|
||||
|
|
|
@ -417,11 +417,27 @@ func TestAcme_getValidDomain(t *testing.T) {
|
|||
expectedDomains: nil,
|
||||
},
|
||||
{
|
||||
desc: "unexpected SANs",
|
||||
domains: []string{"*.traefik.wtf", "foo.traefik.wtf"},
|
||||
desc: "unauthorized wildcard with SAN",
|
||||
domains: []string{"*.*.traefik.wtf", "foo.traefik.wtf"},
|
||||
dnsChallenge: &acmeprovider.DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "unable to generate a wildcard certificate for domain \"*.traefik.wtf,foo.traefik.wtf\" : SANs are not allowed",
|
||||
expectedErr: "unable to generate a wildcard certificate for domain \"*.*.traefik.wtf,foo.traefik.wtf\" : ACME does not allow '*.*' wildcard domain",
|
||||
expectedDomains: nil,
|
||||
},
|
||||
{
|
||||
desc: "wildcard with SANs",
|
||||
domains: []string{"*.traefik.wtf", "traefik.wtf"},
|
||||
dnsChallenge: &acmeprovider.DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "",
|
||||
expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"},
|
||||
},
|
||||
{
|
||||
desc: "unexpected SANs",
|
||||
domains: []string{"*.traefik.wtf", "*.acme.wtf"},
|
||||
dnsChallenge: &acmeprovider.DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "unable to generate a certificate for domains \"*.traefik.wtf,*.acme.wtf\": SANs can not be a wildcard domain",
|
||||
expectedDomains: nil,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ entryPoint = "https"
|
|||
#
|
||||
entryPoint = "http"
|
||||
|
||||
# Use a DNS-01/DNS-02 acme challenge rather than HTTP-01 challenge.
|
||||
# Use a DNS-01/DNS-01 acme challenge rather than HTTP-01 challenge.
|
||||
# Note : Mandatory for wildcard certificates generation.
|
||||
#
|
||||
# Optional
|
||||
|
@ -264,7 +264,7 @@ defaultEntryPoints = ["http", "https"]
|
|||
|
||||
### `dnsChallenge`
|
||||
|
||||
Use `DNS-01/DNS-02` challenge to generate/renew ACME certificates.
|
||||
Use `DNS-01/DNS-01` challenge to generate/renew ACME certificates.
|
||||
|
||||
```toml
|
||||
[acme]
|
||||
|
@ -276,7 +276,7 @@ Use `DNS-01/DNS-02` challenge to generate/renew ACME certificates.
|
|||
```
|
||||
|
||||
!!! note
|
||||
ACME wildcard certificates can only be generated thanks to a `DNS-02` challenge.
|
||||
ACME wildcard certificates can only be generated thanks to a `DNS-01` challenge.
|
||||
|
||||
#### `provider`
|
||||
|
||||
|
@ -397,14 +397,18 @@ CA server to use.
|
|||
main = "local3.com"
|
||||
[[acme.domains]]
|
||||
main = "*.local4.com"
|
||||
sans = ["local4.com", "test1.test1.local4.com"]
|
||||
# ...
|
||||
```
|
||||
|
||||
#### Wildcard domains
|
||||
|
||||
Wildcard domain has to be defined as a main domain **with no SANs** (alternative domains).
|
||||
Wildcard domain has to be defined as a main domain.
|
||||
All domains must have A/AAAA records pointing to Træfik.
|
||||
|
||||
Due to ACME limitation, it's not possible to define a wildcard as a SAN (alternative domains).
|
||||
It's neither possible to define a wildcard on a wildcard domain (for example `*.*.local.com`).
|
||||
|
||||
!!! warning
|
||||
Note that Let's Encrypt has [rate limiting](https://letsencrypt.org/docs/rate-limits).
|
||||
|
||||
|
@ -435,9 +439,9 @@ Each domain & SANs will lead to a certificate request.
|
|||
[ACME V2](https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579) allows wildcard certificate support.
|
||||
However, this feature needs a specific configuration.
|
||||
|
||||
### DNS-02 Challenge
|
||||
### DNS-01 Challenge
|
||||
|
||||
As described in [Let's Encrypt post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605), wildcard certificates can only be generated through a `DNS-02`Challenge.
|
||||
As described in [Let's Encrypt post](https://community.letsencrypt.org/t/staging-endpoint-for-acme-v2/49605), wildcard certificates can only be generated through a `DNS-01` Challenge.
|
||||
This challenge is linked to the Træfik option `acme.dnsChallenge`.
|
||||
|
||||
```toml
|
||||
|
@ -454,16 +458,88 @@ For more information about this option, please refer to the [dnsChallenge sectio
|
|||
### Wildcard domain
|
||||
|
||||
Wildcard domains can currently be provided only by to the `acme.domains` option.
|
||||
Theses domains can not have SANs.
|
||||
|
||||
```toml
|
||||
[acme]
|
||||
# ...
|
||||
[[acme.domains]]
|
||||
main = "*local1.com"
|
||||
main = "*.local1.com"
|
||||
sans = ["local1.com"]
|
||||
[[acme.domains]]
|
||||
main = "*.local2.com"
|
||||
# ...
|
||||
```
|
||||
|
||||
For more information about this option, please refer to the [domains section](/configuration/acme/#domains).
|
||||
|
||||
### Limitations
|
||||
|
||||
Let's Encrypt wildcard support have some limitations to take into account :
|
||||
|
||||
- Wildcard domain can not be a SAN (alternative domain),
|
||||
- Wildcard domain on a wildcard domain is forbidden (for example `*.*.local.com`),
|
||||
- A DNS-01 Challenge is executed for each domain (CN and SANs), DNS provider can not manage correctly this behavior as explained in the [DNS provider support section](/configuration/acme/#dns-provider-support)
|
||||
|
||||
|
||||
### DNS provider support
|
||||
|
||||
All DNS providers allow creating ACME wildcard certificates.
|
||||
However, many troubles can appear for wildcard domains with SANs.
|
||||
|
||||
If a wildcard domain is defined with it root domain as SAN, as described below, 2 DNS-01 Challenges will be executed.
|
||||
|
||||
```toml
|
||||
[acme]
|
||||
# ...
|
||||
[[acme.domains]]
|
||||
main = "*.local1.com"
|
||||
sans = ["local1.com"]
|
||||
# ...
|
||||
```
|
||||
|
||||
When a DNS-01 Challenge is done, Let's Encrypt checks if a TXT record is created with a given name and a given value.
|
||||
When a certificate is generated for a wildcard domain is defined with it root domain as SAN, the requested TXT record name for both the wildcard domain and the root domain is the same.
|
||||
|
||||
The [DNS RFC](https://community.letsencrypt.org/t/wildcard-issuance-two-txt-records-for-the-same-name/54528/2) allows this behavior.
|
||||
But all DNS providers keep TXT records values in a cache with a TTL.
|
||||
In function of the parameters given by the Træfik ACME client library ([LEGO](https://github.com/xenolf/lego)), the TXT record TTL can be superior to challenge Timeout.
|
||||
In that event, the DNS-01 Challenge will not work correctly.
|
||||
|
||||
[LEGO](https://github.com/xenolf/lego) will involve in the way to be adapted to all of DNS providers.
|
||||
Meanwhile, the table described below contains all the DNS providers supported by Træfik and indicates if they allow generating certificates for a wildcard domain and its root domain.
|
||||
Do not hesitate to complete it.
|
||||
|
||||
| Provider Name | Provider code | Wildcard and Root Domain Support |
|
||||
|--------------------------------------------------------|----------------|----------------------------------|
|
||||
| [Auroradns](https://www.pcextreme.com/aurora/dns) | `auroradns` | Not tested yet |
|
||||
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | Not tested yet |
|
||||
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | Not tested yet |
|
||||
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | YES |
|
||||
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | Not tested yet |
|
||||
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | YES |
|
||||
| [DNSimple](https://dnsimple.com) | `dnsimple` | Not tested yet |
|
||||
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | Not tested yet |
|
||||
| [DNSPod](http://www.dnspod.net/) | `dnspod` | Not tested yet |
|
||||
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | Not tested yet |
|
||||
| [Dyn](https://dyn.com) | `dyn` | Not tested yet |
|
||||
| External Program | `exec` | Not tested yet |
|
||||
| [Exoscale](https://www.exoscale.ch) | `exoscale` | Not tested yet |
|
||||
| [Fast DNS](https://www.akamai.com/) | `fastdns` | Not tested yet |
|
||||
| [Gandi](https://www.gandi.net) | `gandi` | Not tested yet |
|
||||
| [Gandi V5](http://doc.livedns.gandi.net) | `gandiv5` | Not tested yet |
|
||||
| [Glesys](https://glesys.com/) | `glesys` | Not tested yet |
|
||||
| [GoDaddy](https://godaddy.com/domains) | `godaddy` | Not tested yet |
|
||||
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | YES |
|
||||
| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | Not tested yet |
|
||||
| [Linode](https://www.linode.com) | `linode` | Not tested yet |
|
||||
| manual | - | YES |
|
||||
| [Namecheap](https://www.namecheap.com) | `namecheap` | Not tested yet |
|
||||
| [name.com](https://www.name.com/) | `namedotcom` | Not tested yet |
|
||||
| [Ns1](https://ns1.com/) | `ns1` | Not tested yet |
|
||||
| [Open Telekom Cloud](https://cloud.telekom.de/en/) | `otc` | Not tested yet |
|
||||
| [OVH](https://www.ovh.com) | `ovh` | YES |
|
||||
| [PowerDNS](https://www.powerdns.com) | `pdns` | Not tested yet |
|
||||
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | Not tested yet |
|
||||
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | Not tested yet |
|
||||
| [Route 53](https://aws.amazon.com/route53/) | `route53` | YES |
|
||||
| [VULTR](https://www.vultr.com) | `vultr` | Not tested yet |
|
||||
|
|
|
@ -42,7 +42,7 @@ type Configuration struct {
|
|||
EntryPoint string `description:"EntryPoint to use."`
|
||||
OnHostRule bool `description:"Enable certificate generation on frontends Host rules."`
|
||||
OnDemand bool `description:"Enable on demand certificate generation. This will request a certificate from Let's Encrypt during the first TLS handshake for a hostname that does not yet have a certificate."` //deprecated
|
||||
DNSChallenge *DNSChallenge `description:"Activate DNS-02 Challenge"`
|
||||
DNSChallenge *DNSChallenge `description:"Activate DNS-01 Challenge"`
|
||||
HTTPChallenge *HTTPChallenge `description:"Activate HTTP-01 Challenge"`
|
||||
Domains []types.Domain `description:"CN and SANs (alternative domains) to each main domain using format: --acme.domains='main.com,san1.com,san2.com' --acme.domains='*.main.net'. No SANs for wildcards domain. Wildcard domains only accepted with DNSChallenge"`
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ type Certificate struct {
|
|||
|
||||
// DNSChallenge contains DNS challenge Configuration
|
||||
type DNSChallenge struct {
|
||||
Provider string `description:"Use a DNS-02 based challenge provider rather than HTTPS."`
|
||||
Provider string `description:"Use a DNS-01 based challenge provider rather than HTTPS."`
|
||||
DelayBeforeCheck flaeg.Duration `description:"Assume DNS propagates after a delay in seconds rather than finding and querying nameservers."`
|
||||
}
|
||||
|
||||
|
@ -565,16 +565,16 @@ func (p *Provider) getValidDomains(domain types.Domain, wildcardAllowed bool) ([
|
|||
if p.DNSChallenge == nil {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : ACME needs a DNSChallenge", strings.Join(domains, ","))
|
||||
}
|
||||
if len(domain.SANs) > 0 {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : SANs are not allowed", strings.Join(domains, ","))
|
||||
}
|
||||
} else {
|
||||
for _, san := range domain.SANs {
|
||||
if strings.HasPrefix(san, "*") {
|
||||
return nil, fmt.Errorf("unable to generate a certificate in ACME provider for domains %q: SANs can not be a wildcard domain", strings.Join(domains, ","))
|
||||
}
|
||||
if strings.HasPrefix(domain.Main, "*.*") {
|
||||
return nil, fmt.Errorf("unable to generate a wildcard certificate in ACME provider for domain %q : ACME does not allow '*.*' wildcard domain", strings.Join(domains, ","))
|
||||
}
|
||||
}
|
||||
for _, san := range domain.SANs {
|
||||
if strings.HasPrefix(san, "*") {
|
||||
return nil, fmt.Errorf("unable to generate a certificate in ACME provider for domains %q: SAN %q can not be a wildcard domain", strings.Join(domains, ","), san)
|
||||
}
|
||||
}
|
||||
|
||||
domains = fun.Map(types.CanonicalDomain, domains).([]string)
|
||||
return domains, nil
|
||||
}
|
||||
|
@ -610,26 +610,31 @@ func (p *Provider) deleteUnnecessaryDomains() {
|
|||
keepDomain = false
|
||||
}
|
||||
break
|
||||
} else if strings.HasPrefix(domain.Main, "*") && domain.SANs == nil {
|
||||
|
||||
// Check if domains can be validated by the wildcard domain
|
||||
var newDomainsToCheck []string
|
||||
for _, domainProcessed := range domainToCheck.ToStrArray() {
|
||||
if isDomainAlreadyChecked(domainProcessed, domain.ToStrArray()) {
|
||||
log.Warnf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main)
|
||||
continue
|
||||
}
|
||||
newDomainsToCheck = append(newDomainsToCheck, domainProcessed)
|
||||
}
|
||||
|
||||
// Delete the domain if both Main and SANs can be validated by the wildcard domain
|
||||
// otherwise keep the unchecked values
|
||||
if newDomainsToCheck == nil {
|
||||
keepDomain = false
|
||||
break
|
||||
}
|
||||
domainToCheck.Set(newDomainsToCheck)
|
||||
}
|
||||
|
||||
// Check if CN or SANS to check already exists
|
||||
// or can not be checked by a wildcard
|
||||
var newDomainsToCheck []string
|
||||
for _, domainProcessed := range domainToCheck.ToStrArray() {
|
||||
if idxDomain < idxDomainToCheck && isDomainAlreadyChecked(domainProcessed, domain.ToStrArray()) {
|
||||
// The domain is duplicated in a CN
|
||||
log.Warnf("Domain %q is duplicated in the configuration or validated by the domain %v. It will be processed once.", domainProcessed, domain)
|
||||
continue
|
||||
} else if domain.Main != domainProcessed && strings.HasPrefix(domain.Main, "*") && isDomainAlreadyChecked(domainProcessed, []string{domain.Main}) {
|
||||
// Check if a wildcard can validate the domain
|
||||
log.Warnf("Domain %q will not be processed by ACME provider because it is validated by the wildcard %q", domainProcessed, domain.Main)
|
||||
continue
|
||||
}
|
||||
newDomainsToCheck = append(newDomainsToCheck, domainProcessed)
|
||||
}
|
||||
|
||||
// Delete the domain if both Main and SANs can be validated by the wildcard domain
|
||||
// otherwise keep the unchecked values
|
||||
if newDomainsToCheck == nil {
|
||||
keepDomain = false
|
||||
break
|
||||
}
|
||||
domainToCheck.Set(newDomainsToCheck)
|
||||
}
|
||||
|
||||
if keepDomain {
|
||||
|
|
|
@ -207,11 +207,27 @@ func TestGetValidDomain(t *testing.T) {
|
|||
expectedDomains: nil,
|
||||
},
|
||||
{
|
||||
desc: "unexpected SANs",
|
||||
domains: types.Domain{Main: "*.traefik.wtf", SANs: []string{"foo.traefik.wtf"}},
|
||||
desc: "unauthorized wildcard with SAN",
|
||||
domains: types.Domain{Main: "*.*.traefik.wtf", SANs: []string{"foo.traefik.wtf"}},
|
||||
dnsChallenge: &DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "unable to generate a wildcard certificate in ACME provider for domain \"*.traefik.wtf,foo.traefik.wtf\" : SANs are not allowed",
|
||||
expectedErr: "unable to generate a wildcard certificate in ACME provider for domain \"*.*.traefik.wtf,foo.traefik.wtf\" : ACME does not allow '*.*' wildcard domain",
|
||||
expectedDomains: nil,
|
||||
},
|
||||
{
|
||||
desc: "wildcard and SANs",
|
||||
domains: types.Domain{Main: "*.traefik.wtf", SANs: []string{"traefik.wtf"}},
|
||||
dnsChallenge: &DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "",
|
||||
expectedDomains: []string{"*.traefik.wtf", "traefik.wtf"},
|
||||
},
|
||||
{
|
||||
desc: "unexpected SANs",
|
||||
domains: types.Domain{Main: "*.traefik.wtf", SANs: []string{"*.acme.wtf"}},
|
||||
dnsChallenge: &DNSChallenge{},
|
||||
wildcardAllowed: true,
|
||||
expectedErr: "unable to generate a certificate in ACME provider for domains \"*.traefik.wtf,*.acme.wtf\": SAN \"*.acme.wtf\" can not be a wildcard domain",
|
||||
expectedDomains: nil,
|
||||
},
|
||||
}
|
||||
|
@ -251,8 +267,8 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
Main: "*.foo.acme.wtf",
|
||||
},
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf", "bar.foo"},
|
||||
Main: "acme02.wtf",
|
||||
SANs: []string{"traefik.acme02.wtf", "bar.foo"},
|
||||
},
|
||||
},
|
||||
expectedDomains: []types.Domain{
|
||||
|
@ -262,15 +278,38 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Main: "*.foo.acme.wtf",
|
||||
SANs: []string{},
|
||||
},
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf", "bar.foo"},
|
||||
Main: "acme02.wtf",
|
||||
SANs: []string{"traefik.acme02.wtf", "bar.foo"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "2 domains with same values",
|
||||
desc: "wildcard and root domain",
|
||||
domains: []types.Domain{
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
},
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{"acme.wtf"},
|
||||
},
|
||||
},
|
||||
expectedDomains: []types.Domain{
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{},
|
||||
},
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "2 equals domains",
|
||||
domains: []types.Domain{
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
|
@ -288,6 +327,29 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "2 domains with same values",
|
||||
domains: []types.Domain{
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf"},
|
||||
},
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf", "foo.bar"},
|
||||
},
|
||||
},
|
||||
expectedDomains: []types.Domain{
|
||||
{
|
||||
Main: "acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf"},
|
||||
},
|
||||
{
|
||||
Main: "foo.bar",
|
||||
SANs: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "domain totally checked by wildcard",
|
||||
domains: []types.Domain{
|
||||
|
@ -302,6 +364,25 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
expectedDomains: []types.Domain{
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "duplicated wildcard",
|
||||
domains: []types.Domain{
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{"acme.wtf"},
|
||||
},
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
},
|
||||
},
|
||||
expectedDomains: []types.Domain{
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{"acme.wtf"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -315,6 +396,10 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
{
|
||||
Main: "*.acme.wtf",
|
||||
},
|
||||
{
|
||||
Main: "who.acme.wtf",
|
||||
SANs: []string{"traefik.acme.wtf", "bar.acme.wtf"},
|
||||
},
|
||||
},
|
||||
expectedDomains: []types.Domain{
|
||||
{
|
||||
|
@ -323,6 +408,7 @@ func TestDeleteUnnecessaryDomains(t *testing.T) {
|
|||
},
|
||||
{
|
||||
Main: "*.acme.wtf",
|
||||
SANs: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue