Merge latest changes from upstream crypto/acme library
This commit is contained in:
parent
959aba219f
commit
41d7136bf5
63
third_party/crypto/acme/acme.go
vendored
63
third_party/crypto/acme/acme.go
vendored
@ -46,6 +46,10 @@ const (
|
||||
// Max number of collected nonces kept in memory.
|
||||
// Expect usual peak of 1 or 2.
|
||||
maxNonces = 100
|
||||
|
||||
// User-Agent, bump the version each time a change is made to the
|
||||
// handling of API requests.
|
||||
userAgent = "go-acme/2"
|
||||
)
|
||||
|
||||
// Client is an ACME client.
|
||||
@ -73,6 +77,11 @@ type Client struct {
|
||||
// will have no effect.
|
||||
DirectoryURL string
|
||||
|
||||
// UserAgent is an optional string that identifies this client and
|
||||
// version to the ACME server. It should be set to something like
|
||||
// "myclient/1.2.3".
|
||||
UserAgent string
|
||||
|
||||
noncesMu sync.Mutex
|
||||
nonces map[string]struct{} // nonces collected from previous responses
|
||||
|
||||
@ -274,6 +283,13 @@ func (c *Client) WaitOrder(ctx context.Context, url string) (*Order, error) {
|
||||
sleep := timeSleeper(ctx)
|
||||
for {
|
||||
o, err := c.GetOrder(ctx, url)
|
||||
if e, ok := err.(*Error); ok && e.StatusCode >= 500 && e.StatusCode <= 599 {
|
||||
// retriable 5xx error
|
||||
if err := sleep(retryAfter(e.Header.Get("Retry-After"))); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -392,14 +408,14 @@ func (c *Client) DeactivateAuthorization(ctx context.Context, url string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitAuthorization retrieves authorization details. If the authorization is not in
|
||||
// a final state (StatusValid/StatusInvalid), it retries the request until the authorization
|
||||
// is final, ctx is cancelled by the caller, an error response is received, or the ACME CA
|
||||
// responded with a 4xx error.
|
||||
// WaitAuthorization polls an authorization at the given URL
|
||||
// until it is in one of the final states, StatusValid or StatusInvalid,
|
||||
// the ACME CA responded with a 4xx error code, or the context is done.
|
||||
//
|
||||
// It returns a non-nil Authorization only if its Status is StatusValid.
|
||||
// In all other cases WaitAuthorization returns an error.
|
||||
// If the Status is StatusInvalid or StatusDeactivated, the returned error will be of type AuthorizationError.
|
||||
// If the Status is StatusInvalid, StatusDeactivated, or StatusRevoked the
|
||||
// returned error will be of type AuthorizationError.
|
||||
func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorization, error) {
|
||||
sleep := sleeper(ctx)
|
||||
for {
|
||||
@ -407,17 +423,21 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.StatusCode != http.StatusOK {
|
||||
err = responseError(res)
|
||||
res.Body.Close()
|
||||
return nil, err
|
||||
}
|
||||
if res.StatusCode >= 400 && res.StatusCode <= 499 {
|
||||
// Non-retriable error. For instance, Let's Encrypt may return 404 Not Found
|
||||
// when requesting an expired authorization.
|
||||
defer res.Body.Close()
|
||||
return nil, responseError(res)
|
||||
}
|
||||
|
||||
retry := res.Header.Get("Retry-After")
|
||||
if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusAccepted {
|
||||
res.Body.Close()
|
||||
if err := sleep(retry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
continue
|
||||
}
|
||||
var raw wireAuthz
|
||||
err = json.NewDecoder(res.Body).Decode(&raw)
|
||||
res.Body.Close()
|
||||
@ -427,13 +447,13 @@ func (c *Client) WaitAuthorization(ctx context.Context, url string) (*Authorizat
|
||||
switch raw.Status {
|
||||
case StatusValid:
|
||||
return raw.authorization(url), nil
|
||||
case StatusInvalid, StatusDeactivated:
|
||||
case StatusInvalid, StatusDeactivated, StatusRevoked:
|
||||
return nil, AuthorizationError{raw.authorization(url)}
|
||||
case StatusPending, StatusProcessing: // fall through to sleep
|
||||
default:
|
||||
return nil, fmt.Errorf("acme: unknown authorization status %q", raw.Status)
|
||||
}
|
||||
if err := sleep(res.Header.Get("Retry-After")); err != nil {
|
||||
if err := sleep(retry); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -723,7 +743,7 @@ func (c *Client) httpClient() *http.Client {
|
||||
}
|
||||
|
||||
func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error) {
|
||||
req, err := http.NewRequest("GET", urlStr, nil)
|
||||
req, err := c.newRequest("GET", urlStr, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -731,7 +751,7 @@ func (c *Client) get(ctx context.Context, urlStr string) (*http.Response, error)
|
||||
}
|
||||
|
||||
func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error) {
|
||||
req, err := http.NewRequest("HEAD", urlStr, nil)
|
||||
req, err := c.newRequest("HEAD", urlStr, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -739,7 +759,7 @@ func (c *Client) head(ctx context.Context, urlStr string) (*http.Response, error
|
||||
}
|
||||
|
||||
func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.Reader) (*http.Response, error) {
|
||||
req, err := http.NewRequest("POST", urlStr, body)
|
||||
req, err := c.newRequest("POST", urlStr, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -747,6 +767,19 @@ func (c *Client) post(ctx context.Context, urlStr, contentType string, body io.R
|
||||
return c.do(ctx, req)
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(method, url string, body io.Reader) (*http.Request, error) {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ua := userAgent
|
||||
if c.UserAgent != "" {
|
||||
ua += " " + c.UserAgent
|
||||
}
|
||||
req.Header.Set("User-Agent", ua)
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, error) {
|
||||
res, err := c.httpClient().Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
|
||||
4
third_party/crypto/acme/integration_test.go
vendored
4
third_party/crypto/acme/integration_test.go
vendored
@ -23,9 +23,9 @@ import (
|
||||
)
|
||||
|
||||
// This test works with Pebble and Let's Encrypt staging.
|
||||
// For pebble use: ACME_DIRECTORY_URL=https://localhost:14000/dir go test
|
||||
// For pebble use: ACME_DIRECTORY_URL=https://localhost:14000/dir go test -tags integration_test
|
||||
// For Let's Encrypt you'll need a publicly accessible HTTP server like `ngrok http 8080` and then
|
||||
// TEST_HOST=xxx.ngrok.io:8080 ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory TEST_ACCOUNT_GET=1 TEST_REVOKE=1 go test
|
||||
// TEST_HOST=xxx.ngrok.io:8080 ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory TEST_ACCOUNT_GET=1 TEST_REVOKE=1 go test -tags integration_test
|
||||
func TestIntegration(t *testing.T) {
|
||||
dir := os.Getenv("ACME_DIRECTORY_URL")
|
||||
testAccountGet := os.Getenv("TEST_ACCOUNT_GET") != ""
|
||||
|
||||
11
third_party/crypto/acme/types.go
vendored
11
third_party/crypto/acme/types.go
vendored
@ -20,7 +20,6 @@ const (
|
||||
StatusInvalid = "invalid"
|
||||
StatusRevoked = "revoked"
|
||||
StatusDeactivated = "deactivated"
|
||||
StatusReady = "ready"
|
||||
)
|
||||
|
||||
// CRLReasonCode identifies the reason for a certificate revocation.
|
||||
@ -216,7 +215,7 @@ type Order struct {
|
||||
URL string
|
||||
|
||||
// Status is the status of the order. It will be one of StatusPending,
|
||||
// StatusReady, StatusProcessing, StatusValid, and StatusInvalid.
|
||||
// StatusProcessing, StatusValid, and StatusInvalid.
|
||||
Status string
|
||||
|
||||
// Expires is the teimstamp after which the server will consider the order invalid.
|
||||
@ -287,6 +286,9 @@ type Authorization struct {
|
||||
// Identifier is the identifier that the account is authorized to represent.
|
||||
Identifier AuthzID
|
||||
|
||||
// Wildcard is true if the authorization is for the base domain of a wildcard identifier.
|
||||
Wildcard bool
|
||||
|
||||
// Expires is the timestamp after which the server will consider this authorization invalid.
|
||||
Expires time.Time
|
||||
|
||||
@ -294,9 +296,6 @@ type Authorization struct {
|
||||
// to prove posession of the identifier. For valid/invalid authorizations,
|
||||
// this is the list of challenges that were used.
|
||||
Challenges []*Challenge
|
||||
|
||||
// Wildcard is set to true if this authorization is for a 'wildcard' dnsName.
|
||||
Wildcard bool
|
||||
}
|
||||
|
||||
// AuthzID is an identifier that an account is authorized to represent.
|
||||
@ -328,8 +327,8 @@ func (z *wireAuthz) authorization(url string) *Authorization {
|
||||
Status: z.Status,
|
||||
Expires: z.Expires,
|
||||
Identifier: AuthzID{Type: z.Identifier.Type, Value: z.Identifier.Value},
|
||||
Challenges: make([]*Challenge, len(z.Challenges)),
|
||||
Wildcard: z.Wildcard,
|
||||
Challenges: make([]*Challenge, len(z.Challenges)),
|
||||
}
|
||||
for i, v := range z.Challenges {
|
||||
a.Challenges[i] = v.challenge()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user