Fix HTTPS config for empty/no Caddyfile

This fixes a regression introduced in recent commits that enabled TLS on the default ":2015" config. This fix is possible because On-Demand TLS is no longer implicit; it must be explicitly enabled by the user by setting a maximum number of certificates to issue.
This commit is contained in:
Matthew Holt 2016-02-12 13:04:24 -07:00
parent 04c7c442c5
commit a11e14aca8
5 changed files with 31 additions and 30 deletions

View File

@ -95,7 +95,7 @@ func Deactivate() (err error) {
}
// MarkQualified scans each config and, if it qualifies for managed
// TLS, it sets the Marked field of the TLSConfig to true.
// TLS, it sets the Managed field of the TLSConfig to true.
func MarkQualified(configs []server.Config) {
for i := 0; i < len(configs); i++ {
if ConfigQualifies(configs[i]) {
@ -152,9 +152,10 @@ func ObtainCerts(configs []server.Config, allowPrompts, proxyACME bool) error {
return nil
}
// groupConfigsByEmail groups configs by the email address to be used by its
// ACME client. It only includes configs that are marked as fully managed.
// If userPresent is true, the operator MAY be prompted for an email address.
// groupConfigsByEmail groups configs by the email address to be used by an
// ACME client. It only groups configs that have TLS enabled and that are
// marked as Managed. If userPresent is true, the operator MAY be prompted
// for an email address.
func groupConfigsByEmail(configs []server.Config, userPresent bool) map[string][]server.Config {
initMap := make(map[string][]server.Config)
for _, cfg := range configs {
@ -214,7 +215,7 @@ func hostHasOtherPort(allConfigs []server.Config, thisConfigIdx int, otherPort s
// all configs.
func MakePlaintextRedirects(allConfigs []server.Config) []server.Config {
for i, cfg := range allConfigs {
if cfg.TLS.Managed &&
if (cfg.TLS.Managed || cfg.TLS.OnDemand) &&
!hostHasOtherPort(allConfigs, i, "80") &&
(cfg.Port == "443" || !hostHasOtherPort(allConfigs, i, "443")) {
allConfigs = append(allConfigs, redirPlaintextHost(cfg))
@ -224,10 +225,11 @@ func MakePlaintextRedirects(allConfigs []server.Config) []server.Config {
}
// ConfigQualifies returns true if cfg qualifies for
// fully managed TLS. It does NOT check to see if a
// fully managed TLS (but not on-demand TLS, which is
// not considered here). It does NOT check to see if a
// cert and key already exist for the config. If the
// config does qualify, you should set cfg.TLS.Managed
// to true and use that instead, because the process of
// to true and check that instead, because the process of
// setting up the config may make it look like it
// doesn't qualify even though it originally did.
func ConfigQualifies(cfg server.Config) bool {
@ -238,10 +240,8 @@ func ConfigQualifies(cfg server.Config) bool {
cfg.Port != "80" &&
cfg.TLS.LetsEncryptEmail != "off" &&
// we get can't certs for some kinds of hostnames,
// but we CAN get certs at request-time even if
// the hostname in the config is empty right now.
(cfg.Host == "" || HostQualifies(cfg.Host))
// we get can't certs for some kinds of hostnames
HostQualifies(cfg.Host)
}
// HostQualifies returns true if the hostname alone

View File

@ -46,7 +46,7 @@ func TestConfigQualifies(t *testing.T) {
cfg server.Config
expect bool
}{
{server.Config{Host: ""}, true},
{server.Config{Host: ""}, false},
{server.Config{Host: "localhost"}, false},
{server.Config{Host: "123.44.3.21"}, false},
{server.Config{Host: "example.com"}, true},
@ -302,6 +302,7 @@ func TestGroupConfigsByEmail(t *testing.T) {
func TestMarkQualified(t *testing.T) {
// TODO: TestConfigQualifies and this test share the same config list...
configs := []server.Config{
{Host: ""},
{Host: "localhost"},
{Host: "123.44.3.21"},
{Host: "example.com"},
@ -313,9 +314,8 @@ func TestMarkQualified(t *testing.T) {
{Host: "example.com", Port: "1234"},
{Host: "example.com", Scheme: "https"},
{Host: "example.com", Port: "80", Scheme: "https"},
{Host: ""},
}
expectedManagedCount := 5
expectedManagedCount := 4
MarkQualified(configs)

View File

@ -83,6 +83,7 @@ func Setup(c *setup.Controller) (middleware.Middleware, error) {
c.TLS.Manual = true
case "max_certs":
c.Args(&maxCerts)
c.TLS.OnDemand = true
default:
return nil, c.Errf("Unknown keyword '%s'", c.Val())
}
@ -93,21 +94,18 @@ func Setup(c *setup.Controller) (middleware.Middleware, error) {
return nil, c.ArgErr()
}
if c.TLS.Manual && maxCerts != "" {
return nil, c.Err("Cannot limit certificate count (max_certs) for manual TLS configurations")
}
// set certificate limit if on-demand TLS is enabled
if maxCerts != "" {
maxCertsNum, err := strconv.Atoi(maxCerts)
if err != nil || maxCertsNum < 0 {
if err != nil || maxCertsNum < 1 {
return nil, c.Err("max_certs must be a positive integer")
}
if onDemandMaxIssue == 0 || int32(maxCertsNum) < onDemandMaxIssue { // keep the minimum; TODO: This is global; should be per-server or per-vhost...
if onDemandMaxIssue == 0 || int32(maxCertsNum) < onDemandMaxIssue { // keep the minimum; TODO: We have to do this because it is global; should be per-server or per-vhost...
onDemandMaxIssue = int32(maxCertsNum)
}
}
// don't load certificates unless we're supposed to
// don't try to load certificates unless we're supposed to
if !c.TLS.Enabled || !c.TLS.Manual {
continue
}

View File

@ -65,10 +65,11 @@ func (c Config) Address() string {
// TLSConfig describes how TLS should be configured and used.
type TLSConfig struct {
Enabled bool
Enabled bool // will be set to true if TLS is enabled
LetsEncryptEmail string
Managed bool // will be set to true if config qualifies for automatic, managed TLS
Manual bool // will be set to true if user provides the cert and key files
Manual bool // will be set to true if user provides own certs and keys
Managed bool // will be set to true if config qualifies for automatic/managed HTTPS
OnDemand bool // will be set to true if user enables on-demand TLS (obtain certs during handshakes)
Ciphers []uint16
ProtocolMinVersion uint16
ProtocolMaxVersion uint16

View File

@ -63,12 +63,14 @@ func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server,
var useTLS, useOnDemandTLS bool
if len(configs) > 0 {
useTLS = configs[0].TLS.Enabled
host, _, err := net.SplitHostPort(addr)
if err != nil {
host = addr
}
if useTLS && host == "" && !configs[0].TLS.Manual {
useOnDemandTLS = true
if useTLS {
host, _, err := net.SplitHostPort(addr)
if err != nil {
host = addr
}
if host == "" && configs[0].TLS.OnDemand {
useOnDemandTLS = true
}
}
}