acme: add StatusValid to expected values for Authorize

Let's Encrypt may respond with the "valid" value in status
field to authorization requests:
https://github.com/letsencrypt/boulder/blob/0543691d9e2cbcc1b94baf3b9fab4e64ca2750ef/ra/ra.go#L373-L402

The spec isn't clear on this:
https://tools.ietf.org/html/draft-ietf-acme-acme-02#section-6.4

Either way, this change follows common sense and should not produce
unexpected results.

Change-Id: Iac55aa1fb17d458f6d62e8da875ed86e3e4afbc3
Reviewed-on: https://go-review.googlesource.com/27432
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Alex Vaghin
2016-08-22 17:42:09 +00:00
parent 7e016f1856
commit 1ba5ec0bf2
3 changed files with 27 additions and 1 deletions
+5
View File
@@ -404,6 +404,11 @@ func (m *Manager) verify(ctx context.Context, domain string) error {
if err != nil {
return err
}
// maybe don't need to at all
if authz.Status == acme.StatusValid {
return nil
}
// pick a challenge: prefer tls-sni-02 over tls-sni-01
// TODO: consider authz.Combinations
var chal *acme.Challenge
+5 -1
View File
@@ -302,6 +302,10 @@ func (c *Client) UpdateReg(ctx context.Context, a *Account) (*Account, error) {
// Authorize performs the initial step in an authorization flow.
// The caller will then need to choose from and perform a set of returned
// challenges using c.Accept in order to successfully complete authorization.
//
// If an authorization has been previously granted, the CA may return
// a valid authorization (Authorization.Status is StatusValid). If so, the caller
// need not fulfill any challenge and can proceed to requesting a certificate.
func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization, error) {
if _, err := c.Discover(ctx); err != nil {
return nil, err
@@ -331,7 +335,7 @@ func (c *Client) Authorize(ctx context.Context, domain string) (*Authorization,
if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
return nil, fmt.Errorf("acme: invalid response: %v", err)
}
if v.Status != StatusPending {
if v.Status != StatusPending && v.Status != StatusValid {
return nil, fmt.Errorf("acme: unexpected status: %s", v.Status)
}
return v.authorization(res.Header.Get("Location")), nil
+17
View File
@@ -368,6 +368,23 @@ func TestAuthorize(t *testing.T) {
}
}
func TestAuthorizeValid(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
w.Header().Set("replay-nonce", "nonce")
return
}
w.WriteHeader(http.StatusCreated)
w.Write([]byte(`{"status":"valid"}`))
}))
defer ts.Close()
client := Client{Key: testKey, dir: &Directory{AuthzURL: ts.URL}}
_, err := client.Authorize(context.Background(), "example.com")
if err != nil {
t.Errorf("err = %v", err)
}
}
func TestPollAuthz(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {