From 4e92c7125951f7f9487914ccb9febe94b515e62a Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Fri, 16 Oct 2015 11:38:56 -0600 Subject: [PATCH] LE flags, modified tis directive, moved LE stuff to own file --- app/app.go | 24 ++++++++++++++++++++ config/config.go | 52 ++++++++++++++++--------------------------- config/letsencrypt.go | 35 +++++++++++++++++++++++++++++ config/setup/tls.go | 19 +++++++++------- main.go | 2 ++ server/config.go | 5 ++--- 6 files changed, 93 insertions(+), 44 deletions(-) create mode 100644 config/letsencrypt.go diff --git a/app/app.go b/app/app.go index b006d294..e8cd16bd 100644 --- a/app/app.go +++ b/app/app.go @@ -7,6 +7,8 @@ package app import ( "errors" + "os" + "path/filepath" "runtime" "strconv" "strings" @@ -74,3 +76,25 @@ func SetCPU(cpu string) error { runtime.GOMAXPROCS(numCPU) return nil } + +// DataFolder returns the path to the folder +// where the application may store data. This +// currently resolves to ~/.caddy +func DataFolder() string { + return filepath.Join(userHomeDir(), ".caddy") +} + +// userHomeDir returns the user's home directory according to +// environment variables. +// +// Credit: http://stackoverflow.com/a/7922977/1048862 +func userHomeDir() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") +} diff --git a/config/config.go b/config/config.go index a763d3c2..ea92368e 100644 --- a/config/config.go +++ b/config/config.go @@ -1,8 +1,6 @@ package config import ( - "crypto/rand" - "crypto/rsa" "errors" "fmt" "io" @@ -77,25 +75,20 @@ func Load(filename string, input io.Reader) (Group, error) { // restore logging settings log.SetFlags(flags) - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + // Initiate Let's Encrypt + leUser, err := NewLetsEncryptUser("example1@mail.com") if err != nil { - return Group{}, errors.New("Error Generating Key:" + err.Error()) + return Group{}, err } - for _, cfg := range configs { - // TODO: && hostname does not resolve to localhost (?) && TLS is not force-disabled - if !cfg.TLS.Enabled { - // Initiate Let's Encrypt - user := LetsEncryptUser{ - Email: "example@mail.com", - Key: privateKey, - } - client := acme.NewClient("http://192.168.99.100:4000", &user, 2048, "5001") + // TODO: && !IsLoopback() + if !cfg.TLS.Enabled && cfg.Port != "http" { + client := acme.NewClient("http://192.168.99.100:4000", &leUser, 2048, "5001") reg, err := client.Register() if err != nil { return Group{}, errors.New("Error Registering: " + err.Error()) } - user.Registration = reg + leUser.Registration = reg err = client.AgreeToTos() if err != nil { @@ -106,8 +99,6 @@ func Load(filename string, input io.Reader) (Group, error) { if err != nil { return Group{}, errors.New("Error Obtaining Certs: " + err.Error()) } - - fmt.Printf("%#v\n", certs) } } @@ -115,22 +106,6 @@ func Load(filename string, input io.Reader) (Group, error) { return arrangeBindings(configs) } -type LetsEncryptUser struct { - Email string - Registration *acme.RegistrationResource - Key *rsa.PrivateKey -} - -func (u LetsEncryptUser) GetEmail() string { - return u.Email -} -func (u LetsEncryptUser) GetRegistration() *acme.RegistrationResource { - return u.Registration -} -func (u LetsEncryptUser) GetPrivateKey() *rsa.PrivateKey { - return u.Key -} - // serverBlockToConfig makes a config for the server block // by executing the tokens that were parsed. The returned // config is shared among all hosts/addresses for the server @@ -303,11 +278,22 @@ func Default() (Group, error) { return arrangeBindings([]server.Config{NewDefault()}) } -// These three defaults are configurable through the command line +// These defaults are configurable through the command line var ( + // Site root Root = DefaultRoot + + // Site host Host = DefaultHost + + // Site port Port = DefaultPort + + // Let's Encrypt account email + LetsEncryptEmail string + + // Agreement to Let's Encrypt terms + LetsEncryptAgree bool ) type Group map[*net.TCPAddr][]server.Config diff --git a/config/letsencrypt.go b/config/letsencrypt.go new file mode 100644 index 00000000..53aac694 --- /dev/null +++ b/config/letsencrypt.go @@ -0,0 +1,35 @@ +package config + +import ( + "crypto/rand" + "crypto/rsa" + "errors" + + "github.com/xenolf/lego/acme" +) + +func NewLetsEncryptUser(email string) (LetsEncryptUser, error) { + user := LetsEncryptUser{Email: email} + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return user, errors.New("error generating private key: " + err.Error()) + } + user.Key = privateKey + return user, nil +} + +type LetsEncryptUser struct { + Email string + Registration *acme.RegistrationResource + Key *rsa.PrivateKey +} + +func (u LetsEncryptUser) GetEmail() string { + return u.Email +} +func (u LetsEncryptUser) GetRegistration() *acme.RegistrationResource { + return u.Registration +} +func (u LetsEncryptUser) GetPrivateKey() *rsa.PrivateKey { + return u.Key +} diff --git a/config/setup/tls.go b/config/setup/tls.go index 431409f4..8e0b7f03 100644 --- a/config/setup/tls.go +++ b/config/setup/tls.go @@ -8,18 +8,21 @@ import ( ) func TLS(c *Controller) (middleware.Middleware, error) { - c.TLS.Enabled = true + if c.Port != "http" { + c.TLS.Enabled = true + } for c.Next() { - if !c.NextArg() { + args := c.RemainingArgs() + switch len(args) { + case 1: + c.TLS.LetsEncryptEmail = args[0] + case 2: + c.TLS.Certificate = args[0] + c.TLS.Key = args[1] + default: return nil, c.ArgErr() } - c.TLS.Certificate = c.Val() - - if !c.NextArg() { - return nil, c.ArgErr() - } - c.TLS.Key = c.Val() // Optional block for c.NextBlock() { diff --git a/main.go b/main.go index c1c0d143..7187567d 100644 --- a/main.go +++ b/main.go @@ -33,6 +33,8 @@ func init() { flag.StringVar(&config.Host, "host", config.DefaultHost, "Default host") flag.StringVar(&config.Port, "port", config.DefaultPort, "Default port") flag.BoolVar(&version, "version", false, "Show version") + flag.BoolVar(&config.LetsEncryptAgree, "agree", false, "Agree to Let's Encrypt Subscriber Agreement") + flag.StringVar(&config.LetsEncryptEmail, "email", "", "Email address to use for Let's Encrypt account") } func main() { diff --git a/server/config.go b/server/config.go index 4bcea8b2..dedd7ba3 100644 --- a/server/config.go +++ b/server/config.go @@ -50,13 +50,12 @@ func (c Config) Address() string { return net.JoinHostPort(c.Host, c.Port) } -// TLSConfig describes how TLS should be configured and used, -// if at all. A certificate and key are both required. -// The rest is optional. +// TLSConfig describes how TLS should be configured and used. type TLSConfig struct { Enabled bool Certificate string Key string + LetsEncryptEmail string Ciphers []uint16 ProtocolMinVersion uint16 ProtocolMaxVersion uint16