Commit 1818b1ea authored by Matthew Holt's avatar Matthew Holt

letsencrypt: Better error handling, prompt user for SA

parent b67543f8
...@@ -62,19 +62,19 @@ func Activate(configs []server.Config) ([]server.Config, error) { ...@@ -62,19 +62,19 @@ func Activate(configs []server.Config) ([]server.Config, error) {
// make client to service this email address with CA server // make client to service this email address with CA server
client, err := newClient(leEmail) client, err := newClient(leEmail)
if err != nil { if err != nil {
return configs, err return configs, errors.New("error creating client: " + err.Error())
} }
// client is ready, so let's get free, trusted SSL certificates! yeah! // client is ready, so let's get free, trusted SSL certificates! yeah!
certificates, err := obtainCertificates(client, serverConfigs) certificates, err := obtainCertificates(client, serverConfigs)
if err != nil { if err != nil {
return configs, err return configs, errors.New("error obtaining cert: " + err.Error())
} }
// ... that's it. save the certs, keys, and metadata files to disk // ... that's it. save the certs, keys, and metadata files to disk
err = saveCertsAndKeys(certificates) err = saveCertsAndKeys(certificates)
if err != nil { if err != nil {
return configs, err return configs, errors.New("error saving assets: " + err.Error())
} }
// it all comes down to this: turning TLS on for all the configs // it all comes down to this: turning TLS on for all the configs
...@@ -158,7 +158,10 @@ func newClient(leEmail string) (*acme.Client, error) { ...@@ -158,7 +158,10 @@ func newClient(leEmail string) (*acme.Client, error) {
} }
// The client facilitates our communication with the CA server. // The client facilitates our communication with the CA server.
client := acme.NewClient(CAUrl, &leUser, rsaKeySizeToUse, exposePort) client, err := acme.NewClient(CAUrl, &leUser, rsaKeySizeToUse, exposePort)
if err != nil {
return nil, err
}
// If not registered, the user must register an account with the CA // If not registered, the user must register an account with the CA
// and agree to terms // and agree to terms
...@@ -169,7 +172,13 @@ func newClient(leEmail string) (*acme.Client, error) { ...@@ -169,7 +172,13 @@ func newClient(leEmail string) (*acme.Client, error) {
} }
leUser.Registration = reg leUser.Registration = reg
// TODO: we can just do the agreement once: when registering, right? if !Agreed && reg.TosURL == "" {
Agreed = promptUserAgreement("<TODO>", false) // TODO
}
if !Agreed && reg.TosURL == "" {
return nil, errors.New("user must agree to terms")
}
err = client.AgreeToTOS() err = client.AgreeToTOS()
if err != nil { if err != nil {
saveUser(leUser) // TODO: Might as well try, right? Error check? saveUser(leUser) // TODO: Might as well try, right? Error check?
......
...@@ -34,7 +34,8 @@ func keepCertificatesRenewed(configs []server.Config) { ...@@ -34,7 +34,8 @@ func keepCertificatesRenewed(configs []server.Config) {
// checkCertificateRenewal loops through all configured // checkCertificateRenewal loops through all configured
// sites and looks for certificates to renew. Nothing is mutated // sites and looks for certificates to renew. Nothing is mutated
// through this function. The changes happen directly on disk. // through this function. The changes happen directly on disk.
// It returns the number of certificates renewed and // It returns the number of certificates renewed and any errors
// that occurred.
func processCertificateRenewal(configs []server.Config) (int, []error) { func processCertificateRenewal(configs []server.Config) (int, []error) {
log.Print("[INFO] Processing certificate renewals...") log.Print("[INFO] Processing certificate renewals...")
var errs []error var errs []error
......
...@@ -156,6 +156,29 @@ func getEmail(cfg server.Config) string { ...@@ -156,6 +156,29 @@ func getEmail(cfg server.Config) string {
return strings.TrimSpace(leEmail) return strings.TrimSpace(leEmail)
} }
// promptUserAgreement prompts the user to agree to the agreement
// at agreementURL via stdin. If the agreement has changed, then pass
// true as the second argument. If this is the user's first time
// agreeing, pass false. It returns whether the user agreed or not.
func promptUserAgreement(agreementURL string, changed bool) bool {
if changed {
fmt.Printf("The Let's Encrypt Subscriber Agreement has changed:\n%s\n", agreementURL)
fmt.Print("Do you agree to the new terms? (y/n): ")
} else {
fmt.Printf("To continue, you must agree to the Let's Encrypt Subscriber Agreement:\n%s\n", agreementURL)
fmt.Print("Do you agree to the terms? (y/n): ")
}
reader := bufio.NewReader(stdin) // TODO/BUG: This doesn't work when Caddyfile is piped into caddy
answer, err := reader.ReadString('\n')
if err != nil {
return false
}
answer = strings.ToLower(strings.TrimSpace(answer))
return answer == "y" || answer == "yes"
}
// stdin is used to read the user's input if prompted; // stdin is used to read the user's input if prompted;
// this is changed by tests during tests. // this is changed by tests during tests.
var stdin = io.ReadWriter(os.Stdin) var stdin = io.ReadWriter(os.Stdin)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment