From 55c89ccf2a39dcfd7286fcaed54787821ff9a1aa Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Fri, 14 Mar 2025 15:44:20 -0600 Subject: [PATCH 1/4] caddytls: Convert AP subjects to punycode Fixes bugs related to TLS automation --- modules/caddytls/automation.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 1bc86020d..96fc2ac61 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -28,6 +28,7 @@ import ( "github.com/mholt/acmez/v3" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "golang.org/x/net/idna" "github.com/caddyserver/caddy/v2" ) @@ -183,7 +184,12 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { repl := caddy.NewReplacer() subjects := make([]string, len(ap.SubjectsRaw)) for i, sub := range ap.SubjectsRaw { - subjects[i] = repl.ReplaceAll(sub, "") + sub = repl.ReplaceAll(sub, "") + subASCII, err := idna.ToASCII(sub) + if err != nil { + return fmt.Errorf("could not convert automation policy subject '%s' to punycode: %v", sub, err) + } + subjects[i] = subASCII } ap.subjects = subjects From b3e692ed09f8ba15b741621c4b16d8bfee38f8a1 Mon Sep 17 00:00:00 2001 From: Ted Date: Mon, 17 Mar 2025 17:58:46 +0300 Subject: [PATCH 2/4] caddyfile: Fix formatting for backquote wrapped braces (#6903) --- caddyconfig/caddyfile/formatter.go | 17 +++++++++++++++-- caddyconfig/caddyfile/formatter_test.go | 10 ++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/caddyconfig/caddyfile/formatter.go b/caddyconfig/caddyfile/formatter.go index d35f0ac6b..f1d12fa51 100644 --- a/caddyconfig/caddyfile/formatter.go +++ b/caddyconfig/caddyfile/formatter.go @@ -61,7 +61,8 @@ func Format(input []byte) []byte { heredocMarker []rune heredocClosingMarker []rune - nesting int // indentation level + nesting int // indentation level + withinBackquote bool ) write := func(ch rune) { @@ -88,6 +89,9 @@ func Format(input []byte) []byte { } panic(err) } + if ch == '`' { + withinBackquote = !withinBackquote + } // detect whether we have the start of a heredoc if !quoted && !(heredoc != heredocClosed || heredocEscaped) && @@ -236,14 +240,23 @@ func Format(input []byte) []byte { switch { case ch == '{': openBrace = true - openBraceWritten = false openBraceSpace = spacePrior && !beginningOfLine if openBraceSpace { write(' ') } + openBraceWritten = false + if withinBackquote { + write('{') + openBraceWritten = true + continue + } continue case ch == '}' && (spacePrior || !openBrace): + if withinBackquote { + write('}') + continue + } if last != '\n' { nextLine() } diff --git a/caddyconfig/caddyfile/formatter_test.go b/caddyconfig/caddyfile/formatter_test.go index 6eec822fe..a64383c3c 100644 --- a/caddyconfig/caddyfile/formatter_test.go +++ b/caddyconfig/caddyfile/formatter_test.go @@ -434,6 +434,16 @@ block2 { } `, }, + { + description: "Preserve braces wrapped by backquotes", + input: "block {respond `All braces should remain: {{now | date \"2006\"}}`}", + expect: "block {respond `All braces should remain: {{now | date \"2006\"}}`}", + }, + { + description: "Preserve braces wrapped by quotes", + input: "block {respond \"All braces should remain: {{now | date `2006`}}\"}", + expect: "block {respond \"All braces should remain: {{now | date `2006`}}\"}", + }, } { // the formatter should output a trailing newline, // even if the tests aren't written to expect that From e276994174983dbb190d4bb9acaab157ef14373b Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 17 Mar 2025 12:02:23 -0600 Subject: [PATCH 3/4] caddytls: Initialize permission module earlier (fix #6901) Bug introduced in 4ebcfed9c942c59f473f12f8108e1d0fa92e0855 --- modules/caddytls/automation.go | 10 ++++------ modules/caddytls/tls.go | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/modules/caddytls/automation.go b/modules/caddytls/automation.go index 96fc2ac61..6f3b98a3e 100644 --- a/modules/caddytls/automation.go +++ b/modules/caddytls/automation.go @@ -173,9 +173,6 @@ type AutomationPolicy struct { subjects []string magic *certmagic.Config storage certmagic.Storage - - // Whether this policy had explicit managers configured directly on it. - hadExplicitManagers bool } // Provision sets up ap and builds its underlying CertMagic config. @@ -212,8 +209,9 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { // store them on the policy before putting it on the config // load and provision any cert manager modules + var hadExplicitManagers bool if ap.ManagersRaw != nil { - ap.hadExplicitManagers = true + hadExplicitManagers = true vals, err := tlsApp.ctx.LoadModule(ap, "ManagersRaw") if err != nil { return fmt.Errorf("loading external certificate manager modules: %v", err) @@ -273,9 +271,9 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error { // prevent issuance from Issuers (when Managers don't provide a certificate) if there's no // permission module configured noProtections := ap.isWildcardOrDefault() && !ap.onlyInternalIssuer() && (tlsApp.Automation == nil || tlsApp.Automation.OnDemand == nil || tlsApp.Automation.OnDemand.permission == nil) - failClosed := noProtections && !ap.hadExplicitManagers // don't allow on-demand issuance (other than implicit managers) if no managers have been explicitly configured + failClosed := noProtections && !hadExplicitManagers // don't allow on-demand issuance (other than implicit managers) if no managers have been explicitly configured if noProtections { - if !ap.hadExplicitManagers { + if !hadExplicitManagers { // no managers, no explicitly-configured permission module, this is a config error return fmt.Errorf("on-demand TLS cannot be enabled without a permission module to prevent abuse; please refer to documentation for details") } diff --git a/modules/caddytls/tls.go b/modules/caddytls/tls.go index 089794efb..0f8433960 100644 --- a/modules/caddytls/tls.go +++ b/modules/caddytls/tls.go @@ -262,6 +262,18 @@ func (t *TLS) Provision(ctx caddy.Context) error { } } + // on-demand permission module + if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.PermissionRaw != nil { + if t.Automation.OnDemand.Ask != "" { + return fmt.Errorf("on-demand TLS config conflict: both 'ask' endpoint and a 'permission' module are specified; 'ask' is deprecated, so use only the permission module") + } + val, err := ctx.LoadModule(t.Automation.OnDemand, "PermissionRaw") + if err != nil { + return fmt.Errorf("loading on-demand TLS permission module: %v", err) + } + t.Automation.OnDemand.permission = val.(OnDemandPermission) + } + // automation/management policies if t.Automation == nil { t.Automation = new(AutomationConfig) @@ -294,18 +306,6 @@ func (t *TLS) Provision(ctx caddy.Context) error { } } - // on-demand permission module - if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.PermissionRaw != nil { - if t.Automation.OnDemand.Ask != "" { - return fmt.Errorf("on-demand TLS config conflict: both 'ask' endpoint and a 'permission' module are specified; 'ask' is deprecated, so use only the permission module") - } - val, err := ctx.LoadModule(t.Automation.OnDemand, "PermissionRaw") - if err != nil { - return fmt.Errorf("loading on-demand TLS permission module: %v", err) - } - t.Automation.OnDemand.permission = val.(OnDemandPermission) - } - // run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036) if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.Ask != "" { t.Automation.OnDemand.Ask, err = repl.ReplaceOrErr(t.Automation.OnDemand.Ask, true, true) From 8dc76676fb5156f971db49c50a5c509d1c93613b Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Wed, 19 Mar 2025 09:53:42 -0600 Subject: [PATCH 4/4] chore: Modernize a couple for loops --- caddyconfig/httpcaddyfile/tlsapp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/caddyconfig/httpcaddyfile/tlsapp.go b/caddyconfig/httpcaddyfile/tlsapp.go index 8a21ca038..2eedca453 100644 --- a/caddyconfig/httpcaddyfile/tlsapp.go +++ b/caddyconfig/httpcaddyfile/tlsapp.go @@ -340,7 +340,7 @@ func (st ServerType) buildTLSApp( combined = reflect.New(reflect.TypeOf(cl)).Elem() } clVal := reflect.ValueOf(cl) - for i := 0; i < clVal.Len(); i++ { + for i := range clVal.Len() { combined = reflect.Append(combined, clVal.Index(i)) } loadersByName[name] = combined.Interface().(caddytls.CertificateLoader) @@ -469,7 +469,7 @@ func (st ServerType) buildTLSApp( globalPreferredChains := options["preferred_chains"] hasGlobalACMEDefaults := globalEmail != nil || globalACMECA != nil || globalACMECARoot != nil || globalACMEDNS != nil || globalACMEEAB != nil || globalPreferredChains != nil if hasGlobalACMEDefaults { - for i := 0; i < len(tlsApp.Automation.Policies); i++ { + for i := range tlsApp.Automation.Policies { ap := tlsApp.Automation.Policies[i] if len(ap.Issuers) == 0 && automationPolicyHasAllPublicNames(ap) { // for public names, create default issuers which will later be filled in with configured global defaults