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.
This commit is contained in:
Adrien Carbonne 2016-02-10 16:55:10 +01:00
parent fdf059fbbd
commit 9a424abdee
4 changed files with 36 additions and 26 deletions

View file

@ -12,7 +12,6 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"net" "net"
"os"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -117,21 +116,6 @@ func (c *Client) SetChallengeProvider(challenge Challenge, p ChallengeProvider)
return nil 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. // 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. // 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. // To only specify a port and no interface use the ":port" notation.

View file

@ -79,7 +79,7 @@ func TestHTTPChallengeWebRoot(t *testing.T) {
return nil 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) os.MkdirAll("webroot/.well-known/acme-challenge", 0777)
if err := solver.Solve(clientChallenge, "localhost:23457"); err != nil { if err := solver.Solve(clientChallenge, "localhost:23457"); err != nil {
@ -92,11 +92,11 @@ func TestHTTPChallengeWebRootInvalidPath(t *testing.T) {
privKey, _ := generatePrivateKey(rsakey, 128) privKey, _ := generatePrivateKey(rsakey, 128)
j := &jws{privKey: privKey.(*rsa.PrivateKey)} j := &jws{privKey: privKey.(*rsa.PrivateKey)}
clientChallenge := challenge{Type: HTTP01, Token: "http2"} 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 { if err := solver.Solve(clientChallenge, "localhost:123456"); err == nil {
t.Errorf("Solve error: got %v, want error", err) 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) t.Errorf("Solve error: got %q, want content %q", err.Error(), want)
} }
} }

View file

@ -7,15 +7,35 @@ import (
"path" "path"
) )
// httpChallengeWebRoot implements ChallengeProvider for `http-01` challenge // HTTPProviderWebroot implements ChallengeProvider for `http-01` challenge
type httpChallengeWebRoot struct { type HTTPProviderWebroot struct {
path string path string
} }
// Present makes the token available at `HTTP01ChallengePath(token)` // NewHTTPProviderWebroot returns a HTTPProviderWebroot instance with a configured webroot path
func (w *httpChallengeWebRoot) Present(domain, token, keyAuth string) error { 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 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 { if err != nil {
return fmt.Errorf("Could not write file in webroot for HTTP challenge -> %v", err) 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 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 var err error
err = os.Remove(path.Join(w.path, HTTP01ChallengePath(token))) err = os.Remove(path.Join(w.path, HTTP01ChallengePath(token)))
if err != nil { if err != nil {

View file

@ -44,7 +44,12 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
} }
if c.GlobalIsSet("webroot") { 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") { if c.GlobalIsSet("http") {
client.SetHTTPAddress(c.GlobalString("http")) client.SetHTTPAddress(c.GlobalString("http"))