@@ -30,12 +30,9 @@ public CloudflareDnsProvider(string apiToken)
3030
3131 public async Task < bool > CreateRecordAsync ( string recordName , string txtValue )
3232 {
33- // 1) Determine apex zone
34- var zoneName = ExtractZoneFromRecord ( recordName ) ;
35- var zoneId = await GetZoneIdAsync ( zoneName ) ;
36- if ( zoneId == null ) return false ;
33+ var ( zoneName , zoneId ) = await FindZoneForRecordAsync ( recordName ) ;
34+ if ( zoneId == null || zoneName == null ) return false ;
3735
38- // 2) Get the relative record name for Cloudflare
3936 var relativeName = GetRelativeRecordName ( recordName , zoneName ) ;
4037
4138 var payload = new
@@ -59,12 +56,9 @@ public async Task<bool> CreateRecordAsync(string recordName, string txtValue)
5956
6057 public async Task < bool > DeleteRecordAsync ( string recordName )
6158 {
62- // 1) Determine apex zone
63- var zoneName = ExtractZoneFromRecord ( recordName ) ;
64- var zoneId = await GetZoneIdAsync ( zoneName ) ;
65- if ( zoneId == null ) return false ;
59+ var ( zoneName , zoneId ) = await FindZoneForRecordAsync ( recordName ) ;
60+ if ( zoneId == null || zoneName == null ) return false ;
6661
67- // 2) Get the relative record name for Cloudflare
6862 var relativeName = GetRelativeRecordName ( recordName , zoneName ) ;
6963
7064 var recordsResp = await _httpClient . GetAsync ( $ "zones/{ zoneId } /dns_records?type=TXT&name={ relativeName } ") ;
@@ -73,8 +67,9 @@ public async Task<bool> DeleteRecordAsync(string recordName)
7367 var json = await recordsResp . Content . ReadAsStringAsync ( ) ;
7468 var doc = JsonDocument . Parse ( json ) ;
7569
76- var recordId = doc . RootElement . GetProperty ( "result" ) . EnumerateArray ( )
77- . FirstOrDefault ( ) . GetProperty ( "id" ) . GetString ( ) ;
70+ var resultArray = doc . RootElement . GetProperty ( "result" ) ;
71+ if ( resultArray . GetArrayLength ( ) == 0 ) return false ;
72+ var recordId = resultArray [ 0 ] . GetProperty ( "id" ) . GetString ( ) ;
7873
7974 if ( recordId == null ) return false ;
8075
@@ -92,21 +87,35 @@ public async Task<bool> DeleteRecordAsync(string recordName)
9287
9388 var json = await response . Content . ReadAsStringAsync ( ) ;
9489 var doc = JsonDocument . Parse ( json ) ;
95- return doc . RootElement . GetProperty ( "result" ) . EnumerateArray ( )
96- . FirstOrDefault ( ) . GetProperty ( "id" ) . GetString ( ) ;
90+ var resultArray = doc . RootElement . GetProperty ( "result" ) ;
91+ if ( resultArray . GetArrayLength ( ) == 0 ) return null ;
92+ return resultArray [ 0 ] . GetProperty ( "id" ) . GetString ( ) ;
9793 }
9894
99- private string ExtractZoneFromRecord ( string recordName )
95+ private async Task < ( string ? zoneName , string ? zoneId ) > FindZoneForRecordAsync ( string recordName )
10096 {
10197 if ( string . IsNullOrWhiteSpace ( recordName ) )
102- return string . Empty ;
98+ return ( null , null ) ;
10399
104100 var parts = recordName . TrimEnd ( '.' ) . Split ( '.' ) ;
105- if ( parts . Length < 2 )
106- return recordName ;
107101
108- // Use last two labels as default zone: e.g., "keyfactoracme.com"
109- return string . Join ( "." , parts . Skip ( parts . Length - 2 ) ) ;
102+ // Try progressively shorter domain parts to find the actual zone
103+ // e.g., for "_acme-challenge.www.keyfactor.ssl4saas.com", try:
104+ // - www.keyfactor.ssl4saas.com
105+ // - keyfactor.ssl4saas.com
106+ // - ssl4saas.com
107+ for ( int i = 1 ; i < parts . Length - 1 ; i ++ )
108+ {
109+ var candidateZone = string . Join ( "." , parts . Skip ( i ) ) ;
110+ var zoneId = await GetZoneIdAsync ( candidateZone ) ;
111+ if ( zoneId != null )
112+ {
113+ Console . WriteLine ( $ "Found zone: { candidateZone } (id: { zoneId } )") ;
114+ return ( candidateZone , zoneId ) ;
115+ }
116+ }
117+
118+ return ( null , null ) ;
110119 }
111120
112121 private string GetRelativeRecordName ( string recordName , string zoneName )
0 commit comments