@@ -92,6 +92,25 @@ func (st ServerType) buildTLSApp(
92
92
tlsApp .Automation .Policies = append (tlsApp .Automation .Policies , catchAllAP )
93
93
}
94
94
95
+ // collect all hosts that have a wildcard in them, and arent HTTP
96
+ wildcardHosts := []string {}
97
+ for _ , p := range pairings {
98
+ var addresses []string
99
+ for _ , addressWithProtocols := range p .addressesWithProtocols {
100
+ addresses = append (addresses , addressWithProtocols .address )
101
+ }
102
+ if ! listenersUseAnyPortOtherThan (addresses , httpPort ) {
103
+ continue
104
+ }
105
+ for _ , sblock := range p .serverBlocks {
106
+ for _ , addr := range sblock .parsedKeys {
107
+ if strings .HasPrefix (addr .Host , "*." ) {
108
+ wildcardHosts = append (wildcardHosts , addr .Host [2 :])
109
+ }
110
+ }
111
+ }
112
+ }
113
+
95
114
for _ , p := range pairings {
96
115
// avoid setting up TLS automation policies for a server that is HTTP-only
97
116
var addresses []string
@@ -115,6 +134,12 @@ func (st ServerType) buildTLSApp(
115
134
return nil , warnings , err
116
135
}
117
136
137
+ // make a plain copy so we can compare whether we made any changes
138
+ apCopy , err := newBaseAutomationPolicy (options , warnings , true )
139
+ if err != nil {
140
+ return nil , warnings , err
141
+ }
142
+
118
143
sblockHosts := sblock .hostsFromKeys (false )
119
144
if len (sblockHosts ) == 0 && catchAllAP != nil {
120
145
ap = catchAllAP
@@ -217,9 +242,21 @@ func (st ServerType) buildTLSApp(
217
242
catchAllAP = ap
218
243
}
219
244
245
+ hostsNotHTTP := sblock .hostsFromKeysNotHTTP (httpPort )
246
+ sort .Strings (hostsNotHTTP ) // solely for deterministic test results
247
+
248
+ // if the we prefer wildcards and the AP is unchanged,
249
+ // then we can skip this AP because it should be covered
250
+ // by an AP with a wildcard
251
+ if slices .Contains (autoHTTPS , "prefer_wildcard" ) {
252
+ if hostsCoveredByWildcard (hostsNotHTTP , wildcardHosts ) &&
253
+ reflect .DeepEqual (ap , apCopy ) {
254
+ continue
255
+ }
256
+ }
257
+
220
258
// associate our new automation policy with this server block's hosts
221
- ap .SubjectsRaw = sblock .hostsFromKeysNotHTTP (httpPort )
222
- sort .Strings (ap .SubjectsRaw ) // solely for deterministic test results
259
+ ap .SubjectsRaw = hostsNotHTTP
223
260
224
261
// if a combination of public and internal names were given
225
262
// for this same server block and no issuer was specified, we
@@ -258,6 +295,7 @@ func (st ServerType) buildTLSApp(
258
295
ap2 .IssuersRaw = []json.RawMessage {caddyconfig .JSONModuleObject (caddytls.InternalIssuer {}, "module" , "internal" , & warnings )}
259
296
}
260
297
}
298
+
261
299
if tlsApp .Automation == nil {
262
300
tlsApp .Automation = new (caddytls.AutomationConfig )
263
301
}
@@ -418,10 +456,7 @@ func (st ServerType) buildTLSApp(
418
456
}
419
457
420
458
// consolidate automation policies that are the exact same
421
- tlsApp .Automation .Policies = consolidateAutomationPolicies (
422
- tlsApp .Automation .Policies ,
423
- slices .Contains (autoHTTPS , "prefer_wildcard" ),
424
- )
459
+ tlsApp .Automation .Policies = consolidateAutomationPolicies (tlsApp .Automation .Policies )
425
460
426
461
// ensure automation policies don't overlap subjects (this should be
427
462
// an error at provision-time as well, but catch it in the adapt phase
@@ -567,7 +602,7 @@ func newBaseAutomationPolicy(
567
602
568
603
// consolidateAutomationPolicies combines automation policies that are the same,
569
604
// for a cleaner overall output.
570
- func consolidateAutomationPolicies (aps []* caddytls.AutomationPolicy , preferWildcard bool ) []* caddytls.AutomationPolicy {
605
+ func consolidateAutomationPolicies (aps []* caddytls.AutomationPolicy ) []* caddytls.AutomationPolicy {
571
606
// sort from most specific to least specific; we depend on this ordering
572
607
sort .SliceStable (aps , func (i , j int ) bool {
573
608
if automationPolicyIsSubset (aps [i ], aps [j ]) {
@@ -652,31 +687,6 @@ outer:
652
687
j --
653
688
}
654
689
}
655
-
656
- if preferWildcard {
657
- // remove subjects from i if they're covered by a wildcard in j
658
- iSubjs := aps [i ].SubjectsRaw
659
- for iSubj := 0 ; iSubj < len (iSubjs ); iSubj ++ {
660
- for jSubj := range aps [j ].SubjectsRaw {
661
- if ! strings .HasPrefix (aps [j ].SubjectsRaw [jSubj ], "*." ) {
662
- continue
663
- }
664
- if certmagic .MatchWildcard (aps [i ].SubjectsRaw [iSubj ], aps [j ].SubjectsRaw [jSubj ]) {
665
- iSubjs = slices .Delete (iSubjs , iSubj , iSubj + 1 )
666
- iSubj --
667
- break
668
- }
669
- }
670
- }
671
- aps [i ].SubjectsRaw = iSubjs
672
-
673
- // remove i if it has no subjects left
674
- if len (aps [i ].SubjectsRaw ) == 0 {
675
- aps = slices .Delete (aps , i , i + 1 )
676
- i --
677
- continue outer
678
- }
679
- }
680
690
}
681
691
}
682
692
@@ -748,3 +758,20 @@ func automationPolicyHasAllPublicNames(ap *caddytls.AutomationPolicy) bool {
748
758
func isTailscaleDomain (name string ) bool {
749
759
return strings .HasSuffix (strings .ToLower (name ), ".ts.net" )
750
760
}
761
+
762
+ func hostsCoveredByWildcard (hosts []string , wildcards []string ) bool {
763
+ if len (hosts ) == 0 || len (wildcards ) == 0 {
764
+ return false
765
+ }
766
+ for _ , host := range hosts {
767
+ for _ , wildcard := range wildcards {
768
+ if strings .HasPrefix (host , "*." ) {
769
+ continue
770
+ }
771
+ if certmagic .MatchWildcard (host , "*." + wildcard ) {
772
+ return true
773
+ }
774
+ }
775
+ }
776
+ return false
777
+ }
0 commit comments