Browse Source

acme: implement authorization revocation

As with other methods of the Client, this is an implementation
for the v2 version of the spec.

Change-Id: I7fa7e0b700212992125de32524801048b56ac5d0
Reviewed-on: https://go-review.googlesource.com/28593
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Alex Vaghin 9 years ago
parent
commit
f944096df8
2 changed files with 62 additions and 0 deletions
  1. 28 0
      acme/acme.go
  2. 34 0
      acme/acme_test.go

+ 28 - 0
acme/acme.go

@@ -380,6 +380,34 @@ func (c *Client) GetAuthorization(ctx context.Context, url string) (*Authorizati
 	return v.authorization(url), nil
 	return v.authorization(url), nil
 }
 }
 
 
+// RevokeAuthorization relinquishes an existing authorization identified
+// by the given URL.
+// The url argument is an Authorization.URI value.
+//
+// If successful, the caller will be required to obtain a new authorization
+// using the Authorize method before being able to request a new certificate
+// for the domain associated with the authorization.
+//
+// It does not revoke existing certificates.
+func (c *Client) RevokeAuthorization(ctx context.Context, url string) error {
+	req := struct {
+		Resource string `json:"resource"`
+		Delete   bool   `json:"delete"`
+	}{
+		Resource: "authz",
+		Delete:   true,
+	}
+	res, err := postJWS(ctx, c.HTTPClient, c.Key, url, req)
+	if err != nil {
+		return err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != http.StatusOK {
+		return responseError(res)
+	}
+	return nil
+}
+
 // WaitAuthorization polls an authorization at the given URL
 // WaitAuthorization polls an authorization at the given URL
 // until it is in one of the final states, StatusValid or StatusInvalid,
 // until it is in one of the final states, StatusValid or StatusInvalid,
 // or the context is done.
 // or the context is done.

+ 34 - 0
acme/acme_test.go

@@ -552,6 +552,40 @@ func TestWaitAuthorizationCancel(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestRevokeAuthorization(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
+		}
+		switch r.URL.Path {
+		case "/1":
+			var req struct {
+				Resource string
+				Delete   bool
+			}
+			decodeJWSRequest(t, &req, r)
+			if req.Resource != "authz" {
+				t.Errorf("req.Resource = %q; want authz", req.Resource)
+			}
+			if !req.Delete {
+				t.Errorf("req.Delete is false")
+			}
+		case "/2":
+			w.WriteHeader(http.StatusInternalServerError)
+		}
+	}))
+	defer ts.Close()
+	client := &Client{Key: testKey}
+	ctx := context.Background()
+	if err := client.RevokeAuthorization(ctx, ts.URL+"/1"); err != nil {
+		t.Errorf("err = %v", err)
+	}
+	if client.RevokeAuthorization(ctx, ts.URL+"/2") == nil {
+		t.Error("nil error")
+	}
+}
+
 func TestPollChallenge(t *testing.T) {
 func TestPollChallenge(t *testing.T) {
 	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		if r.Method != "GET" {
 		if r.Method != "GET" {