Skip to content

Commit 7e06193

Browse files
authored
Merge pull request #166 from stackitcloud/bug/fix-resolver-acme-challenges
fix: safely handle concurrent DNS-01 challenges in Present and Cleanup
2 parents 7fa8a1b + 38db935 commit 7e06193

File tree

2 files changed

+435
-22
lines changed

2 files changed

+435
-22
lines changed

internal/resolver/resolver.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"net/http"
88
"os"
9+
"slices"
910
"strings"
1011

1112
"github.com/cert-manager/cert-manager/pkg/acme/webhook"
@@ -82,7 +83,7 @@ func (s *stackitDnsProviderResolver) Present(ch *v1alpha1.ChallengeRequest) erro
8283
return err
8384
}
8485

85-
return s.updateExistingRRSet(initResolverRes, rrSet)
86+
return s.updateExistingRRSet(initResolverRes, rrSet, ch.Key)
8687
}
8788

8889
// CleanUp should delete the relevant TXT record from the DNS provider console.
@@ -97,7 +98,7 @@ func (s *stackitDnsProviderResolver) CleanUp(ch *v1alpha1.ChallengeRequest) erro
9798
return s.handleErrorDuringInitialization(err)
9899
}
99100

100-
return s.handleRRSetCleanup(initResolverRes)
101+
return s.handleRRSetCleanup(initResolverRes, ch.Key)
101102
}
102103

103104
// Initialize will be called when the webhook first starts.
@@ -287,6 +288,7 @@ func (s *stackitDnsProviderResolver) handleErrorDuringInitialization(
287288

288289
func (s *stackitDnsProviderResolver) handleRRSetCleanup(
289290
initResolverRes *initResolverContextResult,
291+
challengeKey string,
290292
) error {
291293
s.logger.Info("Cleaning up RRSet", zap.String("rrSetName", initResolverRes.rrSetName))
292294

@@ -299,7 +301,27 @@ func (s *stackitDnsProviderResolver) handleRRSetCleanup(
299301
return s.handleFetchRRSetError(err, initResolverRes.rrSetName)
300302
}
301303

302-
return s.deleteRRSet(initResolverRes.rrSetRepository, rrSet, initResolverRes.rrSetName)
304+
if rrSet == nil || rrSet.Records == nil || len(*rrSet.Records) == 0 {
305+
return s.deleteRRSet(initResolverRes.rrSetRepository, rrSet, initResolverRes.rrSetName)
306+
}
307+
308+
originalLen := len(*rrSet.Records)
309+
310+
*rrSet.Records = slices.DeleteFunc(*rrSet.Records, func(r stackitdnsclient.Record) bool {
311+
return r.Content != nil && *r.Content == challengeKey
312+
})
313+
314+
if len(*rrSet.Records) == originalLen {
315+
s.logger.Info("Challenge key not found in RRSet records, nothing to clean up", zap.String("rrSetName", initResolverRes.rrSetName))
316+
317+
return nil
318+
}
319+
320+
if len(*rrSet.Records) == 0 {
321+
return s.deleteRRSet(initResolverRes.rrSetRepository, rrSet, initResolverRes.rrSetName)
322+
}
323+
324+
return initResolverRes.rrSetRepository.UpdateRRSet(s.ctx, *rrSet)
303325
}
304326

305327
func (s *stackitDnsProviderResolver) handleFetchRRSetError(err error, rrSetName string) error {
@@ -384,12 +406,31 @@ func (s *stackitDnsProviderResolver) handleRRSetNotFound(
384406
return nil
385407
}
386408

409+
func keyExists(records *[]stackitdnsclient.Record, challengeKey string) bool {
410+
for _, record := range *records {
411+
if record.Content != nil && *record.Content == challengeKey {
412+
return true
413+
}
414+
}
415+
416+
return false
417+
}
418+
387419
func (s *stackitDnsProviderResolver) updateExistingRRSet(
388420
initResolverRes *initResolverContextResult,
389421
rrSet *stackitdnsclient.RecordSet,
422+
challengeKey string,
390423
) error {
391424
s.logger.Info("RRSet found, updating RRSet", zap.String("rrSetName", initResolverRes.rrSetName))
392425

426+
if !keyExists(rrSet.Records, challengeKey) {
427+
s.logger.Info("Challenge key not found in existing RRSet, adding new record", zap.String("rrSetName", initResolverRes.rrSetName))
428+
newRecord := stackitdnsclient.Record{
429+
Content: &challengeKey,
430+
}
431+
*rrSet.Records = append(*rrSet.Records, newRecord)
432+
}
433+
393434
rrSet.Ttl = &initResolverRes.acmeTxtDefaultTTL
394435

395436
if err := initResolverRes.rrSetRepository.UpdateRRSet(s.ctx, *rrSet); err != nil {

0 commit comments

Comments
 (0)