@@ -243,22 +243,49 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
243243 }
244244 }
245245
246+ // build certmagic.Config and attach it to the policy
247+ storage := ap .storage
248+ if storage == nil {
249+ storage = tlsApp .ctx .Storage ()
250+ }
251+ cfg , err := ap .makeCertMagicConfig (tlsApp , issuers , storage )
252+ if err != nil {
253+ return err
254+ }
255+ certCacheMu .RLock ()
256+ ap .magic = certmagic .New (certCache , cfg )
257+ certCacheMu .RUnlock ()
258+
259+ // give issuers a chance to see the config pointer
260+ for _ , issuer := range ap .magic .Issuers {
261+ if annoying , ok := issuer .(ConfigSetter ); ok {
262+ annoying .SetConfig (ap .magic )
263+ }
264+ }
265+
266+ return nil
267+ }
268+
269+ // makeCertMagicConfig constructs a certmagic.Config for this policy using the
270+ // provided issuers and storage. It encapsulates common logic shared between
271+ // Provision and RebuildCertMagic so we don't duplicate code.
272+ func (ap * AutomationPolicy ) makeCertMagicConfig (tlsApp * TLS , issuers []certmagic.Issuer , storage certmagic.Storage ) (certmagic.Config , error ) {
273+ // key source
246274 keyType := ap .KeyType
247275 if keyType != "" {
248276 var err error
249277 keyType , err = caddy .NewReplacer ().ReplaceOrErr (ap .KeyType , true , true )
250278 if err != nil {
251- return fmt .Errorf ("invalid key type %s: %s" , ap .KeyType , err )
279+ return certmagic. Config {}, fmt .Errorf ("invalid key type %s: %s" , ap .KeyType , err )
252280 }
253281 if _ , ok := supportedCertKeyTypes [keyType ]; ! ok {
254- return fmt .Errorf ("unrecognized key type: %s" , keyType )
282+ return certmagic. Config {}, fmt .Errorf ("unrecognized key type: %s" , keyType )
255283 }
256284 }
257285 keySource := certmagic.StandardKeyGenerator {
258286 KeyType : supportedCertKeyTypes [keyType ],
259287 }
260288
261- storage := ap .storage
262289 if storage == nil {
263290 storage = tlsApp .ctx .Storage ()
264291 }
@@ -277,7 +304,7 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
277304 if noProtections {
278305 if ! ap .hadExplicitManagers {
279306 // no managers, no explicitly-configured permission module, this is a config error
280- return fmt .Errorf ("on-demand TLS cannot be enabled without a permission module to prevent abuse; please refer to documentation for details" )
307+ return certmagic. Config {}, fmt .Errorf ("on-demand TLS cannot be enabled without a permission module to prevent abuse; please refer to documentation for details" )
281308 }
282309 // allow on-demand to be enabled but only for the purpose of the Managers; issuance won't be allowed from Issuers
283310 tlsApp .logger .Warn ("on-demand TLS can only get certificates from the configured external manager(s) because no ask endpoint / permission module is specified" )
@@ -334,7 +361,7 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
334361 }
335362 }
336363
337- template := certmagic.Config {
364+ cfg := certmagic.Config {
338365 MustStaple : ap .MustStaple ,
339366 RenewalWindowRatio : ap .RenewalWindowRatio ,
340367 KeySource : keySource ,
@@ -349,8 +376,31 @@ func (ap *AutomationPolicy) Provision(tlsApp *TLS) error {
349376 Issuers : issuers ,
350377 Logger : tlsApp .logger ,
351378 }
379+
380+ return cfg , nil
381+ }
382+
383+ // IsProvisioned reports whether the automation policy has been
384+ // provisioned. A provisioned policy has an initialized CertMagic
385+ // instance (i.e. ap.magic != nil).
386+ func (ap * AutomationPolicy ) IsProvisioned () bool { return ap .magic != nil }
387+
388+ // RebuildCertMagic rebuilds the policy's CertMagic configuration from the
389+ // policy's already-populated fields (Issuers, Managers, storage, etc.) and
390+ // replaces the internal CertMagic instance. This is a lightweight
391+ // alternative to calling Provision because it does not re-provision
392+ // modules or re-run module Provision; instead, it constructs a new
393+ // certmagic.Config and calls SetConfig on issuers so they receive updated
394+ // templates (for example, alternate HTTP/TLS ports supplied by the HTTP
395+ // app). RebuildCertMagic should only be called when the policy's required
396+ // fields are already populated.
397+ func (ap * AutomationPolicy ) RebuildCertMagic (tlsApp * TLS ) error {
398+ cfg , err := ap .makeCertMagicConfig (tlsApp , ap .Issuers , ap .storage )
399+ if err != nil {
400+ return err
401+ }
352402 certCacheMu .RLock ()
353- ap .magic = certmagic .New (certCache , template )
403+ ap .magic = certmagic .New (certCache , cfg )
354404 certCacheMu .RUnlock ()
355405
356406 // sometimes issuers may need the parent certmagic.Config in
0 commit comments