From 9a424abdee87489eca675c1a33955aaa5e7e0394 Mon Sep 17 00:00:00 2001 From: Adrien Carbonne Date: Wed, 10 Feb 2016 16:55:10 +0100 Subject: [PATCH] Using the standard provider way Other providers should be used with the SetChallengeProvider function and should supply a New function. In your case this would be NewHTTPProviderWebroot taking the path as an argument. --- acme/client.go | 16 ---------------- acme/http_challenge_test.go | 6 +++--- acme/http_challenge_webroot.go | 33 +++++++++++++++++++++++++++------ cli_handlers.go | 7 ++++++- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/acme/client.go b/acme/client.go index 119e0d94..700aeab5 100644 --- a/acme/client.go +++ b/acme/client.go @@ -12,7 +12,6 @@ import ( "io/ioutil" "log" "net" - "os" "regexp" "strconv" "strings" @@ -117,21 +116,6 @@ func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider) return nil } -// SetWebRoot specifies a custom folder path to be used for HTTP based challenges. -// If this option is used, lego will not bind any port to listen to, -// instead it will write the challenge in a file into path/.well-known/acme-challenge/ -func (c *Client) SetWebRoot(path string) error { - if _, err := os.Stat(path); os.IsNotExist(err) { - return err - } - - if chlng, ok := c.solvers[HTTP01]; ok { - chlng.(*httpChallenge).provider = &httpChallengeWebRoot{path: path} - } - - return nil -} - // SetHTTPAddress specifies a custom interface:port to be used for HTTP based challenges. // If this option is not used, the default port 80 and all interfaces will be used. // To only specify a port and no interface use the ":port" notation. diff --git a/acme/http_challenge_test.go b/acme/http_challenge_test.go index ff41c209..56f07345 100644 --- a/acme/http_challenge_test.go +++ b/acme/http_challenge_test.go @@ -79,7 +79,7 @@ func TestHTTPChallengeWebRoot(t *testing.T) { return nil } - solver := &httpChallenge{jws: j, validate: mockValidate, provider: &httpChallengeWebRoot{path: "webroot"}} + solver := &httpChallenge{jws: j, validate: mockValidate, provider: &HTTPProviderWebroot{path: "webroot"}} os.MkdirAll("webroot/.well-known/acme-challenge", 0777) if err := solver.Solve(clientChallenge, "localhost:23457"); err != nil { @@ -92,11 +92,11 @@ func TestHTTPChallengeWebRootInvalidPath(t *testing.T) { privKey, _ := generatePrivateKey(rsakey, 128) j := &jws{privKey: privKey.(*rsa.PrivateKey)} clientChallenge := challenge{Type: HTTP01, Token: "http2"} - solver := &httpChallenge{jws: j, validate: stubValidate, provider: &httpChallengeWebRoot{path: "/invalid-path-123456"}} + solver := &httpChallenge{jws: j, validate: stubValidate, provider: &HTTPProviderWebroot{path: "/invalid-\000-path"}} if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil { t.Errorf("Solve error: got %v, want error", err) - } else if want := "Could not write file in webroot"; !strings.Contains(err.Error(), want) { + } else if want := "Could not create required directories in webroot"; !strings.Contains(err.Error(), want) { t.Errorf("Solve error: got %q, want content %q", err.Error(), want) } } diff --git a/acme/http_challenge_webroot.go b/acme/http_challenge_webroot.go index caece376..914d2545 100644 --- a/acme/http_challenge_webroot.go +++ b/acme/http_challenge_webroot.go @@ -7,15 +7,35 @@ import ( "path" ) -// httpChallengeWebRoot implements ChallengeProvider for `http-01` challenge -type httpChallengeWebRoot struct { +// HTTPProviderWebroot implements ChallengeProvider for `http-01` challenge +type HTTPProviderWebroot struct { path string } -// Present makes the token available at `HTTP01ChallengePath(token)` -func (w *httpChallengeWebRoot) Present(domain, token, keyAuth string) error { +// NewHTTPProviderWebroot returns a HTTPProviderWebroot instance with a configured webroot path +func NewHTTPProviderWebroot(path string) (*HTTPProviderWebroot, error) { + if _, err := os.Stat(path); os.IsNotExist(err) { + return nil, fmt.Errorf("Webroot path does not exist") + } + + c := &HTTPProviderWebroot{ + path: path, + } + + return c, nil +} + +// Present makes the token available at `HTTP01ChallengePath(token)` by creating a file in the given webroot path +func (w *HTTPProviderWebroot) Present(domain, token, keyAuth string) error { var err error - err = ioutil.WriteFile(path.Join(w.path, HTTP01ChallengePath(token)), []byte(keyAuth), 0777) + + challengeFilePath := path.Join(w.path, HTTP01ChallengePath(token)) + err = os.MkdirAll(path.Dir(challengeFilePath), 0777) + if err != nil { + return fmt.Errorf("Could not create required directories in webroot for HTTP challenge -> %v", err) + } + + err = ioutil.WriteFile(challengeFilePath, []byte(keyAuth), 0777) if err != nil { return fmt.Errorf("Could not write file in webroot for HTTP challenge -> %v", err) } @@ -23,7 +43,8 @@ func (w *httpChallengeWebRoot) Present(domain, token, keyAuth string) error { return nil } -func (w *httpChallengeWebRoot) CleanUp(domain, token, keyAuth string) error { +// CleanUp removes the file created for the challenge +func (w *HTTPProviderWebroot) CleanUp(domain, token, keyAuth string) error { var err error err = os.Remove(path.Join(w.path, HTTP01ChallengePath(token))) if err != nil { diff --git a/cli_handlers.go b/cli_handlers.go index d9da8357..eda355b5 100644 --- a/cli_handlers.go +++ b/cli_handlers.go @@ -44,7 +44,12 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) { } if c.GlobalIsSet("webroot") { - client.SetWebRoot(c.GlobalString("webroot")) + provider, err := acme.NewHTTPProviderWebroot(c.GlobalString("webroot")) + if err != nil { + logger().Fatal(err) + } + + client.SetChallengeProvider(HTTP01, provider) } if c.GlobalIsSet("http") { client.SetHTTPAddress(c.GlobalString("http"))