Add support for Let's Encrypt

Add configuration and certificate manager to use letsencrypt

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
This commit is contained in:
Derek McGowan 2016-06-13 11:30:42 -07:00
parent 1c99939221
commit be2ed961aa
3 changed files with 44 additions and 5 deletions

View file

@ -95,6 +95,19 @@ type Configuration struct {
// Specifies the CA certs for client authentication // Specifies the CA certs for client authentication
// A file may contain multiple CA certificates encoded as PEM // A file may contain multiple CA certificates encoded as PEM
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
// LetsEncrypt is used to configuration setting up TLS through
// Let's Encrypt instead of manually specifying certificate and
// key. If a TLS certificate is specified, the Let's Encrypt
// section will not be used.
LetsEncrypt struct {
// CacheFile specifies cache file to use for lets encrypt
// certificates and keys.
CacheFile string `yaml:"cachefile,omitempty"`
// Email is the email to use during Let's Encrypt registration
Email string `yaml:"email,omitempty"`
} `yaml:"letsencrypt,omitempty"`
} `yaml:"tls,omitempty"` } `yaml:"tls,omitempty"`
// Headers is a set of headers to include in HTTP responses. A common // Headers is a set of headers to include in HTTP responses. A common

View file

@ -73,6 +73,10 @@ var configStruct = Configuration{
Certificate string `yaml:"certificate,omitempty"` Certificate string `yaml:"certificate,omitempty"`
Key string `yaml:"key,omitempty"` Key string `yaml:"key,omitempty"`
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
LetsEncrypt struct {
CacheFile string `yaml:"cachefile,omitempty"`
Email string `yaml:"email,omitempty"`
} `yaml:"letsencrypt,omitempty"`
} `yaml:"tls,omitempty"` } `yaml:"tls,omitempty"`
Headers http.Header `yaml:"headers,omitempty"` Headers http.Header `yaml:"headers,omitempty"`
Debug struct { Debug struct {
@ -83,6 +87,10 @@ var configStruct = Configuration{
Certificate string `yaml:"certificate,omitempty"` Certificate string `yaml:"certificate,omitempty"`
Key string `yaml:"key,omitempty"` Key string `yaml:"key,omitempty"`
ClientCAs []string `yaml:"clientcas,omitempty"` ClientCAs []string `yaml:"clientcas,omitempty"`
LetsEncrypt struct {
CacheFile string `yaml:"cachefile,omitempty"`
Email string `yaml:"email,omitempty"`
} `yaml:"letsencrypt,omitempty"`
}{ }{
ClientCAs: []string{"/path/to/ca.pem"}, ClientCAs: []string{"/path/to/ca.pem"},
}, },

View file

@ -9,6 +9,8 @@ import (
"os" "os"
"time" "time"
"rsc.io/letsencrypt"
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/Sirupsen/logrus/formatters/logstash" "github.com/Sirupsen/logrus/formatters/logstash"
"github.com/bugsnag/bugsnag-go" "github.com/bugsnag/bugsnag-go"
@ -111,11 +113,10 @@ func (registry *Registry) ListenAndServe() error {
return err return err
} }
if config.HTTP.TLS.Certificate != "" { if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" {
tlsConf := &tls.Config{ tlsConf := &tls.Config{
ClientAuth: tls.NoClientCert, ClientAuth: tls.NoClientCert,
NextProtos: []string{"http/1.1"}, NextProtos: []string{"http/1.1"},
Certificates: make([]tls.Certificate, 1),
MinVersion: tls.VersionTLS10, MinVersion: tls.VersionTLS10,
PreferServerCipherSuites: true, PreferServerCipherSuites: true,
CipherSuites: []uint16{ CipherSuites: []uint16{
@ -130,9 +131,26 @@ func (registry *Registry) ListenAndServe() error {
}, },
} }
tlsConf.Certificates[0], err = tls.LoadX509KeyPair(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key) if config.HTTP.TLS.LetsEncrypt.CacheFile != "" {
if err != nil { if config.HTTP.TLS.Certificate != "" {
return err return fmt.Errorf("cannot specify both certificate and Let's Encrypt")
}
var m letsencrypt.Manager
if err := m.CacheFile(config.HTTP.TLS.LetsEncrypt.CacheFile); err != nil {
return err
}
if !m.Registered() {
if err := m.Register(config.HTTP.TLS.LetsEncrypt.Email, nil); err != nil {
return err
}
}
tlsConf.GetCertificate = m.GetCertificate
} else {
tlsConf.Certificates = make([]tls.Certificate, 1)
tlsConf.Certificates[0], err = tls.LoadX509KeyPair(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key)
if err != nil {
return err
}
} }
if len(config.HTTP.TLS.ClientCAs) != 0 { if len(config.HTTP.TLS.ClientCAs) != 0 {