@marcel91200 / caddy Mirror · read-only / commits / 6a210e96
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 11:00 UTC

caddyfile: preserve implicit TLS issuer semantics (#7743)

Zen Dodd committed May 21, 2026 at 02:48 UTC 6a210e96ee481a07abde725fd4eae8c76cccfe82
2 files changed +71 -1
caddyconfig/httpcaddyfile/tlsapp.go
+53 -1
@@ -1036,7 +1036,7 @@ outer:
1036 // otherwise the one without any subjects (a catch-all) would be
1037 // eaten up by the one with subjects; and if both have subjects, we
1038 // need to combine their lists
1039 - if reflect.DeepEqual(aps[i].IssuersRaw, aps[j].IssuersRaw) &&
1039 + if automationPoliciesHaveSameIssuers(aps[i], aps[j]) &&
1040 reflect.DeepEqual(aps[i].ManagersRaw, aps[j].ManagersRaw) &&
1041 bytes.Equal(aps[i].StorageRaw, aps[j].StorageRaw) &&
1042 aps[i].MustStaple == aps[j].MustStaple &&
@@ -1128,6 +1128,58 @@ func subjectQualifiesForPublicCert(ap *caddytls.AutomationPolicy, subj string) b
1128 (strings.Count(subj, "*.") < 2 || ap.OnDemand)
1129 }
1130
1131 +func automationPoliciesHaveSameIssuers(a, b *caddytls.AutomationPolicy) bool {
1132 + if reflect.DeepEqual(a.IssuersRaw, b.IssuersRaw) {
1133 + return automationPoliciesHaveCompatibleImplicitIssuers(a, b)
1134 + }
1135 + return automationPolicyUsesDefaultInternalIssuer(a) && automationPolicyUsesDefaultInternalIssuer(b)
1136 +}
1137 +
1138 +func automationPolicyUsesDefaultInternalIssuer(ap *caddytls.AutomationPolicy) bool {
1139 + if len(ap.IssuersRaw) == 0 && len(ap.Issuers) == 0 {
1140 + return automationPolicyImplicitIssuerClass(ap) == "internal"
1141 + }
1142 + return len(ap.IssuersRaw) == 1 &&
1143 + len(ap.Issuers) == 0 &&
1144 + string(bytes.TrimSpace(ap.IssuersRaw[0])) == `{"module":"internal"}`
1145 +}
1146 +
1147 +// automationPoliciesHaveCompatibleImplicitIssuers returns whether two policies
1148 +// without explicit issuers can be consolidated without changing default issuer
1149 +// selection for their subjects.
1150 +func automationPoliciesHaveCompatibleImplicitIssuers(a, b *caddytls.AutomationPolicy) bool {
1151 + if len(a.IssuersRaw) > 0 || len(a.Issuers) > 0 ||
1152 + len(b.IssuersRaw) > 0 || len(b.Issuers) > 0 {
1153 + return true
1154 + }
1155 +
1156 + aClass := automationPolicyImplicitIssuerClass(a)
1157 + bClass := automationPolicyImplicitIssuerClass(b)
1158 + return aClass == "catch-all" || bClass == "catch-all" || aClass == bClass
1159 +}
1160 +
1161 +func automationPolicyImplicitIssuerClass(ap *caddytls.AutomationPolicy) string {
1162 + if len(ap.SubjectsRaw) == 0 {
1163 + return "catch-all"
1164 + }
1165 +
1166 + hasPublic := slices.ContainsFunc(ap.SubjectsRaw, func(subj string) bool {
1167 + return subjectQualifiesForPublicCert(ap, subj)
1168 + })
1169 + hasInternal := slices.ContainsFunc(ap.SubjectsRaw, func(subj string) bool {
1170 + return !subjectQualifiesForPublicCert(ap, subj)
1171 + })
1172 +
1173 + switch {
1174 + case hasPublic && hasInternal:
1175 + return "mixed"
1176 + case hasPublic:
1177 + return "public"
1178 + default:
1179 + return "internal"
1180 + }
1181 +}
1182 +
1183 // automationPolicyHasAllPublicNames returns true if all the names on the policy
1184 // do NOT qualify for public certs OR are tailscale domains.
1185 func automationPolicyHasAllPublicNames(ap *caddytls.AutomationPolicy) bool {
caddyconfig/httpcaddyfile/tlsapp_test.go
+18
@@ -3,6 +3,7 @@ package httpcaddyfile
3 import (
4 "testing"
5
6 + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
7 "github.com/caddyserver/caddy/v2/modules/caddytls"
8 )
9
@@ -54,3 +55,20 @@ func TestAutomationPolicyIsSubset(t *testing.T) {
55 }
56 }
57 }
58 +
59 +func TestAutomationPoliciesAllowSameHostOnDifferentPorts(t *testing.T) {
60 + input := `https://example.com:5000 localhost:5000 {
61 + respond "one"
62 +}
63 +
64 +https://example.net localhost:8080 {
65 + respond "two"
66 +}
67 +`
68 +
69 + adapter := caddyfile.Adapter{ServerType: ServerType{}}
70 + _, _, err := adapter.Adapt([]byte(input), nil)
71 + if err != nil {
72 + t.Fatalf("adapting Caddyfile: %v", err)
73 + }
74 +}