acme: improve http-01 challenge API

This makes http-01 handling more consistent with tls-sni-* methods
and, hopefully, future implementation such as dns-01 and oob-01.

Change-Id: If1a4a47ee8528ef19960fee4e6860392c1813fe6
Reviewed-on: https://go-review.googlesource.com/27011
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Alex Vaghin
2016-08-16 19:51:47 +00:00
parent f0e11a3ccc
commit 1f83de14df
2 changed files with 36 additions and 15 deletions
+16 -15
View File
@@ -377,22 +377,23 @@ func (c *Client) Accept(ctx context.Context, chal *Challenge) (*Challenge, error
return v.challenge(), nil
}
// HTTP01Handler creates a new handler which responds to a http-01 challenge.
// HTTP01ChallengeResponse returns the response for an http-01 challenge.
// Servers should respond with the value to HTTP requests at the URL path
// provided by HTTP01ChallengePath to validate the challenge and prove control
// over a domain name.
//
// The token argument is a Challenge.Token value.
func (c *Client) HTTP01Handler(token string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !strings.HasSuffix(r.URL.Path, token) {
w.WriteHeader(http.StatusNotFound)
return
}
w.Header().Set("content-type", "text/plain")
auth, err := keyAuth(c.Key.Public(), token)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write([]byte(auth))
})
func (c *Client) HTTP01ChallengeResponse(token string) (string, error) {
return keyAuth(c.Key.Public(), token)
}
// HTTP01ChallengePath returns the URL path at which the response for an http-01 challenge
// should be provided by the servers.
// The response value can be obtained with HTTP01ChallengeResponse.
//
// The token argument is a Challenge.Token value.
func (c *Client) HTTP01ChallengePath(token string) string {
return "/.well-known/acme-challenge/" + token
}
// TLSSNI01ChallengeCert creates a certificate for TLS-SNI-01 challenge response.
+20
View File
@@ -892,3 +892,23 @@ func TestTLSSNI02ChallengeCert(t *testing.T) {
t.Errorf("%v doesn't have %q", cert.DNSNames, name)
}
}
func TestHTTP01Challenge(t *testing.T) {
const (
token = "xxx"
// thumbprint is precomputed for testKey in jws_test.go
value = token + "." + testKeyThumbprint
urlpath = "/.well-known/acme-challenge/" + token
)
client := &Client{Key: testKey}
val, err := client.HTTP01ChallengeResponse(token)
if err != nil {
t.Fatal(err)
}
if val != value {
t.Errorf("val = %q; want %q", val, value)
}
if path := client.HTTP01ChallengePath(token); path != urlpath {
t.Errorf("path = %q; want %q", path, urlpath)
}
}