diff --git a/pkg/apis/certmanager/v1alpha1/types.go b/pkg/apis/certmanager/v1alpha1/types.go index 054f72995..7ac4a832c 100644 --- a/pkg/apis/certmanager/v1alpha1/types.go +++ b/pkg/apis/certmanager/v1alpha1/types.go @@ -374,6 +374,9 @@ type ACMEOrderChallenge struct { // Challenge key for this challenge Key string `json:"key"` + // Set to true if this challenge is for a wildcard domain + Wildcard bool `json:"wildcard"` + // Configuration used to present this challenge ACMESolverConfig `json:",inline"` } diff --git a/pkg/issuer/acme/prepare.go b/pkg/issuer/acme/prepare.go index 941c20921..69c015f53 100644 --- a/pkg/issuer/acme/prepare.go +++ b/pkg/issuer/acme/prepare.go @@ -122,7 +122,22 @@ func (a *Acme) presentOrder(ctx context.Context, cl client.Interface, crt *v1alp var errs []error // TODO: run this in parallel + // we use this field to ensure we don't attempt to present the same identifier + // twice in a single sync. + // Without this, if a Certificate specifies both *.domain.com and domain.com on + // a Certificate, the DNS provider will race with itself and fail to solve either + // challenge. + var presentedIdentifiers []string +Outer: for _, ch := range chs { + // don't present challenges for the same domain more than once + for _, i := range presentedIdentifiers { + if ch.Domain == i { + errs = append(errs, fmt.Errorf("another authorization for domain %q is in progress", ch.Domain)) + continue Outer + } + } + presentedIdentifiers = append(presentedIdentifiers, ch.Domain) errs = append(errs, a.presentChallenge(ctx, cl, crt, ch)) } // we aggregate the errors here before beginning to accept challenges. @@ -304,7 +319,7 @@ func (a *Acme) selectChallengesForAuthorizations(ctx context.Context, cl client. continue } - internalCh, err := buildInternalChallengeType(cl, challenge, *cfg, domain, authz.URL) + internalCh, err := buildInternalChallengeType(cl, challenge, *cfg, domain, authz.URL, authz.Wildcard) if err != nil { errs = append(errs, err) continue @@ -315,7 +330,7 @@ func (a *Acme) selectChallengesForAuthorizations(ctx context.Context, cl client. return chals, utilerrors.NewAggregate(errs) } -func buildInternalChallengeType(cl client.Interface, ch *acme.Challenge, cfg v1alpha1.ACMESolverConfig, domain, authzURL string) (v1alpha1.ACMEOrderChallenge, error) { +func buildInternalChallengeType(cl client.Interface, ch *acme.Challenge, cfg v1alpha1.ACMESolverConfig, domain, authzURL string, wildcard bool) (v1alpha1.ACMEOrderChallenge, error) { var key string var err error switch ch.Type { @@ -338,6 +353,7 @@ func buildInternalChallengeType(cl client.Interface, ch *acme.Challenge, cfg v1a Token: ch.Token, Key: key, ACMESolverConfig: cfg, + Wildcard: wildcard, }, nil }