@@ -61,7 +61,6 @@ public class AcmeCaPlugin : IAnyCAPlugin
6161 {
6262 private static readonly ILogger _logger = LogHandler . GetClassLogger < AcmeCaPlugin > ( ) ;
6363 private IAnyCAPluginConfigProvider Config { get ; set ; }
64- private IDomainValidator _domainValidator ;
6564 private readonly IDomainValidatorFactory _validatorFactory ;
6665
6766 // Constants for better maintainability
@@ -88,7 +87,7 @@ public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDa
8887 _logger . MethodEntry ( ) ;
8988 Config = configProvider ?? throw new ArgumentNullException ( nameof ( configProvider ) ) ;
9089
91- // Factory is now required - all DNS providers are externalized as plugins
90+ // Validate that factory is available - validators will be resolved per-domain during enrollment
9291 if ( _validatorFactory == null )
9392 {
9493 var errorMsg = "IDomainValidatorFactory is required. DNS providers are now loaded as external plugins. " +
@@ -97,28 +96,7 @@ public void Initialize(IAnyCAPluginConfigProvider configProvider, ICertificateDa
9796 throw new InvalidOperationException ( errorMsg ) ;
9897 }
9998
100- _logger . LogInformation ( "Resolving domain validator from plugin system" ) ;
101-
102- // Resolve domain validator from plugin system
103- _domainValidator = _validatorFactory . ResolveDomainValidator (
104- domain : "*" , // Wildcard - let the factory choose based on configuration
105- validationType : DNS_CHALLENGE_TYPE
106- ) ;
107-
108- if ( _domainValidator == null )
109- {
110- var errorMsg = $ "Failed to resolve domain validator for type '{ DNS_CHALLENGE_TYPE } '. " +
111- "Ensure the appropriate DNS provider plugin is deployed and configured." ;
112- _logger . LogError ( errorMsg ) ;
113- throw new InvalidOperationException ( errorMsg ) ;
114- }
115-
116- // Initialize the validator with configuration
117- var domainValidatorConfig = new DomainValidatorConfigProvider ( configProvider . CAConnectionData ) ;
118- _domainValidator . Initialize ( domainValidatorConfig ) ;
119-
120- _logger . LogInformation ( "Successfully initialized domain validator from plugin: {ValidatorType}" ,
121- _domainValidator . GetType ( ) . FullName ) ;
99+ _logger . LogInformation ( "IDomainValidatorFactory available - domain validators will be resolved per-domain during enrollment" ) ;
122100
123101 _logger . MethodExit ( ) ;
124102 }
@@ -527,9 +505,9 @@ private async Task ProcessAuthorizations(AcmeClient acmeClient, OrderDetails ord
527505 }
528506
529507 var dnsVerifier = new DnsVerificationHelper ( _logger , config . DnsVerificationServer ) ;
530- var pendingChallenges = new List < ( Authorization authz , Challenge challenge , Dns01ChallengeValidationDetails validation ) > ( ) ;
508+ var pendingChallenges = new List < ( Authorization authz , Challenge challenge , Dns01ChallengeValidationDetails validation , IDomainValidator validator ) > ( ) ;
531509
532- // First pass: Create all DNS records using IDomainValidator
510+ // First pass: Create all DNS records using per-domain IDomainValidator
533511 foreach ( var authzUrl in payload . Authorizations )
534512 {
535513 var authz = await acmeClient . GetAuthorizationAsync ( authzUrl ) ;
@@ -548,23 +526,42 @@ private async Task ProcessAuthorizations(AcmeClient acmeClient, OrderDetails ord
548526 if ( validation == null )
549527 throw new InvalidOperationException ( $ "Failed to decode { DNS_CHALLENGE_TYPE } challenge validation details") ;
550528
551- // Use IDomainValidator instead of DnsProviderFactory directly
552- var result = await _domainValidator . StageValidation (
529+ // Resolve domain validator for this specific domain
530+ var domain = authz . Identifier . Value ;
531+ _logger . LogInformation ( "Resolving domain validator for domain: {Domain}" , domain ) ;
532+
533+ var domainValidator = _validatorFactory . ResolveDomainValidator ( domain , DNS_CHALLENGE_TYPE ) ;
534+ if ( domainValidator == null )
535+ {
536+ throw new InvalidOperationException (
537+ $ "Failed to resolve domain validator for domain '{ domain } '. " +
538+ "Ensure the appropriate DNS provider plugin is deployed and configured for this domain's zone." ) ;
539+ }
540+
541+ // Initialize the validator with configuration
542+ var domainValidatorConfig = new DomainValidatorConfigProvider ( Config . CAConnectionData ) ;
543+ domainValidator . Initialize ( domainValidatorConfig ) ;
544+
545+ _logger . LogInformation ( "Using domain validator: {ValidatorType} for domain: {Domain}" ,
546+ domainValidator . GetType ( ) . Name , domain ) ;
547+
548+ // Stage the DNS validation
549+ var result = await domainValidator . StageValidation (
553550 validation . DnsRecordName ,
554551 validation . DnsRecordValue ,
555552 CancellationToken . None ) ;
556553
557554 if ( ! result . Success )
558- throw new InvalidOperationException ( $ "Failed to stage DNS validation: { result . ErrorMessage } ") ;
555+ throw new InvalidOperationException ( $ "Failed to stage DNS validation for { domain } : { result . ErrorMessage } ") ;
559556
560557 _logger . LogInformation ( "Created DNS record {RecordName} for domain {Domain}" ,
561- validation . DnsRecordName , authz . Identifier . Value ) ;
558+ validation . DnsRecordName , domain ) ;
562559
563- pendingChallenges . Add ( ( authz , challenge , validation ) ) ;
560+ pendingChallenges . Add ( ( authz , challenge , validation , domainValidator ) ) ;
564561 }
565562
566563 // Second pass: Wait for DNS propagation and submit challenges
567- foreach ( var ( authz , challenge , validation ) in pendingChallenges )
564+ foreach ( var ( authz , challenge , validation , validator ) in pendingChallenges )
568565 {
569566 // Skip external DNS verification for Infoblox since it cannot ping external DNS providers
570567 bool isInfoblox = config . DnsProvider ? . Trim ( ) . Equals ( "infoblox" , StringComparison . OrdinalIgnoreCase ) ?? false ;
@@ -601,10 +598,21 @@ private async Task ProcessAuthorizations(AcmeClient acmeClient, OrderDetails ord
601598 await acmeClient . AnswerChallengeAsync ( challenge ) ;
602599 }
603600
604- // Optional: Cleanup after challenges complete
605- foreach ( var ( authz , challenge , validation ) in pendingChallenges )
601+ // Cleanup: Remove DNS records using the per-domain validators
602+ foreach ( var ( authz , challenge , validation , validator ) in pendingChallenges )
606603 {
607- await _domainValidator . CleanupValidation ( validation . DnsRecordName , CancellationToken . None ) ;
604+ try
605+ {
606+ await validator . CleanupValidation ( validation . DnsRecordName , CancellationToken . None ) ;
607+ _logger . LogInformation ( "Cleaned up DNS record {RecordName} for domain {Domain}" ,
608+ validation . DnsRecordName , authz . Identifier . Value ) ;
609+ }
610+ catch ( Exception ex )
611+ {
612+ _logger . LogWarning ( ex , "Failed to cleanup DNS record {RecordName} for domain {Domain}" ,
613+ validation . DnsRecordName , authz . Identifier . Value ) ;
614+ // Continue cleanup for other domains even if one fails
615+ }
608616 }
609617 }
610618
0 commit comments