summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-03-04 12:14:25 -0700
committerMatthew Holt <mholt@users.noreply.github.com>2019-03-04 12:14:25 -0700
commit80dfb8b2a7f89b120a627bc4d866a1dc5ed3d92f (patch)
tree089d8a001256988f299277d2cb54d93c9efed5e5
parent98f160e39cadeb737cd631199b9f5e1e30682e94 (diff)
vendor: Update lego; notes for v0.11.5v0.11.5
-rw-r--r--README.md2
-rw-r--r--dist/CHANGES.txt12
-rw-r--r--dist/README.txt2
-rw-r--r--vendor/github.com/cenkalti/backoff/LICENSE20
-rw-r--r--vendor/github.com/cenkalti/backoff/backoff.go66
-rw-r--r--vendor/github.com/cenkalti/backoff/context.go63
-rw-r--r--vendor/github.com/cenkalti/backoff/exponential.go153
-rw-r--r--vendor/github.com/cenkalti/backoff/retry.go82
-rw-r--r--vendor/github.com/cenkalti/backoff/ticker.go82
-rw-r--r--vendor/github.com/cenkalti/backoff/tries.go35
-rw-r--r--vendor/github.com/xenolf/lego/acme/api/api.go53
-rw-r--r--vendor/github.com/xenolf/lego/acme/api/internal/sender/useragent.go2
-rw-r--r--vendor/github.com/xenolf/lego/certcrypto/crypto.go6
-rw-r--r--vendor/github.com/xenolf/lego/challenge/dns01/cname.go16
-rw-r--r--vendor/github.com/xenolf/lego/challenge/dns01/dns_challenge.go16
-rw-r--r--vendor/github.com/xenolf/lego/challenge/dns01/precheck.go39
-rw-r--r--vendor/github.com/xenolf/lego/challenge/http01/http_challenge.go2
-rw-r--r--vendor/github.com/xenolf/lego/challenge/resolver/solver_manager.go35
-rw-r--r--vendor/manifest20
19 files changed, 651 insertions, 55 deletions
diff --git a/README.md b/README.md
index 7364cbad..3fe847a2 100644
--- a/README.md
+++ b/README.md
@@ -76,7 +76,7 @@ Caddy binaries have no dependencies and are available for every platform. Get Ca
## Build
-To build from source you need **[Git](https://git-scm.com/downloads)** and **[Go](https://golang.org/doc/install)** (1.10 or newer). Follow these instruction for fast building:
+To build from source you need **[Git](https://git-scm.com/downloads)** and **[Go](https://golang.org/doc/install)** (1.12 or newer). Follow these instruction for fast building:
- Get the source with `go get github.com/mholt/caddy/caddy` and then run `go get github.com/caddyserver/builds`
- Now `cd $GOPATH/src/github.com/mholt/caddy/caddy` and run `go run build.go`
diff --git a/dist/CHANGES.txt b/dist/CHANGES.txt
index 47383a9b..eed33276 100644
--- a/dist/CHANGES.txt
+++ b/dist/CHANGES.txt
@@ -1,6 +1,18 @@
CHANGES
+0.11.5 (March 4, 2019)
+- TLS 1.3
+- Built with Go 1.12
+- More organized output at startup
+- internal: Paths are now hidden from other middlewares
+- staticfiles: Allow HEAD method
+- tls: TLS 1.3 default max version (1.2 still default min)
+- tls: Better handling of empty ACME email addresses
+- tls: Removed CBC ciphers from defaults
+- Other minor improvements and bug fixes
+
+
0.11.4 (February 15, 2019)
- New -json-to-caddyfile and -caddyfile-to-json flags
- Fix leaking logging goroutine on SIGUSR1
diff --git a/dist/README.txt b/dist/README.txt
index 0b6ce04e..b74a1c0b 100644
--- a/dist/README.txt
+++ b/dist/README.txt
@@ -1,4 +1,4 @@
-CADDY 0.11.4
+CADDY 0.11.5
Website
https://caddyserver.com
diff --git a/vendor/github.com/cenkalti/backoff/LICENSE b/vendor/github.com/cenkalti/backoff/LICENSE
new file mode 100644
index 00000000..89b81799
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Cenk Altı
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/cenkalti/backoff/backoff.go b/vendor/github.com/cenkalti/backoff/backoff.go
new file mode 100644
index 00000000..3676ee40
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/backoff.go
@@ -0,0 +1,66 @@
+// Package backoff implements backoff algorithms for retrying operations.
+//
+// Use Retry function for retrying operations that may fail.
+// If Retry does not meet your needs,
+// copy/paste the function into your project and modify as you wish.
+//
+// There is also Ticker type similar to time.Ticker.
+// You can use it if you need to work with channels.
+//
+// See Examples section below for usage examples.
+package backoff
+
+import "time"
+
+// BackOff is a backoff policy for retrying an operation.
+type BackOff interface {
+ // NextBackOff returns the duration to wait before retrying the operation,
+ // or backoff. Stop to indicate that no more retries should be made.
+ //
+ // Example usage:
+ //
+ // duration := backoff.NextBackOff();
+ // if (duration == backoff.Stop) {
+ // // Do not retry operation.
+ // } else {
+ // // Sleep for duration and retry operation.
+ // }
+ //
+ NextBackOff() time.Duration
+
+ // Reset to initial state.
+ Reset()
+}
+
+// Stop indicates that no more retries should be made for use in NextBackOff().
+const Stop time.Duration = -1
+
+// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
+// meaning that the operation is retried immediately without waiting, indefinitely.
+type ZeroBackOff struct{}
+
+func (b *ZeroBackOff) Reset() {}
+
+func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
+
+// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
+// NextBackOff(), meaning that the operation should never be retried.
+type StopBackOff struct{}
+
+func (b *StopBackOff) Reset() {}
+
+func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
+
+// ConstantBackOff is a backoff policy that always returns the same backoff delay.
+// This is in contrast to an exponential backoff policy,
+// which returns a delay that grows longer as you call NextBackOff() over and over again.
+type ConstantBackOff struct {
+ Interval time.Duration
+}
+
+func (b *ConstantBackOff) Reset() {}
+func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
+
+func NewConstantBackOff(d time.Duration) *ConstantBackOff {
+ return &ConstantBackOff{Interval: d}
+}
diff --git a/vendor/github.com/cenkalti/backoff/context.go b/vendor/github.com/cenkalti/backoff/context.go
new file mode 100644
index 00000000..7706faa2
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/context.go
@@ -0,0 +1,63 @@
+package backoff
+
+import (
+ "context"
+ "time"
+)
+
+// BackOffContext is a backoff policy that stops retrying after the context
+// is canceled.
+type BackOffContext interface {
+ BackOff
+ Context() context.Context
+}
+
+type backOffContext struct {
+ BackOff
+ ctx context.Context
+}
+
+// WithContext returns a BackOffContext with context ctx
+//
+// ctx must not be nil
+func WithContext(b BackOff, ctx context.Context) BackOffContext {
+ if ctx == nil {
+ panic("nil context")
+ }
+
+ if b, ok := b.(*backOffContext); ok {
+ return &backOffContext{
+ BackOff: b.BackOff,
+ ctx: ctx,
+ }
+ }
+
+ return &backOffContext{
+ BackOff: b,
+ ctx: ctx,
+ }
+}
+
+func ensureContext(b BackOff) BackOffContext {
+ if cb, ok := b.(BackOffContext); ok {
+ return cb
+ }
+ return WithContext(b, context.Background())
+}
+
+func (b *backOffContext) Context() context.Context {
+ return b.ctx
+}
+
+func (b *backOffContext) NextBackOff() time.Duration {
+ select {
+ case <-b.ctx.Done():
+ return Stop
+ default:
+ }
+ next := b.BackOff.NextBackOff()
+ if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next {
+ return Stop
+ }
+ return next
+}
diff --git a/vendor/github.com/cenkalti/backoff/exponential.go b/vendor/github.com/cenkalti/backoff/exponential.go
new file mode 100644
index 00000000..a031a659
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/exponential.go
@@ -0,0 +1,153 @@
+package backoff
+
+import (
+ "math/rand"
+ "time"
+)
+
+/*
+ExponentialBackOff is a backoff implementation that increases the backoff
+period for each retry attempt using a randomization function that grows exponentially.
+
+NextBackOff() is calculated using the following formula:
+
+ randomized interval =
+ RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
+
+In other words NextBackOff() will range between the randomization factor
+percentage below and above the retry interval.
+
+For example, given the following parameters:
+
+ RetryInterval = 2
+ RandomizationFactor = 0.5
+ Multiplier = 2
+
+the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
+multiplied by the exponential, that is, between 2 and 6 seconds.
+
+Note: MaxInterval caps the RetryInterval and not the randomized interval.
+
+If the time elapsed since an ExponentialBackOff instance is created goes past the
+MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
+
+The elapsed time can be reset by calling Reset().
+
+Example: Given the following default arguments, for 10 tries the sequence will be,
+and assuming we go over the MaxElapsedTime on the 10th try:
+
+ Request # RetryInterval (seconds) Randomized Interval (seconds)
+
+ 1 0.5 [0.25, 0.75]
+ 2 0.75 [0.375, 1.125]
+ 3 1.125 [0.562, 1.687]
+ 4 1.687 [0.8435, 2.53]
+ 5 2.53 [1.265, 3.795]
+ 6 3.795 [1.897, 5.692]
+ 7 5.692 [2.846, 8.538]
+ 8 8.538 [4.269, 12.807]
+ 9 12.807 [6.403, 19.210]
+ 10 19.210 backoff.Stop
+
+Note: Implementation is not thread-safe.
+*/
+type ExponentialBackOff struct {
+ InitialInterval time.Duration
+ RandomizationFactor float64
+ Multiplier float64
+ MaxInterval time.Duration
+ // After MaxElapsedTime the ExponentialBackOff stops.
+ // It never stops if MaxElapsedTime == 0.
+ MaxElapsedTime time.Duration
+ Clock Clock
+
+ currentInterval time.Duration
+ startTime time.Time
+}
+
+// Clock is an interface that returns current time for BackOff.
+type Clock interface {
+ Now() time.Time
+}
+
+// Default values for ExponentialBackOff.
+const (
+ DefaultInitialInterval = 500 * time.Millisecond
+ DefaultRandomizationFactor = 0.5
+ DefaultMultiplier = 1.5
+ DefaultMaxInterval = 60 * time.Second
+ DefaultMaxElapsedTime = 15 * time.Minute
+)
+
+// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
+func NewExponentialBackOff() *ExponentialBackOff {
+ b := &ExponentialBackOff{
+ InitialInterval: DefaultInitialInterval,
+ RandomizationFactor: DefaultRandomizationFactor,
+ Multiplier: DefaultMultiplier,
+ MaxInterval: DefaultMaxInterval,
+ MaxElapsedTime: DefaultMaxElapsedTime,
+ Clock: SystemClock,
+ }
+ b.Reset()
+ return b
+}
+
+type systemClock struct{}
+
+func (t systemClock) Now() time.Time {
+ return time.Now()
+}
+
+// SystemClock implements Clock interface that uses time.Now().
+var SystemClock = systemClock{}
+
+// Reset the interval back to the initial retry interval and restarts the timer.
+func (b *ExponentialBackOff) Reset() {
+ b.currentInterval = b.InitialInterval
+ b.startTime = b.Clock.Now()
+}
+
+// NextBackOff calculates the next backoff interval using the formula:
+// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
+func (b *ExponentialBackOff) NextBackOff() time.Duration {
+ // Make sure we have not gone over the maximum elapsed time.
+ if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
+ return Stop
+ }
+ defer b.incrementCurrentInterval()
+ return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
+}
+
+// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
+// is created and is reset when Reset() is called.
+//
+// The elapsed time is computed using time.Now().UnixNano(). It is
+// safe to call even while the backoff policy is used by a running
+// ticker.
+func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
+ return b.Clock.Now().Sub(b.startTime)
+}
+
+// Increments the current interval by multiplying it with the multiplier.
+func (b *ExponentialBackOff) incrementCurrentInterval() {
+ // Check for overflow, if overflow is detected set the current interval to the max interval.
+ if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
+ b.currentInterval = b.MaxInterval
+ } else {
+ b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
+ }
+}
+
+// Returns a random value from the following interval:
+// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
+func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
+ var delta = randomizationFactor * float64(currentInterval)
+ var minInterval = float64(currentInterval) - delta
+ var maxInterval = float64(currentInterval) + delta
+
+ // Get a random value from the range [minInterval, maxInterval].
+ // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
+ // we want a 33% chance for selecting either 1, 2 or 3.
+ return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
+}
diff --git a/vendor/github.com/cenkalti/backoff/retry.go b/vendor/github.com/cenkalti/backoff/retry.go
new file mode 100644
index 00000000..e936a506
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/retry.go
@@ -0,0 +1,82 @@
+package backoff
+
+import "time"
+
+// An Operation is executing by Retry() or RetryNotify().
+// The operation will be retried using a backoff policy if it returns an error.
+type Operation func() error
+
+// Notify is a notify-on-error function. It receives an operation error and
+// backoff delay if the operation failed (with an error).
+//
+// NOTE that if the backoff policy stated to stop retrying,
+// the notify function isn't called.
+type Notify func(error, time.Duration)
+
+// Retry the operation o until it does not return error or BackOff stops.
+// o is guaranteed to be run at least once.
+//
+// If o returns a *PermanentError, the operation is not retried, and the
+// wrapped error is returned.
+//
+// Retry sleeps the goroutine for the duration returned by BackOff after a
+// failed operation returns.
+func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
+
+// RetryNotify calls notify function with the error and wait duration
+// for each failed attempt before sleep.
+func RetryNotify(operation Operation, b BackOff, notify Notify) error {
+ var err error
+ var next time.Duration
+ var t *time.Timer
+
+ cb := ensureContext(b)
+
+ b.Reset()
+ for {
+ if err = operation(); err == nil {
+ return nil
+ }
+
+ if permanent, ok := err.(*PermanentError); ok {
+ return permanent.Err
+ }
+
+ if next = cb.NextBackOff(); next == Stop {
+ return err
+ }
+
+ if notify != nil {
+ notify(err, next)
+ }
+
+ if t == nil {
+ t = time.NewTimer(next)
+ defer t.Stop()
+ } else {
+ t.Reset(next)
+ }
+
+ select {
+ case <-cb.Context().Done():
+ return err
+ case <-t.C:
+ }
+ }
+}
+
+// PermanentError signals that the operation should not be retried.
+type PermanentError struct {
+ Err error
+}
+
+func (e *PermanentError) Error() string {
+ return e.Err.Error()
+}
+
+// Permanent wraps the given err in a *PermanentError.
+func Permanent(err error) *PermanentError {
+ return &PermanentError{
+ Err: err,
+ }
+}
diff --git a/vendor/github.com/cenkalti/backoff/ticker.go b/vendor/github.com/cenkalti/backoff/ticker.go
new file mode 100644
index 00000000..e41084b0
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/ticker.go
@@ -0,0 +1,82 @@
+package backoff
+
+import (
+ "sync"
+ "time"
+)
+
+// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
+//
+// Ticks will continue to arrive when the previous operation is still running,
+// so operations that take a while to fail could run in quick succession.
+type Ticker struct {
+ C <-chan time.Time
+ c chan time.Time
+ b BackOffContext
+ stop chan struct{}
+ stopOnce sync.Once
+}
+
+// NewTicker returns a new Ticker containing a channel that will send
+// the time at times specified by the BackOff argument. Ticker is
+// guaranteed to tick at least once. The channel is closed when Stop
+// method is called or BackOff stops. It is not safe to manipulate the
+// provided backoff policy (notably calling NextBackOff or Reset)
+// while the ticker is running.
+func NewTicker(b BackOff) *Ticker {
+ c := make(chan time.Time)
+ t := &Ticker{
+ C: c,
+ c: c,
+ b: ensureContext(b),
+ stop: make(chan struct{}),
+ }
+ t.b.Reset()
+ go t.run()
+ return t
+}
+
+// Stop turns off a ticker. After Stop, no more ticks will be sent.
+func (t *Ticker) Stop() {
+ t.stopOnce.Do(func() { close(t.stop) })
+}
+
+func (t *Ticker) run() {
+ c := t.c
+ defer close(c)
+
+ // Ticker is guaranteed to tick at least once.
+ afterC := t.send(time.Now())
+
+ for {
+ if afterC == nil {
+ return
+ }
+
+ select {
+ case tick := <-afterC:
+ afterC = t.send(tick)
+ case <-t.stop:
+ t.c = nil // Prevent future ticks from being sent to the channel.
+ return
+ case <-t.b.Context().Done():
+ return
+ }
+ }
+}
+
+func (t *Ticker) send(tick time.Time) <-chan time.Time {
+ select {
+ case t.c <- tick:
+ case <-t.stop:
+ return nil
+ }
+
+ next := t.b.NextBackOff()
+ if next == Stop {
+ t.Stop()
+ return nil
+ }
+
+ return time.After(next)
+}
diff --git a/vendor/github.com/cenkalti/backoff/tries.go b/vendor/github.com/cenkalti/backoff/tries.go
new file mode 100644
index 00000000..cfeefd9b
--- /dev/null
+++ b/vendor/github.com/cenkalti/backoff/tries.go
@@ -0,0 +1,35 @@
+package backoff
+
+import "time"
+
+/*
+WithMaxRetries creates a wrapper around another BackOff, which will
+return Stop if NextBackOff() has been called too many times since
+the last time Reset() was called
+
+Note: Implementation is not thread-safe.
+*/
+func WithMaxRetries(b BackOff, max uint64) BackOff {
+ return &backOffTries{delegate: b, maxTries: max}
+}
+
+type backOffTries struct {
+ delegate BackOff
+ maxTries uint64
+ numTries uint64
+}
+
+func (b *backOffTries) NextBackOff() time.Duration {
+ if b.maxTries > 0 {
+ if b.maxTries <= b.numTries {
+ return Stop
+ }
+ b.numTries++
+ }
+ return b.delegate.NextBackOff()
+}
+
+func (b *backOffTries) Reset() {
+ b.numTries = 0
+ b.delegate.Reset()
+}
diff --git a/vendor/github.com/xenolf/lego/acme/api/api.go b/vendor/github.com/xenolf/lego/acme/api/api.go
index 14b18f52..a62e49e4 100644
--- a/vendor/github.com/xenolf/lego/acme/api/api.go
+++ b/vendor/github.com/xenolf/lego/acme/api/api.go
@@ -2,12 +2,15 @@ package api
import (
"bytes"
+ "context"
"crypto"
"encoding/json"
"errors"
"fmt"
"net/http"
+ "time"
+ "github.com/cenkalti/backoff"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/acme/api/internal/nonces"
"github.com/xenolf/lego/acme/api/internal/secure"
@@ -64,34 +67,46 @@ func (a *Core) post(uri string, reqBody, response interface{}) (*http.Response,
return nil, errors.New("failed to marshal message")
}
- return a.retrievablePost(uri, content, response, 0)
+ return a.retrievablePost(uri, content, response)
}
// postAsGet performs an HTTP POST ("POST-as-GET") request.
// https://tools.ietf.org/html/draft-ietf-acme-acme-16#section-6.3
func (a *Core) postAsGet(uri string, response interface{}) (*http.Response, error) {
- return a.retrievablePost(uri, []byte{}, response, 0)
+ return a.retrievablePost(uri, []byte{}, response)
}
-func (a *Core) retrievablePost(uri string, content []byte, response interface{}, retry int) (*http.Response, error) {
- resp, err := a.signedPost(uri, content, response)
- if err != nil {
- // during tests, 5 retries allow to support ~50% of bad nonce.
- if retry >= 5 {
- log.Infof("too many retry on a nonce error, retry count: %d", retry)
- return resp, err
- }
- switch err.(type) {
- // Retry once if the nonce was invalidated
- case *acme.NonceError:
- log.Infof("nonce error retry: %s", err)
- resp, err = a.retrievablePost(uri, content, response, retry+1)
- if err != nil {
- return resp, err
+func (a *Core) retrievablePost(uri string, content []byte, response interface{}) (*http.Response, error) {
+ // during tests, allow to support ~90% of bad nonce with a minimum of attempts.
+ bo := backoff.NewExponentialBackOff()
+ bo.InitialInterval = 200 * time.Millisecond
+ bo.MaxInterval = 5 * time.Second
+ bo.MaxElapsedTime = 20 * time.Second
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ var resp *http.Response
+ operation := func() error {
+ var err error
+ resp, err = a.signedPost(uri, content, response)
+ if err != nil {
+ switch err.(type) {
+ // Retry if the nonce was invalidated
+ case *acme.NonceError:
+ log.Infof("nonce error retry: %s", err)
+ return err
+ default:
+ cancel()
+ return err
}
- default:
- return resp, err
}
+
+ return nil
+ }
+
+ err := backoff.Retry(operation, backoff.WithContext(bo, ctx))
+ if err != nil {
+ return nil, err
}
return resp, nil
diff --git a/vendor/github.com/xenolf/lego/acme/api/internal/sender/useragent.go b/vendor/github.com/xenolf/lego/acme/api/internal/sender/useragent.go
index b2096407..9806fd1f 100644
--- a/vendor/github.com/xenolf/lego/acme/api/internal/sender/useragent.go
+++ b/vendor/github.com/xenolf/lego/acme/api/internal/sender/useragent.go
@@ -5,7 +5,7 @@ package sender
const (
// ourUserAgent is the User-Agent of this underlying library package.
- ourUserAgent = "xenolf-acme/2.0.1"
+ ourUserAgent = "xenolf-acme/2.2.0"
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
// values: detach|release
diff --git a/vendor/github.com/xenolf/lego/certcrypto/crypto.go b/vendor/github.com/xenolf/lego/certcrypto/crypto.go
index bb99d7d2..c9d0c109 100644
--- a/vendor/github.com/xenolf/lego/certcrypto/crypto.go
+++ b/vendor/github.com/xenolf/lego/certcrypto/crypto.go
@@ -124,6 +124,10 @@ func GenerateCSR(privateKey crypto.PrivateKey, domain string, san []string, must
}
func PEMEncode(data interface{}) []byte {
+ return pem.EncodeToMemory(PEMBlock(data))
+}
+
+func PEMBlock(data interface{}) *pem.Block {
var pemBlock *pem.Block
switch key := data.(type) {
case *ecdsa.PrivateKey:
@@ -137,7 +141,7 @@ func PEMEncode(data interface{}) []byte {
pemBlock = &pem.Block{Type: "CERTIFICATE", Bytes: []byte(data.(DERCertificateBytes))}
}
- return pem.EncodeToMemory(pemBlock)
+ return pemBlock
}
func pemDecode(data []byte) (*pem.Block, error) {
diff --git a/vendor/github.com/xenolf/lego/challenge/dns01/cname.go b/vendor/github.com/xenolf/lego/challenge/dns01/cname.go
new file mode 100644
index 00000000..619c8476
--- /dev/null
+++ b/vendor/github.com/xenolf/lego/challenge/dns01/cname.go
@@ -0,0 +1,16 @@
+package dns01
+
+import "github.com/miekg/dns"
+
+// Update FQDN with CNAME if any
+func updateDomainWithCName(r *dns.Msg, fqdn string) string {
+ for _, rr := range r.Answer {
+ if cn, ok := rr.(*dns.CNAME); ok {
+ if cn.Hdr.Name == fqdn {
+ return cn.Target
+ }
+ }
+ }
+
+ return fqdn
+}
diff --git a/vendor/github.com/xenolf/lego/challenge/dns01/dns_challenge.go b/vendor/github.com/xenolf/lego/challenge/dns01/dns_challenge.go
index c9ef2ee3..ace01378 100644
--- a/vendor/github.com/xenolf/lego/challenge/dns01/dns_challenge.go
+++ b/vendor/github.com/xenolf/lego/challenge/dns01/dns_challenge.go
@@ -4,8 +4,11 @@ import (
"crypto/sha256"
"encoding/base64"
"fmt"
+ "os"
+ "strconv"
"time"
+ "github.com/miekg/dns"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/acme/api"
"github.com/xenolf/lego/challenge"
@@ -124,7 +127,7 @@ func (c *Challenge) Solve(authz acme.Authorization) error {
log.Infof("[%s] acme: Checking DNS record propagation using %+v", domain, recursiveNameservers)
err = wait.For("propagation", timeout, interval, func() (bool, error) {
- stop, errP := c.preCheck.call(fqdn, value)
+ stop, errP := c.preCheck.call(domain, fqdn, value)
if !stop || errP != nil {
log.Infof("[%s] acme: Waiting for DNS record propagation.", domain)
}
@@ -135,7 +138,7 @@ func (c *Challenge) Solve(authz acme.Authorization) error {
}
chlng.KeyAuthorization = keyAuth
- return c.validate(c.core, authz.Identifier.Value, chlng)
+ return c.validate(c.core, domain, chlng)
}
// CleanUp cleans the challenge.
@@ -172,5 +175,14 @@ func GetRecord(domain, keyAuth string) (fqdn string, value string) {
// base64URL encoding without padding
value = base64.RawURLEncoding.EncodeToString(keyAuthShaBytes[:sha256.Size])
fqdn = fmt.Sprintf("_acme-challenge.%s.", domain)
+
+ if ok, _ := strconv.ParseBool(os.Getenv("LEGO_EXPERIMENTAL_CNAME_SUPPORT")); ok {
+ r, err := dnsQuery(fqdn, dns.TypeCNAME, recursiveNameservers, true)
+ // Check if the domain has CNAME then return that
+ if err == nil && r.Rcode == dns.RcodeSuccess {
+ fqdn = updateDomainWithCName(r, fqdn)
+ }
+ }
+
return
}
diff --git a/vendor/github.com/xenolf/lego/challenge/dns01/precheck.go b/vendor/github.com/xenolf/lego/challenge/dns01/precheck.go
index 63b72cef..00e09854 100644
--- a/vendor/github.com/xenolf/lego/challenge/dns01/precheck.go
+++ b/vendor/github.com/xenolf/lego/challenge/dns01/precheck.go
@@ -1,6 +1,7 @@
package dns01
import (
+ "errors"
"fmt"
"net"
"strings"
@@ -11,11 +12,30 @@ import (
// PreCheckFunc checks DNS propagation before notifying ACME that the DNS challenge is ready.
type PreCheckFunc func(fqdn, value string) (bool, error)
+// WrapPreCheckFunc wraps a PreCheckFunc in order to do extra operations before or after
+// the main check, put it in a loop, etc.
+type WrapPreCheckFunc func(domain, fqdn, value string, check PreCheckFunc) (bool, error)
+
+// WrapPreCheck Allow to define checks before notifying ACME that the DNS challenge is ready.
+func WrapPreCheck(wrap WrapPreCheckFunc) ChallengeOption {
+ return func(chlg *Challenge) error {
+ chlg.preCheck.checkFunc = wrap
+ return nil
+ }
+}
+
+// AddPreCheck Allow to define checks before notifying ACME that the DNS challenge is ready.
+// Deprecated: use WrapPreCheck instead.
func AddPreCheck(preCheck PreCheckFunc) ChallengeOption {
// Prevent race condition
check := preCheck
return func(chlg *Challenge) error {
- chlg.preCheck.checkFunc = check
+ chlg.preCheck.checkFunc = func(_, fqdn, value string, _ PreCheckFunc) (bool, error) {
+ if check == nil {
+ return false, errors.New("invalid preCheck: preCheck is nil")
+ }
+ return check(fqdn, value)
+ }
return nil
}
}
@@ -29,7 +49,7 @@ func DisableCompletePropagationRequirement() ChallengeOption {
type preCheck struct {
// checks DNS propagation before notifying ACME that the DNS challenge is ready.
- checkFunc PreCheckFunc
+ checkFunc WrapPreCheckFunc
// require the TXT record to be propagated to all authoritative name servers
requireCompletePropagation bool
}
@@ -40,11 +60,12 @@ func newPreCheck() preCheck {
}
}
-func (p preCheck) call(fqdn, value string) (bool, error) {
+func (p preCheck) call(domain, fqdn, value string) (bool, error) {
if p.checkFunc == nil {
return p.checkDNSPropagation(fqdn, value)
}
- return p.checkFunc(fqdn, value)
+
+ return p.checkFunc(domain, fqdn, value, p.checkDNSPropagation)
}
// checkDNSPropagation checks if the expected TXT record has been propagated to all authoritative nameservers.
@@ -60,15 +81,7 @@ func (p preCheck) checkDNSPropagation(fqdn, value string) (bool, error) {
}
if r.Rcode == dns.RcodeSuccess {
- // If we see a CNAME here then use the alias
- for _, rr := range r.Answer {
- if cn, ok := rr.(*dns.CNAME); ok {
- if cn.Hdr.Name == fqdn {
- fqdn = cn.Target
- break
- }
- }
- }
+ fqdn = updateDomainWithCName(r, fqdn)
}
authoritativeNss, err := lookupNameservers(fqdn)
diff --git a/vendor/github.com/xenolf/lego/challenge/http01/http_challenge.go b/vendor/github.com/xenolf/lego/challenge/http01/http_challenge.go
index 4176ecae..861bdbed 100644
--- a/vendor/github.com/xenolf/lego/challenge/http01/http_challenge.go
+++ b/vendor/github.com/xenolf/lego/challenge/http01/http_challenge.go
@@ -61,5 +61,5 @@ func (c *Challenge) Solve(authz acme.Authorization) error {
}()
chlng.KeyAuthorization = keyAuth
- return c.validate(c.core, authz.Identifier.Value, chlng)
+ return c.validate(c.core, domain, chlng)
}
diff --git a/vendor/github.com/xenolf/lego/challenge/resolver/solver_manager.go b/vendor/github.com/xenolf/lego/challenge/resolver/solver_manager.go
index 55faf77a..840e19d8 100644
--- a/vendor/github.com/xenolf/lego/challenge/resolver/solver_manager.go
+++ b/vendor/github.com/xenolf/lego/challenge/resolver/solver_manager.go
@@ -1,12 +1,14 @@
package resolver
import (
+ "context"
"errors"
"fmt"
"sort"
"strconv"
"time"
+ "github.com/cenkalti/backoff"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/acme/api"
"github.com/xenolf/lego/challenge"
@@ -90,16 +92,35 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
return nil
}
+ ra, err := strconv.Atoi(chlng.RetryAfter)
+ if err != nil {
+ // The ACME server MUST return a Retry-After.
+ // If it doesn't, we'll just poll hard.
+ // Boulder does not implement the ability to retry challenges or the Retry-After header.
+ // https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md#section-82
+ ra = 5
+ }
+ initialInterval := time.Duration(ra) * time.Second
+
+ bo := backoff.NewExponentialBackOff()
+ bo.InitialInterval = initialInterval
+ bo.MaxInterval = 10 * initialInterval
+ bo.MaxElapsedTime = 100 * initialInterval
+
+ ctx, cancel := context.WithCancel(context.Background())
+
// After the path is sent, the ACME server will access our server.
// Repeatedly check the server for an updated status on our request.
- for {
+ operation := func() error {
authz, err := core.Authorizations.Get(chlng.AuthorizationURL)
if err != nil {
+ cancel()
return err
}
valid, err := checkAuthorizationStatus(authz)
if err != nil {
+ cancel()
return err
}
@@ -108,16 +129,10 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
return nil
}
- ra, err := strconv.Atoi(chlng.RetryAfter)
- if err != nil {
- // The ACME server MUST return a Retry-After.
- // If it doesn't, we'll just poll hard.
- // Boulder does not implement the ability to retry challenges or the Retry-After header.
- // https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md#section-82
- ra = 5
- }
- time.Sleep(time.Duration(ra) * time.Second)
+ return errors.New("the server didn't respond to our request")
}
+
+ return backoff.Retry(operation, backoff.WithContext(bo, ctx))
}
func checkChallengeStatus(chlng acme.ExtendedChallenge) (bool, error) {
diff --git a/vendor/manifest b/vendor/manifest
index d00333f1..feb0466f 100644
--- a/vendor/manifest
+++ b/vendor/manifest
@@ -35,6 +35,14 @@
"notests": true
},
{
+ "importpath": "github.com/cenkalti/backoff",
+ "repository": "https://github.com/cenkalti/backoff",
+ "vcs": "git",
+ "revision": "1e4cf3da559842a91afcb6ea6141451e6c30c618",
+ "branch": "master",
+ "notests": true
+ },
+ {
"importpath": "github.com/codahale/aesnicheck",
"repository": "https://github.com/codahale/aesnicheck",
"vcs": "git",
@@ -178,7 +186,7 @@
"importpath": "github.com/xenolf/lego/acme",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "a43ec709e8034f388aab28d14b97aeed0e7aa98c",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "acme",
"notests": true
@@ -187,7 +195,7 @@
"importpath": "github.com/xenolf/lego/certcrypto",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "a43ec709e8034f388aab28d14b97aeed0e7aa98c",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "certcrypto",
"notests": true
@@ -196,7 +204,7 @@
"importpath": "github.com/xenolf/lego/certificate",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "a43ec709e8034f388aab28d14b97aeed0e7aa98c",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "certificate",
"notests": true
@@ -205,7 +213,7 @@
"importpath": "github.com/xenolf/lego/challenge",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "a43ec709e8034f388aab28d14b97aeed0e7aa98c",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "/challenge",
"notests": true
@@ -214,7 +222,7 @@
"importpath": "github.com/xenolf/lego/lego",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "f05aa4c241fd8b43da9dc8cab8c8965e5b3c1b55",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "/lego",
"notests": true
@@ -241,7 +249,7 @@
"importpath": "github.com/xenolf/lego/registration",
"repository": "https://github.com/xenolf/lego",
"vcs": "git",
- "revision": "a43ec709e8034f388aab28d14b97aeed0e7aa98c",
+ "revision": "67b329e3e370f481da545a4c95577f60c9be08b6",
"branch": "master",
"path": "registration",
"notests": true