Commit cd0b47d0 authored by Matthew Holt's avatar Matthew Holt

letsencrypt: Don't auto-configure loopback hosts or 'tls off'

User can specify 'tls off" in Caddyfile to force-disable automatic HTTPS configuration
parent 4c93ab8c
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
"strings"
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
"github.com/mholt/caddy/middleware/redirect" "github.com/mholt/caddy/middleware/redirect"
...@@ -33,7 +34,7 @@ func Activate(configs []server.Config) ([]server.Config, error) { ...@@ -33,7 +34,7 @@ func Activate(configs []server.Config) ([]server.Config, error) {
// we already have certs and keys in storage from last time. // we already have certs and keys in storage from last time.
configLen := len(configs) // avoid infinite loop since this loop appends to the slice configLen := len(configs) // avoid infinite loop since this loop appends to the slice
for i := 0; i < configLen; i++ { for i := 0; i < configLen; i++ {
if existingCertAndKey(configs[i].Host) { if existingCertAndKey(configs[i].Host) && configs[i].TLS.LetsEncryptEmail != "off" {
configs = autoConfigure(&configs[i], configs) configs = autoConfigure(&configs[i], configs)
} }
} }
...@@ -83,19 +84,37 @@ func Activate(configs []server.Config) ([]server.Config, error) { ...@@ -83,19 +84,37 @@ func Activate(configs []server.Config) ([]server.Config, error) {
// Configurations with a manual TLS configuration or one that is already // Configurations with a manual TLS configuration or one that is already
// found in storage will not be added to any group. // found in storage will not be added to any group.
func groupConfigsByEmail(configs []server.Config) (map[string][]*server.Config, error) { func groupConfigsByEmail(configs []server.Config) (map[string][]*server.Config, error) {
// configQualifies returns true if cfg qualifes for automatic LE activation
configQualifies := func(cfg server.Config) bool {
return cfg.TLS.Certificate == "" && // user could provide their own cert and key
cfg.TLS.Key == "" &&
// user can force-disable automatic HTTPS for this host
cfg.Port != "http" &&
cfg.TLS.LetsEncryptEmail != "off" &&
// obviously we get can't certs for loopback or internal hosts
cfg.Host != "localhost" &&
cfg.Host != "" &&
cfg.Host != "0.0.0.0" &&
cfg.Host != "::1" &&
!strings.HasPrefix(cfg.Host, "127.") &&
!strings.HasPrefix(cfg.Host, "10.") &&
// make sure an HTTPS version of this config doesn't exist in the list already
!hostHasOtherScheme(cfg.Host, "https", configs)
}
initMap := make(map[string][]*server.Config) initMap := make(map[string][]*server.Config)
for i := 0; i < len(configs); i++ { for i := 0; i < len(configs); i++ {
if configs[i].TLS.Certificate == "" && configs[i].TLS.Key == "" && configs[i].Port != "http" { // TODO: && !cfg.Host.IsLoopback() if !configQualifies(configs[i]) {
// make sure an HTTPS version of this config doesn't exist in the list already continue
if hostHasOtherScheme(configs[i].Host, "https", configs) { }
continue leEmail := getEmail(configs[i])
} if leEmail == "" {
leEmail := getEmail(configs[i]) return nil, errors.New("must have email address to serve HTTPS without existing certificate and key")
if leEmail == "" {
return nil, errors.New("must have email address to serve HTTPS without existing certificate and key")
}
initMap[leEmail] = append(initMap[leEmail], &configs[i])
} }
initMap[leEmail] = append(initMap[leEmail], &configs[i])
} }
return initMap, nil return initMap, nil
} }
...@@ -212,12 +231,12 @@ func autoConfigure(cfg *server.Config, allConfigs []server.Config) []server.Conf ...@@ -212,12 +231,12 @@ func autoConfigure(cfg *server.Config, allConfigs []server.Config) []server.Conf
cfg.TLS.Enabled = true cfg.TLS.Enabled = true
cfg.Port = "https" cfg.Port = "https"
// Is there a plaintext HTTP config for the same host? If not, make // Set up http->https redirect as long as there isn't already
// one and have it redirect all requests to this HTTPS host. // a http counterpart in the configs
if !hostHasOtherScheme(cfg.Host, "http", allConfigs) { if !hostHasOtherScheme(cfg.Host, "http", allConfigs) {
// Make one that redirects to HTTPS for all requests
allConfigs = append(allConfigs, redirPlaintextHost(*cfg)) allConfigs = append(allConfigs, redirPlaintextHost(*cfg))
} }
return allConfigs return allConfigs
} }
...@@ -270,6 +289,7 @@ var ( ...@@ -270,6 +289,7 @@ var (
// Some essential values related to the Let's Encrypt process // Some essential values related to the Let's Encrypt process
const ( const (
// The base URL to the Let's Encrypt CA // The base URL to the Let's Encrypt CA
// TODO: Staging API URL is: https://acme-staging.api.letsencrypt.org
caURL = "http://192.168.99.100:4000" caURL = "http://192.168.99.100:4000"
// The port to expose to the CA server for Simple HTTP Challenge // The port to expose to the CA server for Simple HTTP Challenge
......
...@@ -21,6 +21,10 @@ func TLS(c *Controller) (middleware.Middleware, error) { ...@@ -21,6 +21,10 @@ func TLS(c *Controller) (middleware.Middleware, error) {
switch len(args) { switch len(args) {
case 1: case 1:
c.TLS.LetsEncryptEmail = args[0] c.TLS.LetsEncryptEmail = args[0]
// user can force-disable LE activation this way
if c.TLS.LetsEncryptEmail == "off" {
c.TLS.Enabled = false
}
case 2: case 2:
c.TLS.Certificate = args[0] c.TLS.Certificate = args[0]
c.TLS.Key = args[1] c.TLS.Key = args[1]
......
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