refactor: use new logger.

This commit is contained in:
Fernandez Ludovic 2018-05-28 00:08:23 +02:00 committed by Ludovic Fernandez
parent 56911d8e18
commit eed8169a03
9 changed files with 99 additions and 133 deletions

View file

@ -8,6 +8,7 @@ import (
"path" "path"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
"github.com/xenolf/lego/log"
) )
// Account represents a users local saved credentials // Account represents a users local saved credentials
@ -25,23 +26,23 @@ func NewAccount(email string, conf *Configuration) *Account {
// TODO: move to function in configuration? // TODO: move to function in configuration?
accKeyPath := accKeysPath + string(os.PathSeparator) + email + ".key" accKeyPath := accKeysPath + string(os.PathSeparator) + email + ".key"
if err := checkFolder(accKeysPath); err != nil { if err := checkFolder(accKeysPath); err != nil {
logger().Fatalf("Could not check/create directory for account %s: %v", email, err) log.Fatalf("Could not check/create directory for account %s: %v", email, err)
} }
var privKey crypto.PrivateKey var privKey crypto.PrivateKey
if _, err := os.Stat(accKeyPath); os.IsNotExist(err) { if _, err := os.Stat(accKeyPath); os.IsNotExist(err) {
logger().Printf("No key found for account %s. Generating a curve P384 EC key.", email) log.Printf("No key found for account %s. Generating a curve P384 EC key.", email)
privKey, err = generatePrivateKey(accKeyPath) privKey, err = generatePrivateKey(accKeyPath)
if err != nil { if err != nil {
logger().Fatalf("Could not generate RSA private account key for account %s: %v", email, err) log.Fatalf("Could not generate RSA private account key for account %s: %v", email, err)
} }
logger().Printf("Saved key to %s", accKeyPath) log.Printf("Saved key to %s", accKeyPath)
} else { } else {
privKey, err = loadPrivateKey(accKeyPath) privKey, err = loadPrivateKey(accKeyPath)
if err != nil { if err != nil {
logger().Fatalf("Could not load RSA private key from file %s: %v", accKeyPath, err) log.Fatalf("Could not load RSA private key from file %s: %v", accKeyPath, err)
} }
} }
@ -52,13 +53,13 @@ func NewAccount(email string, conf *Configuration) *Account {
fileBytes, err := ioutil.ReadFile(accountFile) fileBytes, err := ioutil.ReadFile(accountFile)
if err != nil { if err != nil {
logger().Fatalf("Could not load file for account %s -> %v", email, err) log.Fatalf("Could not load file for account %s -> %v", email, err)
} }
var acc Account var acc Account
err = json.Unmarshal(fileBytes, &acc) err = json.Unmarshal(fileBytes, &acc)
if err != nil { if err != nil {
logger().Fatalf("Could not parse file for account %s -> %v", email, err) log.Fatalf("Could not parse file for account %s -> %v", email, err)
} }
acc.key = privKey acc.key = privKey
@ -67,7 +68,7 @@ func NewAccount(email string, conf *Configuration) *Account {
if acc.Registration == nil || acc.Registration.Body.Status == "" { if acc.Registration == nil || acc.Registration.Body.Status == "" {
reg, err := tryRecoverAccount(privKey, conf) reg, err := tryRecoverAccount(privKey, conf)
if err != nil { if err != nil {
logger().Fatalf("Could not load account for %s. Registration is nil -> %#v", email, err) log.Fatalf("Could not load account for %s. Registration is nil -> %#v", email, err)
} }
acc.Registration = reg acc.Registration = reg
@ -75,7 +76,7 @@ func NewAccount(email string, conf *Configuration) *Account {
} }
if acc.conf == nil { if acc.conf == nil {
logger().Fatalf("Could not load account for %s. Configuration is nil.", email) log.Fatalf("Could not load account for %s. Configuration is nil.", email)
} }
return &acc return &acc

View file

@ -8,17 +8,13 @@ import (
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"net" "net"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
)
var ( "github.com/xenolf/lego/log"
// Logger is an optional custom logger.
Logger *log.Logger
) )
const ( const (
@ -31,16 +27,6 @@ const (
overallRequestLimit = 18 overallRequestLimit = 18
) )
// logf writes a log entry. It uses Logger if not
// nil, otherwise it uses the default log.Logger.
func logf(format string, args ...interface{}) {
if Logger != nil {
Logger.Printf(format, args...)
} else {
log.Printf(format, args...)
}
}
// User interface is to be implemented by users of this library. // User interface is to be implemented by users of this library.
// It is used by the client type to get user specific information. // It is used by the client type to get user specific information.
type User interface { type User interface {
@ -159,7 +145,7 @@ func (c *Client) Register(tosAgreed bool) (*RegistrationResource, error) {
if c == nil || c.user == nil { if c == nil || c.user == nil {
return nil, errors.New("acme: cannot register a nil client or user") return nil, errors.New("acme: cannot register a nil client or user")
} }
logf("[INFO] acme: Registering account for %s", c.user.GetEmail()) log.Printf("[INFO] acme: Registering account for %s", c.user.GetEmail())
accMsg := accountMessage{} accMsg := accountMessage{}
if c.user.GetEmail() != "" { if c.user.GetEmail() != "" {
@ -239,7 +225,7 @@ func (c *Client) RegisterWithExternalAccountBinding(tosAgreed bool, kid string,
// ResolveAccountByKey will attempt to look up an account using the given account key // ResolveAccountByKey will attempt to look up an account using the given account key
// and return its registration resource. // and return its registration resource.
func (c *Client) ResolveAccountByKey() (*RegistrationResource, error) { func (c *Client) ResolveAccountByKey() (*RegistrationResource, error) {
logf("[INFO] acme: Trying to resolve account by key") log.Printf("[INFO] acme: Trying to resolve account by key")
acc := accountMessage{OnlyReturnExisting: true} acc := accountMessage{OnlyReturnExisting: true}
hdr, err := postJSON(c.jws, c.directory.NewAccountURL, acc, nil) hdr, err := postJSON(c.jws, c.directory.NewAccountURL, acc, nil)
@ -268,7 +254,7 @@ func (c *Client) DeleteRegistration() error {
if c == nil || c.user == nil { if c == nil || c.user == nil {
return errors.New("acme: cannot unregister a nil client or user") return errors.New("acme: cannot unregister a nil client or user")
} }
logf("[INFO] acme: Deleting account for %s", c.user.GetEmail()) log.Printf("[INFO] acme: Deleting account for %s", c.user.GetEmail())
accMsg := accountMessage{ accMsg := accountMessage{
Status: "deactivated", Status: "deactivated",
@ -292,7 +278,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) {
return nil, errors.New("acme: cannot query the registration of a nil client or user") return nil, errors.New("acme: cannot query the registration of a nil client or user")
} }
// Log the URL here instead of the email as the email may not be set // Log the URL here instead of the email as the email may not be set
logf("[INFO] acme: Querying account for %s", c.user.GetRegistration().URI) log.Printf("[INFO] acme: Querying account for %s", c.user.GetRegistration().URI)
accMsg := accountMessage{} accMsg := accountMessage{}
@ -338,9 +324,9 @@ DNSNames:
} }
if bundle { if bundle {
logf("[INFO][%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
} else { } else {
logf("[INFO][%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
} }
order, err := c.createOrderForIdentifiers(domains) order, err := c.createOrderForIdentifiers(domains)
@ -362,7 +348,7 @@ DNSNames:
return nil, err return nil, err
} }
logf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
failures := make(ObtainError) failures := make(ObtainError)
cert, err := c.requestCertificateForCsr(order, bundle, csr.Raw, nil) cert, err := c.requestCertificateForCsr(order, bundle, csr.Raw, nil)
@ -398,9 +384,9 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
} }
if bundle { if bundle {
logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
} else { } else {
logf("[INFO][%s] acme: Obtaining SAN certificate", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
} }
order, err := c.createOrderForIdentifiers(domains) order, err := c.createOrderForIdentifiers(domains)
@ -422,7 +408,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
return nil, err return nil, err
} }
logf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", ")) log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
failures := make(ObtainError) failures := make(ObtainError)
cert, err := c.requestCertificateForOrder(order, bundle, privKey, mustStaple) cert, err := c.requestCertificateForOrder(order, bundle, privKey, mustStaple)
@ -481,7 +467,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
// This is just meant to be informal for the user. // This is just meant to be informal for the user.
timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC()) timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
logf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours())) log.Printf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
// We always need to request a new certificate to renew. // We always need to request a new certificate to renew.
// Start by checking to see if the certificate was based off a CSR, and // Start by checking to see if the certificate was based off a CSR, and
@ -555,7 +541,7 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
for _, authz := range authorizations { for _, authz := range authorizations {
if authz.Status == "valid" { if authz.Status == "valid" {
// Boulder might recycle recent validated authz (see issue #267) // Boulder might recycle recent validated authz (see issue #267)
logf("[INFO][%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value) log.Printf("[INFO][%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
continue continue
} }
@ -586,7 +572,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) {
if solver, ok := c.solvers[Challenge(challenge.Type)]; ok { if solver, ok := c.solvers[Challenge(challenge.Type)]; ok {
return i, solver return i, solver
} }
logf("[INFO][%s] acme: Could not find solver for: %s", domain, challenge.Type) log.Printf("[INFO][%s] acme: Could not find solver for: %s", domain, challenge.Type)
} }
return 0, nil return 0, nil
} }
@ -638,7 +624,7 @@ func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, error)
func logAuthz(order orderResource) { func logAuthz(order orderResource) {
for i, auth := range order.Authorizations { for i, auth := range order.Authorizations {
logf("[INFO][%s] AuthURL: %s", order.Identifiers[i].Value, auth) log.Printf("[INFO][%s] AuthURL: %s", order.Identifiers[i].Value, auth)
} }
} }
@ -755,7 +741,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
if err != nil { if err != nil {
// If we fail to acquire the issuer cert, return the issued certificate - do not fail. // If we fail to acquire the issuer cert, return the issued certificate - do not fail.
logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err) log.Printf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
} else { } else {
issuerCert = pemEncode(derCertificateBytes(issuerCert)) issuerCert = pemEncode(derCertificateBytes(issuerCert))
@ -772,7 +758,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
certRes.Certificate = cert certRes.Certificate = cert
certRes.CertURL = order.Certificate certRes.CertURL = order.Certificate
certRes.CertStableURL = order.Certificate certRes.CertStableURL = order.Certificate
logf("[INFO][%s] Server responded with a certificate.", certRes.Domain) log.Printf("[INFO][%s] Server responded with a certificate.", certRes.Domain)
return true, nil return true, nil
case "processing": case "processing":
@ -786,7 +772,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
// getIssuerCertificate requests the issuer certificate // getIssuerCertificate requests the issuer certificate
func (c *Client) getIssuerCertificate(url string) ([]byte, error) { func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
logf("[INFO] acme: Requesting issuer cert from %s", url) log.Printf("[INFO] acme: Requesting issuer cert from %s", url)
resp, err := httpGet(url) resp, err := httpGet(url)
if err != nil { if err != nil {
return nil, err return nil, err
@ -840,7 +826,7 @@ func validate(j *jws, domain, uri string, c challenge) error {
for { for {
switch chlng.Status { switch chlng.Status {
case "valid": case "valid":
logf("[INFO][%s] The server validated our request", domain) log.Printf("[INFO][%s] The server validated our request", domain)
return nil return nil
case "pending": case "pending":
break break

View file

@ -5,12 +5,12 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"log"
"net" "net"
"strings" "strings"
"time" "time"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/xenolf/lego/log"
) )
type preCheckDNSFunc func(fqdn, value string) (bool, error) type preCheckDNSFunc func(fqdn, value string) (bool, error)
@ -72,7 +72,7 @@ type dnsChallenge struct {
} }
func (s *dnsChallenge) Solve(chlng challenge, domain string) error { func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
logf("[INFO][%s] acme: Trying to solve DNS-01", domain) log.Printf("[INFO][%s] acme: Trying to solve DNS-01", domain)
if s.provider == nil { if s.provider == nil {
return errors.New("No DNS Provider configured") return errors.New("No DNS Provider configured")
@ -97,7 +97,7 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
fqdn, value, _ := DNS01Record(domain, keyAuth) fqdn, value, _ := DNS01Record(domain, keyAuth)
logf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers) log.Printf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
var timeout, interval time.Duration var timeout, interval time.Duration
switch provider := s.provider.(type) { switch provider := s.provider.(type) {

View file

@ -4,6 +4,8 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"os" "os"
"github.com/xenolf/lego/log"
) )
const ( const (
@ -28,9 +30,9 @@ func (*DNSProviderManual) Present(domain, token, keyAuth string) error {
return err return err
} }
logf("[INFO] acme: Please create the following TXT record in your %s zone:", authZone) log.Printf("[INFO] acme: Please create the following TXT record in your %s zone:", authZone)
logf("[INFO] acme: %s", dnsRecord) log.Printf("[INFO] acme: %s", dnsRecord)
logf("[INFO] acme: Press 'Enter' when you are done") log.Printf("[INFO] acme: Press 'Enter' when you are done")
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
_, _ = reader.ReadString('\n') _, _ = reader.ReadString('\n')
@ -47,7 +49,7 @@ func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
return err return err
} }
logf("[INFO] acme: You can now remove this TXT record from your %s zone:", authZone) log.Printf("[INFO] acme: You can now remove this TXT record from your %s zone:", authZone)
logf("[INFO] acme: %s", dnsRecord) log.Printf("[INFO] acme: %s", dnsRecord)
return nil return nil
} }

View file

@ -2,7 +2,8 @@ package acme
import ( import (
"fmt" "fmt"
"log"
"github.com/xenolf/lego/log"
) )
type httpChallenge struct { type httpChallenge struct {
@ -18,7 +19,7 @@ func HTTP01ChallengePath(token string) string {
func (s *httpChallenge) Solve(chlng challenge, domain string) error { func (s *httpChallenge) Solve(chlng challenge, domain string) error {
logf("[INFO][%s] acme: Trying to solve HTTP-01", domain) log.Printf("[INFO][%s] acme: Trying to solve HTTP-01", domain)
// Generate the Key Authorization for the challenge // Generate the Key Authorization for the challenge
keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey) keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)

View file

@ -5,6 +5,8 @@ import (
"net" "net"
"net/http" "net/http"
"strings" "strings"
"github.com/xenolf/lego/log"
) )
// HTTPProviderServer implements ChallengeProvider for `http-01` challenge // HTTPProviderServer implements ChallengeProvider for `http-01` challenge
@ -61,9 +63,9 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
if strings.HasPrefix(r.Host, domain) && r.Method == "GET" { if strings.HasPrefix(r.Host, domain) && r.Method == "GET" {
w.Header().Add("Content-Type", "text/plain") w.Header().Add("Content-Type", "text/plain")
w.Write([]byte(keyAuth)) w.Write([]byte(keyAuth))
logf("[INFO][%s] Served key authentication", domain) log.Printf("[INFO][%s] Served key authentication", domain)
} else { } else {
logf("[WARN] Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method) log.Printf("[WARN] Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
w.Write([]byte("TEST")) w.Write([]byte("TEST"))
} }
}) })

15
cli.go
View file

@ -4,7 +4,6 @@ package main
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"path" "path"
"strings" "strings"
@ -12,19 +11,9 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
"github.com/xenolf/lego/log"
) )
// Logger is used to log errors; if nil, the default log.Logger is used.
var Logger *log.Logger
// logger is an helper function to retrieve the available logger
func logger() *log.Logger {
if Logger == nil {
Logger = log.New(os.Stderr, "", log.LstdFlags)
}
return Logger
}
var gittag string var gittag string
func main() { func main() {
@ -49,7 +38,7 @@ func main() {
app.Before = func(c *cli.Context) error { app.Before = func(c *cli.Context) error {
if c.GlobalString("path") == "" { if c.GlobalString("path") == "" {
logger().Fatal("Could not determine current working directory. Please pass --path.") log.Fatal("Could not determine current working directory. Please pass --path.")
} }
return nil return nil
} }

View file

@ -16,6 +16,7 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
"github.com/xenolf/lego/log"
"github.com/xenolf/lego/providers/dns" "github.com/xenolf/lego/providers/dns"
"github.com/xenolf/lego/providers/http/memcached" "github.com/xenolf/lego/providers/http/memcached"
"github.com/xenolf/lego/providers/http/webroot" "github.com/xenolf/lego/providers/http/webroot"
@ -51,12 +52,12 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
err := checkFolder(c.GlobalString("path")) err := checkFolder(c.GlobalString("path"))
if err != nil { if err != nil {
logger().Fatalf("Could not check/create path: %s", err.Error()) log.Fatalf("Could not check/create path: %s", err.Error())
} }
conf := NewConfiguration(c) conf := NewConfiguration(c)
if len(c.GlobalString("email")) == 0 { if len(c.GlobalString("email")) == 0 {
logger().Fatal("You have to pass an account (email address) to the program using --email or -m") log.Fatal("You have to pass an account (email address) to the program using --email or -m")
} }
//TODO: move to account struct? Currently MUST pass email. //TODO: move to account struct? Currently MUST pass email.
@ -64,14 +65,14 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
keyType, err := conf.KeyType() keyType, err := conf.KeyType()
if err != nil { if err != nil {
logger().Fatal(err.Error()) log.Fatal(err)
} }
acme.UserAgent = fmt.Sprintf("le-go/cli %s", c.App.Version) acme.UserAgent = fmt.Sprintf("le-go/cli %s", c.App.Version)
client, err := acme.NewClient(c.GlobalString("server"), acc, keyType) client, err := acme.NewClient(c.GlobalString("server"), acc, keyType)
if err != nil { if err != nil {
logger().Fatalf("Could not create client: %s", err.Error()) log.Fatalf("Could not create client: %s", err.Error())
} }
if len(c.GlobalStringSlice("exclude")) > 0 { if len(c.GlobalStringSlice("exclude")) > 0 {
@ -81,7 +82,7 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
if c.GlobalIsSet("webroot") { if c.GlobalIsSet("webroot") {
provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot")) provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot"))
if err != nil { if err != nil {
logger().Fatal(err) log.Fatal(err)
} }
client.SetChallengeProvider(acme.HTTP01, provider) client.SetChallengeProvider(acme.HTTP01, provider)
@ -93,7 +94,7 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
if c.GlobalIsSet("memcached-host") { if c.GlobalIsSet("memcached-host") {
provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host")) provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host"))
if err != nil { if err != nil {
logger().Fatal(err) log.Fatal(err)
} }
client.SetChallengeProvider(acme.HTTP01, provider) client.SetChallengeProvider(acme.HTTP01, provider)
@ -104,7 +105,7 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
} }
if c.GlobalIsSet("http") { if c.GlobalIsSet("http") {
if strings.Index(c.GlobalString("http"), ":") == -1 { if strings.Index(c.GlobalString("http"), ":") == -1 {
logger().Fatalf("The --http switch only accepts interface:port or :port for its argument.") log.Fatalf("The --http switch only accepts interface:port or :port for its argument.")
} }
client.SetHTTPAddress(c.GlobalString("http")) client.SetHTTPAddress(c.GlobalString("http"))
} }
@ -112,7 +113,7 @@ func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
if c.GlobalIsSet("dns") { if c.GlobalIsSet("dns") {
provider, err := dns.NewDNSChallengeProviderByName(c.GlobalString("dns")) provider, err := dns.NewDNSChallengeProviderByName(c.GlobalString("dns"))
if err != nil { if err != nil {
logger().Fatal(err) log.Fatal(err)
} }
client.SetChallengeProvider(acme.DNS01, provider) client.SetChallengeProvider(acme.DNS01, provider)
@ -143,13 +144,13 @@ func saveCertRes(certRes *acme.CertificateResource, conf *Configuration) {
err := ioutil.WriteFile(certOut, certRes.Certificate, 0600) err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
if err != nil { if err != nil {
logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
} }
if certRes.IssuerCertificate != nil { if certRes.IssuerCertificate != nil {
err = ioutil.WriteFile(issuerOut, certRes.IssuerCertificate, 0600) err = ioutil.WriteFile(issuerOut, certRes.IssuerCertificate, 0600)
if err != nil { if err != nil {
logger().Fatalf("Unable to save IssuerCertificate for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to save IssuerCertificate for domain %s\n\t%s", certRes.Domain, err.Error())
} }
} }
@ -157,29 +158,29 @@ func saveCertRes(certRes *acme.CertificateResource, conf *Configuration) {
// if we were given a CSR, we don't know the private key // if we were given a CSR, we don't know the private key
err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600) err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
if err != nil { if err != nil {
logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
} }
if conf.context.GlobalBool("pem") { if conf.context.GlobalBool("pem") {
err = ioutil.WriteFile(pemOut, bytes.Join([][]byte{certRes.Certificate, certRes.PrivateKey}, nil), 0600) err = ioutil.WriteFile(pemOut, bytes.Join([][]byte{certRes.Certificate, certRes.PrivateKey}, nil), 0600)
if err != nil { if err != nil {
logger().Fatalf("Unable to save Certificate and PrivateKey in .pem for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to save Certificate and PrivateKey in .pem for domain %s\n\t%s", certRes.Domain, err.Error())
} }
} }
} else if conf.context.GlobalBool("pem") { } else if conf.context.GlobalBool("pem") {
// we don't have the private key; can't write the .pem file // we don't have the private key; can't write the .pem file
logger().Fatalf("Unable to save pem without private key for domain %s\n\t%s; are you using a CSR?", certRes.Domain, err.Error()) log.Fatalf("Unable to save pem without private key for domain %s\n\t%s; are you using a CSR?", certRes.Domain, err.Error())
} }
jsonBytes, err := json.MarshalIndent(certRes, "", "\t") jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
if err != nil { if err != nil {
logger().Fatalf("Unable to marshal CertResource for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to marshal CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
} }
err = ioutil.WriteFile(metaOut, jsonBytes, 0600) err = ioutil.WriteFile(metaOut, jsonBytes, 0600)
if err != nil { if err != nil {
logger().Fatalf("Unable to save CertResource for domain %s\n\t%s", certRes.Domain, err.Error()) log.Fatalf("Unable to save CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
} }
} }
@ -190,26 +191,26 @@ func handleTOS(c *cli.Context, client *acme.Client) bool {
} }
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
logger().Printf("Please review the TOS at %s", client.GetToSURL()) log.Printf("Please review the TOS at %s", client.GetToSURL())
for { for {
logger().Println("Do you accept the TOS? Y/n") log.Println("Do you accept the TOS? Y/n")
text, err := reader.ReadString('\n') text, err := reader.ReadString('\n')
if err != nil { if err != nil {
logger().Fatalf("Could not read from console: %s", err.Error()) log.Fatalf("Could not read from console: %s", err.Error())
} }
text = strings.Trim(text, "\r\n") text = strings.Trim(text, "\r\n")
if text == "n" { if text == "n" {
logger().Fatal("You did not accept the TOS. Unable to proceed.") log.Fatal("You did not accept the TOS. Unable to proceed.")
} }
if text == "Y" || text == "y" || text == "" { if text == "Y" || text == "y" || text == "" {
return true return true
} }
logger().Println("Your input was invalid. Please answer with one of Y/y, n or by pressing enter.") log.Println("Your input was invalid. Please answer with one of Y/y, n or by pressing enter.")
} }
} }
@ -251,7 +252,7 @@ func run(c *cli.Context) error {
if acc.Registration == nil { if acc.Registration == nil {
accepted := handleTOS(c, client) accepted := handleTOS(c, client)
if !accepted { if !accepted {
logger().Fatal("You did not accept the TOS. Unable to proceed.") log.Fatal("You did not accept the TOS. Unable to proceed.")
} }
var reg *acme.RegistrationResource var reg *acme.RegistrationResource
@ -274,14 +275,14 @@ func run(c *cli.Context) error {
} }
if err != nil { if err != nil {
logger().Fatalf("Could not complete registration\n\t%s", err.Error()) log.Fatalf("Could not complete registration\n\t%s", err.Error())
} }
acc.Registration = reg acc.Registration = reg
acc.Save() acc.Save()
logger().Print("!!!! HEADS UP !!!!") log.Print("!!!! HEADS UP !!!!")
logger().Printf(` log.Printf(`
Your account credentials have been saved in your Let's Encrypt Your account credentials have been saved in your Let's Encrypt
configuration directory at "%s". configuration directory at "%s".
You should make a secure backup of this folder now. This You should make a secure backup of this folder now. This
@ -295,10 +296,10 @@ func run(c *cli.Context) error {
hasDomains := len(c.GlobalStringSlice("domains")) > 0 hasDomains := len(c.GlobalStringSlice("domains")) > 0
hasCsr := len(c.GlobalString("csr")) > 0 hasCsr := len(c.GlobalString("csr")) > 0
if hasDomains && hasCsr { if hasDomains && hasCsr {
logger().Fatal("Please specify either --domains/-d or --csr/-c, but not both") log.Fatal("Please specify either --domains/-d or --csr/-c, but not both")
} }
if !hasDomains && !hasCsr { if !hasDomains && !hasCsr {
logger().Fatal("Please specify --domains/-d (or --csr/-c if you already have a CSR)") log.Fatal("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
} }
var cert *acme.CertificateResource var cert *acme.CertificateResource
@ -316,7 +317,7 @@ func run(c *cli.Context) error {
} }
if err != nil { if err != nil {
logger().Printf("Could not obtain certificates\n\t%s", err.Error()) log.Printf("Could not obtain certificates\n\t%s", err.Error())
// Make sure to return a non-zero exit code if ObtainSANCertificate // Make sure to return a non-zero exit code if ObtainSANCertificate
// returned at least one error. Due to us not returning partial // returned at least one error. Due to us not returning partial
@ -325,7 +326,7 @@ func run(c *cli.Context) error {
} }
if err = checkFolder(conf.CertPath()); err != nil { if err = checkFolder(conf.CertPath()); err != nil {
logger().Fatalf("Could not check/create path: %s", err.Error()) log.Fatalf("Could not check/create path: %s", err.Error())
} }
saveCertRes(cert, conf) saveCertRes(cert, conf)
@ -336,24 +337,24 @@ func run(c *cli.Context) error {
func revoke(c *cli.Context) error { func revoke(c *cli.Context) error {
conf, acc, client := setup(c) conf, acc, client := setup(c)
if acc.Registration == nil { if acc.Registration == nil {
logger().Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email) log.Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email)
} }
if err := checkFolder(conf.CertPath()); err != nil { if err := checkFolder(conf.CertPath()); err != nil {
logger().Fatalf("Could not check/create path: %s", err.Error()) log.Fatalf("Could not check/create path: %s", err.Error())
} }
for _, domain := range c.GlobalStringSlice("domains") { for _, domain := range c.GlobalStringSlice("domains") {
logger().Printf("Trying to revoke certificate for domain %s", domain) log.Printf("Trying to revoke certificate for domain %s", domain)
certPath := path.Join(conf.CertPath(), domain+".crt") certPath := path.Join(conf.CertPath(), domain+".crt")
certBytes, err := ioutil.ReadFile(certPath) certBytes, err := ioutil.ReadFile(certPath)
err = client.RevokeCertificate(certBytes) err = client.RevokeCertificate(certBytes)
if err != nil { if err != nil {
logger().Fatalf("Error while revoking the certificate for domain %s\n\t%s", domain, err.Error()) log.Fatalf("Error while revoking the certificate for domain %s\n\t%s", domain, err.Error())
} else { } else {
logger().Print("Certificate was revoked.") log.Print("Certificate was revoked.")
} }
} }
@ -363,11 +364,11 @@ func revoke(c *cli.Context) error {
func renew(c *cli.Context) error { func renew(c *cli.Context) error {
conf, acc, client := setup(c) conf, acc, client := setup(c)
if acc.Registration == nil { if acc.Registration == nil {
logger().Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email) log.Fatalf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email)
} }
if len(c.GlobalStringSlice("domains")) <= 0 { if len(c.GlobalStringSlice("domains")) <= 0 {
logger().Fatal("Please specify at least one domain.") log.Fatal("Please specify at least one domain.")
} }
domain := c.GlobalStringSlice("domains")[0] domain := c.GlobalStringSlice("domains")[0]
@ -382,13 +383,13 @@ func renew(c *cli.Context) error {
certBytes, err := ioutil.ReadFile(certPath) certBytes, err := ioutil.ReadFile(certPath)
if err != nil { if err != nil {
logger().Fatalf("Error while loading the certificate for domain %s\n\t%s", domain, err.Error()) log.Fatalf("Error while loading the certificate for domain %s\n\t%s", domain, err.Error())
} }
if c.IsSet("days") { if c.IsSet("days") {
expTime, err := acme.GetPEMCertExpiration(certBytes) expTime, err := acme.GetPEMCertExpiration(certBytes)
if err != nil { if err != nil {
logger().Printf("Could not get Certification expiration for domain %s", domain) log.Printf("Could not get Certification expiration for domain %s", domain)
} }
if int(expTime.Sub(time.Now()).Hours()/24.0) > c.Int("days") { if int(expTime.Sub(time.Now()).Hours()/24.0) > c.Int("days") {
@ -398,18 +399,18 @@ func renew(c *cli.Context) error {
metaBytes, err := ioutil.ReadFile(metaPath) metaBytes, err := ioutil.ReadFile(metaPath)
if err != nil { if err != nil {
logger().Fatalf("Error while loading the meta data for domain %s\n\t%s", domain, err.Error()) log.Fatalf("Error while loading the meta data for domain %s\n\t%s", domain, err.Error())
} }
var certRes acme.CertificateResource var certRes acme.CertificateResource
if err := json.Unmarshal(metaBytes, &certRes); err != nil { if err := json.Unmarshal(metaBytes, &certRes); err != nil {
logger().Fatalf("Error while marshalling the meta data for domain %s\n\t%s", domain, err.Error()) log.Fatalf("Error while marshalling the meta data for domain %s\n\t%s", domain, err.Error())
} }
if c.Bool("reuse-key") { if c.Bool("reuse-key") {
keyBytes, err := ioutil.ReadFile(privPath) keyBytes, err := ioutil.ReadFile(privPath)
if err != nil { if err != nil {
logger().Fatalf("Error while loading the private key for domain %s\n\t%s", domain, err.Error()) log.Fatalf("Error while loading the private key for domain %s\n\t%s", domain, err.Error())
} }
certRes.PrivateKey = keyBytes certRes.PrivateKey = keyBytes
} }
@ -418,7 +419,7 @@ func renew(c *cli.Context) error {
newCert, err := client.RenewCertificate(certRes, !c.Bool("no-bundle"), c.Bool("must-staple")) newCert, err := client.RenewCertificate(certRes, !c.Bool("no-bundle"), c.Bool("must-staple"))
if err != nil { if err != nil {
logger().Fatalf("%s", err.Error()) log.Fatal(err)
} }
saveCertRes(newCert, conf) saveCertRes(newCert, conf)

View file

@ -6,7 +6,6 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"net/http" "net/http"
"os" "os"
"strings" "strings"
@ -14,29 +13,14 @@ import (
"time" "time"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
"github.com/xenolf/lego/log"
) )
// GleSYS API reference: https://github.com/GleSYS/API/wiki/API-Documentation // GleSYS API reference: https://github.com/GleSYS/API/wiki/API-Documentation
// domainAPI is the GleSYS API endpoint used by Present and CleanUp. // domainAPI is the GleSYS API endpoint used by Present and CleanUp.
const domainAPI = "https://api.glesys.com/domain" const domainAPI = "https://api.glesys.com/domain"
var (
// Logger is used to log API communication results;
// if nil, the default log.Logger is used.
Logger *log.Logger
)
// logf writes a log entry. It uses Logger if not
// nil, otherwise it uses the default log.Logger.
func logf(format string, args ...interface{}) {
if Logger != nil {
Logger.Printf(format, args...)
} else {
log.Printf(format, args...)
}
}
// DNSProvider is an implementation of the // DNSProvider is an implementation of the
// acme.ChallengeProviderTimeout interface that uses GleSYS // acme.ChallengeProviderTimeout interface that uses GleSYS
// API to manage TXT records for a domain. // API to manage TXT records for a domain.
@ -187,14 +171,14 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
func (d *DNSProvider) addTXTRecord(fqdn string, domain string, name string, value string, ttl int) (int, error) { func (d *DNSProvider) addTXTRecord(fqdn string, domain string, name string, value string, ttl int) (int, error) {
response, err := d.sendRequest("POST", "addrecord", addRecordRequest{ response, err := d.sendRequest("POST", "addrecord", addRecordRequest{
Domainname: domain, Domainname: domain,
Host: name, Host: name,
Type: "TXT", Type: "TXT",
Data: value, Data: value,
Ttl: ttl, Ttl: ttl,
}) })
if response != nil && response.Response.Status.Code == 200 { if response != nil && response.Response.Status.Code == 200 {
logf("[INFO][%s] GleSYS DNS: Successfully created recordid %d", fqdn, response.Response.Record.Recordid) log.Printf("[INFO][%s] GleSYS DNS: Successfully created recordid %d", fqdn, response.Response.Record.Recordid)
return response.Response.Record.Recordid, nil return response.Response.Record.Recordid, nil
} }
return 0, err return 0, err
@ -205,7 +189,7 @@ func (d *DNSProvider) deleteTXTRecord(fqdn string, recordid int) error {
Recordid: recordid, Recordid: recordid,
}) })
if response != nil && response.Response.Status.Code == 200 { if response != nil && response.Response.Status.Code == 200 {
logf("[INFO][%s] GleSYS DNS: Successfully deleted recordid %d", fqdn, recordid) log.Printf("[INFO][%s] GleSYS DNS: Successfully deleted recordid %d", fqdn, recordid)
} }
return err return err
} }