Переглянути джерело

acme: prompt for terms agreement

Allow Client.Register callers to report CA terms agreement,
simplifying the registration usage.

Change-Id: Ia2c237f31c8375b5ae669bbd07d9294c329f59b8
Reviewed-on: https://go-review.googlesource.com/23973
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Alex Vaghin 9 роки тому
батько
коміт
1da79bda50

+ 24 - 2
acme/internal/acme/acme.go

@@ -185,13 +185,35 @@ func (c *Client) FetchCert(ctx context.Context, url string, bundle bool) ([][]by
 	}
 }
 
+// AcceptTOS always returns true to indicate the acceptance of a CA Terms of Service
+// during account registration. See Register method of Client for more details.
+func AcceptTOS(string) bool { return true }
+
 // Register creates a new account registration by following the "new-reg" flow.
 // It returns registered account. The a argument is not modified.
-func (c *Client) Register(a *Account) (*Account, error) {
+//
+// The registration may require the caller to agree to the CA Terms of Service (TOS).
+// If so, and the account has not indicated the acceptance of the terms (see Account for details),
+// Register calls prompt with a TOS URL provided by the CA. Prompt should report
+// whether the caller agrees to the terms. To always accept the terms, the caller can use AcceptTOS.
+func (c *Client) Register(a *Account, prompt func(tos string) bool) (*Account, error) {
 	if _, err := c.Discover(); err != nil {
 		return nil, err
 	}
-	return c.doReg(c.dir.RegURL, "new-reg", a)
+
+	var err error
+	if a, err = c.doReg(c.dir.RegURL, "new-reg", a); err != nil {
+		return nil, err
+	}
+	var accept bool
+	if a.CurrentTerms != "" && a.CurrentTerms != a.AgreedTerms {
+		accept = prompt(a.CurrentTerms)
+	}
+	if accept {
+		a.AgreedTerms = a.CurrentTerms
+		a, err = c.UpdateReg(a)
+	}
+	return a, err
 }
 
 // GetReg retrieves an existing registration.

+ 9 - 1
acme/internal/acme/acme_test.go

@@ -117,10 +117,18 @@ func TestRegister(t *testing.T) {
 	}))
 	defer ts.Close()
 
+	prompt := func(url string) bool {
+		const terms = "https://ca.tld/acme/terms"
+		if url != terms {
+			t.Errorf("prompt url = %q; want %q", url, terms)
+		}
+		return false
+	}
+
 	c := Client{Key: testKey, dir: &Directory{RegURL: ts.URL}}
 	a := &Account{Contact: contacts}
 	var err error
-	if a, err = c.Register(a); err != nil {
+	if a, err = c.Register(a, prompt); err != nil {
 		t.Fatal(err)
 	}
 	if a.URI != "https://ca.tld/acme/reg/1" {

+ 2 - 1
acme/internal/acme/types.go

@@ -25,7 +25,8 @@ type Account struct {
 	Contact []string
 
 	// The terms user has agreed to.
-	// Zero value indicates that the user hasn't agreed yet.
+	// A value not matching CurrentTerms indicates that the user hasn't agreed
+	// to the actual Terms of Service of the CA.
 	AgreedTerms string
 
 	// Actual terms of a CA.