@marcel91200 / caddy Mirror · read-only / commits / 4ebcfed9
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 12, 02:00 UTC

caddytls: Reorder provisioning steps (fix #6877)

Also add a quick check to allow users to load their own certs for ECH (outer) domains.

Matthew Holt committed Mar 7, 2025 at 11:17 UTC 4ebcfed9c942c59f473f12f8108e1d0fa92e0855
1 file changed +62 -56
modules/caddytls/tls.go
+62 -56
@@ -182,17 +182,6 @@ func (t *TLS) Provision(ctx caddy.Context) error {
182 t.dns = dnsMod
183 }
184
185 - // ECH (Encrypted ClientHello) initialization
186 - if t.EncryptedClientHello != nil {
187 - t.EncryptedClientHello.configs = make(map[string][]echConfig)
188 - outerNames, err := t.EncryptedClientHello.Provision(ctx)
189 - if err != nil {
190 - return fmt.Errorf("provisioning Encrypted ClientHello components: %v", err)
191 - }
192 - // outer names should have certificates to reduce client brittleness
193 - t.automateNames = append(t.automateNames, outerNames...)
194 - }
195 -
185 // set up a new certificate cache; this (re)loads all certificates
186 cacheOpts := certmagic.CacheOptions{
187 GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
@@ -243,31 +232,34 @@ func (t *TLS) Provision(ctx caddy.Context) error {
232 t.certificateLoaders = append(t.certificateLoaders, modIface.(CertificateLoader))
233 }
234
246 - // on-demand permission module
247 - if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.PermissionRaw != nil {
248 - if t.Automation.OnDemand.Ask != "" {
249 - 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")
250 - }
251 - val, err := ctx.LoadModule(t.Automation.OnDemand, "PermissionRaw")
252 - if err != nil {
253 - return fmt.Errorf("loading on-demand TLS permission module: %v", err)
254 - }
255 - t.Automation.OnDemand.permission = val.(OnDemandPermission)
256 - }
257 -
258 - // run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036)
259 - if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.Ask != "" {
260 - t.Automation.OnDemand.Ask, err = repl.ReplaceOrErr(t.Automation.OnDemand.Ask, true, true)
235 + // using the certificate loaders we just initialized, load
236 + // manual/static (unmanaged) certificates - we do this in
237 + // provision so that other apps (such as http) can know which
238 + // certificates have been manually loaded, and also so that
239 + // commands like validate can be a better test
240 + certCacheMu.RLock()
241 + magic := certmagic.New(certCache, certmagic.Config{
242 + Storage: ctx.Storage(),
243 + Logger: t.logger,
244 + OnEvent: t.onEvent,
245 + OCSP: certmagic.OCSPConfig{
246 + DisableStapling: t.DisableOCSPStapling,
247 + },
248 + DisableStorageCheck: t.DisableStorageCheck,
249 + })
250 + certCacheMu.RUnlock()
251 + for _, loader := range t.certificateLoaders {
252 + certs, err := loader.LoadCertificates()
253 if err != nil {
262 - return fmt.Errorf("preparing 'ask' endpoint: %v", err)
263 - }
264 - perm := PermissionByHTTP{
265 - Endpoint: t.Automation.OnDemand.Ask,
254 + return fmt.Errorf("loading certificates: %v", err)
255 }
267 - if err := perm.Provision(ctx); err != nil {
268 - return fmt.Errorf("provisioning 'ask' module: %v", err)
256 + for _, cert := range certs {
257 + hash, err := magic.CacheUnmanagedTLSCertificate(ctx, cert.Certificate, cert.Tags)
258 + if err != nil {
259 + return fmt.Errorf("caching unmanaged certificate: %v", err)
260 + }
261 + t.loaded[hash] = ""
262 }
270 - t.Automation.OnDemand.permission = perm
263 }
264
265 // automation/management policies
@@ -302,6 +294,33 @@ func (t *TLS) Provision(ctx caddy.Context) error {
294 }
295 }
296
297 + // on-demand permission module
298 + if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.PermissionRaw != nil {
299 + if t.Automation.OnDemand.Ask != "" {
300 + 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")
301 + }
302 + val, err := ctx.LoadModule(t.Automation.OnDemand, "PermissionRaw")
303 + if err != nil {
304 + return fmt.Errorf("loading on-demand TLS permission module: %v", err)
305 + }
306 + t.Automation.OnDemand.permission = val.(OnDemandPermission)
307 + }
308 +
309 + // run replacer on ask URL (for environment variables) -- return errors to prevent surprises (#5036)
310 + if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.Ask != "" {
311 + t.Automation.OnDemand.Ask, err = repl.ReplaceOrErr(t.Automation.OnDemand.Ask, true, true)
312 + if err != nil {
313 + return fmt.Errorf("preparing 'ask' endpoint: %v", err)
314 + }
315 + perm := PermissionByHTTP{
316 + Endpoint: t.Automation.OnDemand.Ask,
317 + }
318 + if err := perm.Provision(ctx); err != nil {
319 + return fmt.Errorf("provisioning 'ask' module: %v", err)
320 + }
321 + t.Automation.OnDemand.permission = perm
322 + }
323 +
324 // session ticket ephemeral keys (STEK) service and provider
325 if t.SessionTickets != nil {
326 err := t.SessionTickets.provision(ctx)
@@ -310,32 +329,19 @@ func (t *TLS) Provision(ctx caddy.Context) error {
329 }
330 }
331
313 - // load manual/static (unmanaged) certificates - we do this in
314 - // provision so that other apps (such as http) can know which
315 - // certificates have been manually loaded, and also so that
316 - // commands like validate can be a better test
317 - certCacheMu.RLock()
318 - magic := certmagic.New(certCache, certmagic.Config{
319 - Storage: ctx.Storage(),
320 - Logger: t.logger,
321 - OnEvent: t.onEvent,
322 - OCSP: certmagic.OCSPConfig{
323 - DisableStapling: t.DisableOCSPStapling,
324 - },
325 - DisableStorageCheck: t.DisableStorageCheck,
326 - })
327 - certCacheMu.RUnlock()
328 - for _, loader := range t.certificateLoaders {
329 - certs, err := loader.LoadCertificates()
332 + // ECH (Encrypted ClientHello) initialization
333 + if t.EncryptedClientHello != nil {
334 + t.EncryptedClientHello.configs = make(map[string][]echConfig)
335 + outerNames, err := t.EncryptedClientHello.Provision(ctx)
336 if err != nil {
331 - return fmt.Errorf("loading certificates: %v", err)
337 + return fmt.Errorf("provisioning Encrypted ClientHello components: %v", err)
338 }
333 - for _, cert := range certs {
334 - hash, err := magic.CacheUnmanagedTLSCertificate(ctx, cert.Certificate, cert.Tags)
335 - if err != nil {
336 - return fmt.Errorf("caching unmanaged certificate: %v", err)
339 +
340 + // outer names should have certificates to reduce client brittleness
341 + for _, outerName := range outerNames {
342 + if !t.HasCertificateForSubject(outerName) {
343 + t.automateNames = append(t.automateNames, outerNames...)
344 }
338 - t.loaded[hash] = ""
345 }
346 }
347