From 56d50cebd8cd8d7717bf6a43683a62f7cd89037b Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Tue, 27 Oct 2015 17:00:42 -0600 Subject: [PATCH 1/2] Replaced fatal with print; return errors from NewClient --- README.md | 5 ++++- acme/client.go | 49 ++++++++++++++++++++++++++++++--------------- acme/client_test.go | 5 ++++- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1e5b1dfb..e6d67c9f 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,10 @@ myUser := MyUser{ // configured for a local dev instance of Boulder running in Docker in a VM. // We specify an optPort of 5001 because we aren't running as root and can't // bind a listener to port 443 (used later when we attempt to pass challenge). -client := acme.NewClient("http://192.168.99.100:4000", &myUser, rsaKeySize, "5001") +client, err := acme.NewClient("http://192.168.99.100:4000", &myUser, rsaKeySize, "5001") +if err != inl { + log.Fatal(err) +} // New users will need to register; be sure to save it reg, err := client.Register() diff --git a/acme/client.go b/acme/client.go index 63c65059..d3fb6223 100644 --- a/acme/client.go +++ b/acme/client.go @@ -54,13 +54,19 @@ type Client struct { // NewClient creates a new client for the set user. // caURL - The root url to the boulder instance you want certificates from // usr - A filled in user struct +// keyBits - Size of the key in bits // optPort - The alternative port to listen on for challenges. -// devMode - If set to true, all CanSolve() checks are skipped. -func NewClient(caURL string, usr User, keyBits int, optPort string) *Client { - if err := usr.GetPrivateKey().Validate(); err != nil { - logger().Fatalf("Could not validate the private account key of %s\n\t%v", usr.GetEmail(), err) +func NewClient(caURL string, usr User, keyBits int, optPort string) (*Client, error) { + privKey := usr.GetPrivateKey() + if privKey == nil { + return nil, errors.New("private key was nil") } - jws := &jws{privKey: usr.GetPrivateKey()} + + if err := privKey.Validate(); err != nil { + return nil, fmt.Errorf("invalid private key: %v", err) + } + + jws := &jws{privKey: privKey} // REVIEW: best possibility? // Add all available solvers with the right index as per ACME @@ -68,23 +74,33 @@ func NewClient(caURL string, usr User, keyBits int, optPort string) *Client { solvers := make(map[string]solver) solvers["simpleHttp"] = &simpleHTTPChallenge{jws: jws, optPort: optPort} - dirResp, err := http.Get(caURL + "/directory") + dirURL := caURL + "/directory" + dirResp, err := http.Get(dirURL) if err != nil { - logger().Fatalf("Could not get directory from CA URL. Please check the URL.\n\t%v", err) + return nil, fmt.Errorf("get directory at '%s': %v", dirURL, err) } defer dirResp.Body.Close() var dir directory - decoder := json.NewDecoder(dirResp.Body) - err = decoder.Decode(&dir) + err = json.NewDecoder(dirResp.Body).Decode(&dir) if err != nil { - logger().Fatalf("Could not parse directory response from CA URL.\n\t%v", err) - } - if dir.NewRegURL == "" || dir.NewAuthzURL == "" || dir.NewCertURL == "" || dir.RevokeCertURL == "" { - logger().Fatal("The directory returned by the server was invalid.") + return nil, fmt.Errorf("decode directory: %v", err) } - return &Client{directory: dir, user: usr, jws: jws, keyBits: keyBits, solvers: solvers} + if dir.NewRegURL == "" { + return nil, errors.New("directory missing new registration URL") + } + if dir.NewAuthzURL == "" { + return nil, errors.New("directory missing new authz URL") + } + if dir.NewCertURL == "" { + return nil, errors.New("directory missing new certificate URL") + } + if dir.RevokeCertURL == "" { + return nil, errors.New("directory missing revoke certificate URL") + } + + return &Client{directory: dir, user: usr, jws: jws, keyBits: keyBits, solvers: solvers}, nil } // Register the current account to the ACME server. @@ -359,7 +375,8 @@ func (c *Client) getChallenges(domains []string) []*authorizationResource { links := parseLinks(resp.Header["Link"]) if links["next"] == "" { - logger().Fatalln("The server did not provide enough information to proceed.") + logger().Println("The server did not provide enough information to proceed.") + return } var authz authorization @@ -506,7 +523,7 @@ func (c *Client) requestCertificate(authz *authorizationResource, result chan Ce break default: - logger().Fatalf("[%s] The server returned an unexpected status code %d.", authz.Domain, resp.StatusCode) + logger().Printf("[%s] The server returned an unexpected status code %d.", authz.Domain, resp.StatusCode) return } diff --git a/acme/client_test.go b/acme/client_test.go index d55f4984..228ab977 100644 --- a/acme/client_test.go +++ b/acme/client_test.go @@ -27,7 +27,10 @@ func TestNewClient(t *testing.T) { })) caURL, optPort := ts.URL, "1234" - client := NewClient(caURL, user, keyBits, optPort) + client, err := NewClient(caURL, user, keyBits, optPort) + if err != nil { + t.Fatalf("Could not create client: %v", err) + } if client.jws == nil { t.Fatalf("Expected client.jws to not be nil") From ef2501bb4c9b36c98b7f50a48a565727f7919cd2 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Tue, 27 Oct 2015 17:05:40 -0600 Subject: [PATCH 2/2] Update CLI for new NewClient signature --- cli_handlers.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cli_handlers.go b/cli_handlers.go index 253e1e8d..f295c14c 100644 --- a/cli_handlers.go +++ b/cli_handlers.go @@ -32,7 +32,13 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) { //TODO: move to account struct? Currently MUST pass email. acc := NewAccount(c.GlobalString("email"), conf) - return conf, acc, acme.NewClient(c.GlobalString("server"), acc, conf.RsaBits(), conf.OptPort()) + + client, err := acme.NewClient(c.GlobalString("server"), acc, conf.RsaBits(), conf.OptPort()) + if err != nil { + logger().Fatal("Could not create client:", err) + } + + return conf, acc, client } func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {