Skip to content

fix: remove DNS-01 challenge TXT records after enrollment - #32

Merged
indrora merged 1 commit into
release-1.3from
bugfix/dns-txt-record-cleanup
Oct 27, 2026
Merged

indrora merged 1 commit into
release-1.3from
bugfix/dns-txt-record-cleanup

Conversation

@bhillkeyfactor

Copy link
Copy Markdown
Collaborator

Problem

DNS-01 _acme-challenge TXT records were never removed after certificate issuance, for any DNS provider. ProcessAuthorizations called CreateRecordAsync, but nothing in the plugin ever called DeleteRecordAsync. Reported against Cloudflare, where records accumulate in the zone with every enrollment/renewal.

Changes

  • Track the challenge records created during an enrollment and remove them in a finally after order finalization, so cleanup also runs when the enrollment fails. Cleanup is best effort: failures are logged as warnings and never change the enrollment result. Shared names (wildcard + base domain) are deleted once.
  • Cloudflare: DeleteRecordAsync looked records up by the zone-relative name, but the Cloudflare name filter expects the FQDN, and it only deleted the first match. It now queries by FQDN and deletes all matching TXT records.
  • CHANGELOG entry for v1.3.2.

Testing

  • Solution builds with 0 errors.
  • Cloudflare delete exercised with a throwaway harness using a stubbed HTTP handler (not committed): zone lookup, FQDN query, and both matching records deleted.
  • No automated tests are included: release-1.3 has no test project, and the suite on tests/unit-test-coverage targets the 2.0 code.
  • Not verified against a live Cloudflare zone.

Notes

  • Deletion is by record name only, so a concurrent enrollment for the same hostname could have its record removed. Fixing that needs the TXT value added to IDnsProvider.
  • Other providers' DeleteRecordAsync implementations were never exercised before this change and have not been reviewed.
  • Existing orphaned records are not removed and need manual cleanup.

AB#111453

ProcessAuthorizations created challenge TXT records but nothing ever
called DeleteRecordAsync, leaving orphaned _acme-challenge records in
the DNS zone after every enrollment.

Track created records and remove them in a finally block after order
finalization (best effort, failures are logged and never fail the
enrollment). Also fix Cloudflare deletion, which queried by the
zone-relative name instead of the FQDN and removed only the first match.

AB#111453
@indrora
indrora merged commit a78125e into release-1.3 Oct 27, 2026
45 checks passed
indrora added a commit that referenced this pull request Oct 27, 2026
* Release: 1.3.0

---------

Co-authored-by: Keyfactor <keyfactor@keyfactor.github.io>

* docs: make Let's Encrypt certificate instructions generic (#15)

Removed specific root/intermediate names (ISRG Root X1, R3) that go stale
when Let's Encrypt rotates their chain. Users are now directed to the
official Let's Encrypt certificates page to identify the currently active
root and intermediate certificates.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: remove DNS-01 challenge TXT records after enrollment (#32)

ProcessAuthorizations created challenge TXT records but nothing ever
called DeleteRecordAsync, leaving orphaned _acme-challenge records in
the DNS zone after every enrollment.

Track created records and remove them in a finally block after order
finalization (best effort, failures are logged and never fail the
enrollment). Also fix Cloudflare deletion, which queried by the
zone-relative name instead of the FQDN and removed only the first match.

AB#111453

---------

Co-authored-by: Brian Hill <76450501+bhillkeyfactor@users.noreply.github.com>
Co-authored-by: Keyfactor <keyfactor@keyfactor.github.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants