aboutsummaryrefslogtreecommitdiffhomepage
path: root/caddyconfig/httpcaddyfile
diff options
context:
space:
mode:
Diffstat (limited to 'caddyconfig/httpcaddyfile')
-rw-r--r--caddyconfig/httpcaddyfile/httptype.go56
-rw-r--r--caddyconfig/httpcaddyfile/options.go21
-rw-r--r--caddyconfig/httpcaddyfile/tlsapp.go41
3 files changed, 98 insertions, 20 deletions
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index 6745969ee..4dacd9058 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -534,8 +534,8 @@ func (st *ServerType) serversFromPairings(
if hsp, ok := options["https_port"].(int); ok {
httpsPort = strconv.Itoa(hsp)
}
- autoHTTPS := "on"
- if ah, ok := options["auto_https"].(string); ok {
+ autoHTTPS := []string{}
+ if ah, ok := options["auto_https"].([]string); ok {
autoHTTPS = ah
}
@@ -594,17 +594,37 @@ func (st *ServerType) serversFromPairings(
}
// handle the auto_https global option
- if autoHTTPS != "on" {
- srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
- switch autoHTTPS {
+ for _, val := range autoHTTPS {
+ switch val {
case "off":
+ if srv.AutoHTTPS == nil {
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
+ }
srv.AutoHTTPS.Disabled = true
+
case "disable_redirects":
+ if srv.AutoHTTPS == nil {
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
+ }
srv.AutoHTTPS.DisableRedir = true
+
case "disable_certs":
+ if srv.AutoHTTPS == nil {
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
+ }
srv.AutoHTTPS.DisableCerts = true
+
case "ignore_loaded_certs":
+ if srv.AutoHTTPS == nil {
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
+ }
srv.AutoHTTPS.IgnoreLoadedCerts = true
+
+ case "prefer_wildcard":
+ if srv.AutoHTTPS == nil {
+ srv.AutoHTTPS = new(caddyhttp.AutoHTTPSConfig)
+ }
+ srv.AutoHTTPS.PreferWildcard = true
}
}
@@ -673,7 +693,7 @@ func (st *ServerType) serversFromPairings(
})
var hasCatchAllTLSConnPolicy, addressQualifiesForTLS bool
- autoHTTPSWillAddConnPolicy := autoHTTPS != "off"
+ autoHTTPSWillAddConnPolicy := srv.AutoHTTPS == nil || !srv.AutoHTTPS.Disabled
// if needed, the ServerLogConfig is initialized beforehand so
// that all server blocks can populate it with data, even when not
@@ -757,6 +777,13 @@ func (st *ServerType) serversFromPairings(
}
}
+ wildcardHosts := []string{}
+ for _, addr := range sblock.parsedKeys {
+ if strings.HasPrefix(addr.Host, "*.") {
+ wildcardHosts = append(wildcardHosts, addr.Host[2:])
+ }
+ }
+
for _, addr := range sblock.parsedKeys {
// if server only uses HTTP port, auto-HTTPS will not apply
if listenersUseAnyPortOtherThan(srv.Listen, httpPort) {
@@ -772,6 +799,18 @@ func (st *ServerType) serversFromPairings(
}
}
+ // If prefer wildcard is enabled, then we add hosts that are
+ // already covered by the wildcard to the skip list
+ if srv.AutoHTTPS != nil && srv.AutoHTTPS.PreferWildcard && addr.Scheme == "https" {
+ baseDomain := addr.Host
+ if idx := strings.Index(baseDomain, "."); idx != -1 {
+ baseDomain = baseDomain[idx+1:]
+ }
+ if !strings.HasPrefix(addr.Host, "*.") && slices.Contains(wildcardHosts, baseDomain) {
+ srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, addr.Host)
+ }
+ }
+
// If TLS is specified as directive, it will also result in 1 or more connection policy being created
// Thus, catch-all address with non-standard port, e.g. :8443, can have TLS enabled without
// specifying prefix "https://"
@@ -919,7 +958,10 @@ func (st *ServerType) serversFromPairings(
if addressQualifiesForTLS &&
!hasCatchAllTLSConnPolicy &&
(len(srv.TLSConnPolicies) > 0 || !autoHTTPSWillAddConnPolicy || defaultSNI != "" || fallbackSNI != "") {
- srv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{DefaultSNI: defaultSNI, FallbackSNI: fallbackSNI})
+ srv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{
+ DefaultSNI: defaultSNI,
+ FallbackSNI: fallbackSNI,
+ })
}
// tidy things up a bit
diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go
index c14208b61..abbe8f418 100644
--- a/caddyconfig/httpcaddyfile/options.go
+++ b/caddyconfig/httpcaddyfile/options.go
@@ -452,15 +452,22 @@ func parseOptPersistConfig(d *caddyfile.Dispenser, _ any) (any, error) {
func parseOptAutoHTTPS(d *caddyfile.Dispenser, _ any) (any, error) {
d.Next() // consume option name
- if !d.Next() {
- return "", d.ArgErr()
- }
- val := d.Val()
- if d.Next() {
+ val := d.RemainingArgs()
+ if len(val) == 0 {
return "", d.ArgErr()
}
- if val != "off" && val != "disable_redirects" && val != "disable_certs" && val != "ignore_loaded_certs" {
- return "", d.Errf("auto_https must be one of 'off', 'disable_redirects', 'disable_certs', or 'ignore_loaded_certs'")
+ for _, v := range val {
+ switch v {
+ case "off":
+ case "disable_redirects":
+ case "disable_certs":
+ case "ignore_loaded_certs":
+ case "prefer_wildcard":
+ break
+
+ default:
+ return "", d.Errf("auto_https must be one of 'off', 'disable_redirects', 'disable_certs', 'ignore_loaded_certs', or 'prefer_wildcard'")
+ }
}
return val, nil
}
diff --git a/caddyconfig/httpcaddyfile/tlsapp.go b/caddyconfig/httpcaddyfile/tlsapp.go
index c6ff81b2b..ed708524d 100644
--- a/caddyconfig/httpcaddyfile/tlsapp.go
+++ b/caddyconfig/httpcaddyfile/tlsapp.go
@@ -45,8 +45,8 @@ func (st ServerType) buildTLSApp(
if hp, ok := options["http_port"].(int); ok {
httpPort = strconv.Itoa(hp)
}
- autoHTTPS := "on"
- if ah, ok := options["auto_https"].(string); ok {
+ autoHTTPS := []string{}
+ if ah, ok := options["auto_https"].([]string); ok {
autoHTTPS = ah
}
@@ -54,13 +54,14 @@ func (st ServerType) buildTLSApp(
// key, so that they don't get forgotten/omitted by auto-HTTPS
// (since they won't appear in route matchers)
httpsHostsSharedWithHostlessKey := make(map[string]struct{})
- if autoHTTPS != "off" {
+ if !slices.Contains(autoHTTPS, "off") {
for _, pair := range pairings {
for _, sb := range pair.serverBlocks {
for _, addr := range sb.parsedKeys {
if addr.Host != "" {
continue
}
+
// this server block has a hostless key, now
// go through and add all the hosts to the set
for _, otherAddr := range sb.parsedKeys {
@@ -350,7 +351,7 @@ func (st ServerType) buildTLSApp(
internalAP := &caddytls.AutomationPolicy{
IssuersRaw: []json.RawMessage{json.RawMessage(`{"module":"internal"}`)},
}
- if autoHTTPS != "off" && autoHTTPS != "disable_certs" {
+ if !slices.Contains(autoHTTPS, "off") && !slices.Contains(autoHTTPS, "disable_certs") {
for h := range httpsHostsSharedWithHostlessKey {
al = append(al, h)
if !certmagic.SubjectQualifiesForPublicCert(h) {
@@ -417,7 +418,10 @@ func (st ServerType) buildTLSApp(
}
// consolidate automation policies that are the exact same
- tlsApp.Automation.Policies = consolidateAutomationPolicies(tlsApp.Automation.Policies)
+ tlsApp.Automation.Policies = consolidateAutomationPolicies(
+ tlsApp.Automation.Policies,
+ slices.Contains(autoHTTPS, "prefer_wildcard"),
+ )
// ensure automation policies don't overlap subjects (this should be
// an error at provision-time as well, but catch it in the adapt phase
@@ -563,7 +567,7 @@ func newBaseAutomationPolicy(
// consolidateAutomationPolicies combines automation policies that are the same,
// for a cleaner overall output.
-func consolidateAutomationPolicies(aps []*caddytls.AutomationPolicy) []*caddytls.AutomationPolicy {
+func consolidateAutomationPolicies(aps []*caddytls.AutomationPolicy, preferWildcard bool) []*caddytls.AutomationPolicy {
// sort from most specific to least specific; we depend on this ordering
sort.SliceStable(aps, func(i, j int) bool {
if automationPolicyIsSubset(aps[i], aps[j]) {
@@ -648,6 +652,31 @@ outer:
j--
}
}
+
+ if preferWildcard {
+ // remove subjects from i if they're covered by a wildcard in j
+ iSubjs := aps[i].SubjectsRaw
+ for iSubj := 0; iSubj < len(iSubjs); iSubj++ {
+ for jSubj := range aps[j].SubjectsRaw {
+ if !strings.HasPrefix(aps[j].SubjectsRaw[jSubj], "*.") {
+ continue
+ }
+ if certmagic.MatchWildcard(aps[i].SubjectsRaw[iSubj], aps[j].SubjectsRaw[jSubj]) {
+ iSubjs = slices.Delete(iSubjs, iSubj, iSubj+1)
+ iSubj--
+ break
+ }
+ }
+ }
+ aps[i].SubjectsRaw = iSubjs
+
+ // remove i if it has no subjects left
+ if len(aps[i].SubjectsRaw) == 0 {
+ aps = slices.Delete(aps, i, i+1)
+ i--
+ continue outer
+ }
+ }
}
}