mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
letsencrypt: Re-prompt user if obtaining certs fails due to updated SA
This commit is contained in:
parent
2712dcd1f5
commit
be0fb0053d
3 changed files with 45 additions and 10 deletions
|
@ -7,7 +7,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -84,11 +83,35 @@ func Activate(configs []server.Config) ([]server.Config, error) {
|
|||
}
|
||||
|
||||
// client is ready, so let's get free, trusted SSL certificates! yeah!
|
||||
Obtain:
|
||||
certificates, failures := obtainCertificates(client, serverConfigs)
|
||||
if len(failures) > 0 {
|
||||
for k, v := range failures {
|
||||
log.Printf("[%s] Failed to get a certificate: %s", k, v)
|
||||
// Build an error string to return, using all the failures in the list.
|
||||
var errMsg string
|
||||
|
||||
// An agreement error means we need to prompt the user (once) with updated terms
|
||||
// while they're still here.
|
||||
var promptedUpdatedTerms bool
|
||||
|
||||
for domain, obtainErr := range failures {
|
||||
// If the failure was simply because the terms have changed, re-prompt and re-try
|
||||
if tosErr, ok := obtainErr.(acme.TOSError); ok && !promptedUpdatedTerms {
|
||||
Agreed = promptUserAgreement(tosErr.Detail, true) // TODO: Use latest URL
|
||||
promptedUpdatedTerms = true
|
||||
if Agreed {
|
||||
err := client.AgreeToTOS()
|
||||
if err != nil {
|
||||
return configs, errors.New("error agreeing to updated terms: " + err.Error())
|
||||
}
|
||||
goto Obtain
|
||||
}
|
||||
}
|
||||
|
||||
// If user did not agree or it was any other kind of error, just append to the list of errors
|
||||
errMsg += "[" + domain + "] failed to get certificate: " + obtainErr.Error() + "\n"
|
||||
}
|
||||
|
||||
return configs, errors.New(errMsg)
|
||||
}
|
||||
|
||||
// ... that's it. save the certs, keys, and metadata files to disk
|
||||
|
@ -213,7 +236,7 @@ func newClient(leEmail string) (*acme.Client, error) {
|
|||
leUser.Registration = reg
|
||||
|
||||
if !Agreed && reg.TosURL == "" {
|
||||
Agreed = promptUserAgreement("<TODO>", false) // TODO
|
||||
Agreed = promptUserAgreement(saURL, false) // TODO - latest URL
|
||||
}
|
||||
if !Agreed && reg.TosURL == "" {
|
||||
return nil, errors.New("user must agree to terms")
|
||||
|
|
|
@ -97,8 +97,8 @@ func renewCertificates(configs []server.Config) (int, []error) {
|
|||
// Directly convert it to days for the following checks.
|
||||
daysLeft := int(expTime.Sub(time.Now().UTC()).Hours() / 24)
|
||||
|
||||
// Renew with a week or less remaining.
|
||||
if daysLeft <= 7 {
|
||||
// Renew with two weeks or less remaining.
|
||||
if daysLeft <= 14 {
|
||||
log.Printf("[INFO] There are %d days left on the certificate of %s. Trying to renew now.", daysLeft, cfg.Host)
|
||||
client, err := newClient("") // email not used for renewal
|
||||
if err != nil {
|
||||
|
@ -127,8 +127,17 @@ func renewCertificates(configs []server.Config) (int, []error) {
|
|||
// Renew certificate.
|
||||
// TODO: revokeOld should be an option in the caddyfile
|
||||
// TODO: bundle should be an option in the caddyfile as well :)
|
||||
Renew:
|
||||
newCertMeta, err := client.RenewCertificate(certMeta, true, true)
|
||||
if err != nil {
|
||||
if _, ok := err.(acme.TOSError); ok {
|
||||
err := client.AgreeToTOS()
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
goto Renew
|
||||
}
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
newCertMeta, err = client.RenewCertificate(certMeta, true, true)
|
||||
if err != nil {
|
||||
|
|
|
@ -146,9 +146,9 @@ func getEmail(cfg server.Config) string {
|
|||
reader := bufio.NewReader(stdin)
|
||||
fmt.Println("Your sites will be served over HTTPS automatically using Let's Encrypt.")
|
||||
fmt.Println("By continuing, you agree to the Let's Encrypt Subscriber Agreement at:")
|
||||
fmt.Println(" https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf") // TODO: Show current SA link
|
||||
fmt.Println(" " + saURL) // TODO: Show current SA link
|
||||
fmt.Println("Please enter your email address so you can recover your account if needed.")
|
||||
fmt.Println("You can leave it blank, but you lose the ability to recover your account.")
|
||||
fmt.Println("You can leave it blank, but you'll lose the ability to recover your account.")
|
||||
fmt.Print("Email address: ")
|
||||
var err error
|
||||
leEmail, err = reader.ReadString('\n')
|
||||
|
@ -167,10 +167,10 @@ func getEmail(cfg server.Config) string {
|
|||
// 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.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.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): ")
|
||||
}
|
||||
|
||||
|
@ -191,3 +191,6 @@ var stdin = io.ReadWriter(os.Stdin)
|
|||
// The name of the folder for accounts where the email
|
||||
// address was not provided; default 'username' if you will.
|
||||
const emptyEmail = "default"
|
||||
|
||||
// TODO: Use latest
|
||||
const saURL = "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
|
||||
|
|
Loading…
Reference in a new issue