@marcel91200 / caddy Mirror · read-only / commits / b6686a54
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 14, 05:15 UTC

httpcaddyfile: Improve AP logic with OnDemand

We have users that have site blocks like *.*.tld with on-demand TLS enabled. While *.*.tld does not qualify for a publicly-trusted cert due to its wildcards, On-Demand TLS does not actually obtain a cert with those wildcards, since it uses the actual hostname on the handshake. This improves on that logic, but I am still not 100% satisfied with the result since I think we need to also check if another site block is more specific, like foo.example.tld, which might not have on-demand TLS enabled, and make sure an automation policy gets created before the more general policy with on-demand...

Matthew Holt committed Oct 22, 2020 at 12:40 UTC b6686a54d8b21bedbf042caa4a6c09d78d345fc7
2 files changed +31 -5
caddyconfig/httpcaddyfile/tlsapp.go
+11 -1
@@ -213,7 +213,17 @@ func (st ServerType) buildTLSApp(
213 if ap.Issuer == nil {
214 var internal, external []string
215 for _, s := range ap.Subjects {
216 - if certmagic.SubjectQualifiesForPublicCert(s) {
216 + if !certmagic.SubjectQualifiesForCert(s) {
217 + return nil, warnings, fmt.Errorf("subject does not qualify for certificate: '%s'", s)
218 + }
219 + // we don't use certmagic.SubjectQualifiesForPublicCert() because of one nuance:
220 + // names like *.*.tld that may not qualify for a public certificate are actually
221 + // fine when used with OnDemand, since OnDemand (currently) does not obtain
222 + // wildcards (if it ever does, there will be a separate config option to enable
223 + // it that we would need to check here) since the hostname is known at handshake;
224 + // and it is unexpected to switch to internal issuer when the user wants to get
225 + // regular certificates on-demand for a class of certs like *.*.tld.
226 + if !certmagic.SubjectIsIP(s) && !certmagic.SubjectIsInternal(s) && (strings.Count(s, "*.") < 2 || ap.OnDemand) {
227 external = append(external, s)
228 } else {
229 internal = append(internal, s)
modules/caddytls/tls.go
+20 -4
@@ -334,10 +334,26 @@ func (t *TLS) AddAutomationPolicy(ap *AutomationPolicy) error {
334 if err != nil {
335 return err
336 }
337 - for i, other := range t.Automation.Policies {
338 - // if a catch-all policy (or really, any policy with
339 - // fewer names) exists, prioritize this new policy
340 - if len(other.Subjects) < len(ap.Subjects) {
337 + // sort new automation policies just before any other which is a superset
338 + // of this one; if we find an existing policy that covers every subject in
339 + // ap but less specifically (e.g. a catch-all policy, or one with wildcards
340 + // or with fewer subjects), insert ap just before it, otherwise ap would
341 + // never be used because the first matching policy is more general
342 + for i, existing := range t.Automation.Policies {
343 + // first see if existing is superset of ap for all names
344 + var otherIsSuperset bool
345 + outer:
346 + for _, thisSubj := range ap.Subjects {
347 + for _, otherSubj := range existing.Subjects {
348 + if certmagic.MatchWildcard(thisSubj, otherSubj) {
349 + otherIsSuperset = true
350 + break outer
351 + }
352 + }
353 + }
354 + // if existing AP is a superset or if it contains fewer names (i.e. is
355 + // more general), then new AP is more specific, so insert before it
356 + if otherIsSuperset || len(existing.Subjects) < len(ap.Subjects) {
357 t.Automation.Policies = append(t.Automation.Policies[:i],
358 append([]*AutomationPolicy{ap}, t.Automation.Policies[i:]...)...)
359 return nil