github fabriziosalmi/certmate v2.45.2
v2.45.2 (Azure DNS issues and renews again)

3 hours ago

v2.45.2 (Azure DNS issues and renews again)

A patch release for two defects found after 2.45.1, and one dependency refresh. If you use Azure DNS, read the first section: from v2.26.1 to v2.45.1 it could neither issue nor renew. The API contract stays at 2.34.


Read this before upgrading

If you use Azure DNS

Every release from v2.26.1 to v2.45.1 failed the first Azure DNS-01 challenge, for creation and for renewal, with:

TypeError: DnsManagementClient.__init__() takes from 3 to 4 positional arguments but 5 were given

(The count includes self: the call passes four arguments, and the SDK now accepts three.) A certificate you issued before v2.26.1 kept working until it came due, and then its renewal failed. After upgrading, nothing needs changing in Settings; the next renewal pass picks the certificate up, and renewing it by hand does it at once. Check the ones that are close to expiry first.

If your Azure certificates did renew in that period, tell us: this was measured with real certbot on the pinned stack, not against a live Azure zone, and a report from one would be the missing evidence.


Fixed

  • Azure DNS-01 raised TypeError at the first challenge. azure-mgmt-dns 9.0.0 (a Dependabot bump merged on 2026-08-21, shipped in v2.26.1) dropped the api_version parameter: its client takes credential, subscription_id and base_url as positional arguments, where 8.1.0 also took api_version in third place. certbot-dns-azure 2.5.0 still passes four positional arguments, the third being api_version. The plugin declares only azure-mgmt-dns>=8.0.0, so pip did not refuse it, and the check that justified the bump (the plugin imports, and the three operations it calls exist on 9.0.0) was true and did not touch the line that broke: the constructor. azure-mgmt-dns is back on 8.1.0 in requirements.txt, requirements-azure.txt and the lock, and Dependabot is told to leave it alone.
    • A test now runs the plugin's own _get_azure_client, _perform and _cleanup against the installed SDK with the HTTP layer recorded: the request that would go to Azure is the one asserted on (the PUT body and Authorization header, the DELETE, a second value on the same name). Nothing ran the plugin against its SDK before.
  • Deploy Now, and then the window ran the same deploy again. A hook or target held for its maintenance window is queued; Deploy Now runs it at once, by design, and used to leave the queued entry in place, so the deploy ran a second time when the window opened (#1058). A successful Deploy Now now takes the entry off the queue; a failed one leaves it, so the window deploy is the retry; and an entry queued again while Deploy Now was running stays, because that certificate is newer than the one the run read.
    • The two paths no longer run the same deploy at the same time: if the window opens while Deploy Now is running a hook, the scheduled run skips it and finds it delivered (or still owed) on the next pass, and if the scheduled run is already inside the hook when you press the button, Deploy Now waits for it and then runs.
    • The window drain had a second way back to the same defect: it ended by putting back, from the copy it read at the start, the entries it had left for a closed window, which resurrected one Deploy Now had delivered in between. It now writes back only what the queue holds.

Dependencies

  • boto3 1.43.98 -> 1.43.103, with the lock regenerated (the image installs from requirements.lock, so a bump that leaves the lock alone does not ship). Four unpinned transitive packages moved with it because the lock was resolved again: botocore 1.43.105 -> 1.43.106, filelock 4.0.7 -> 4.0.8, google-api-python-client 2.200.0 -> 2.201.0, google-auth 2.59.0 -> 2.59.1.
  • flake8 7.3.0 -> 7.4.1, in the places that name it: CI, CONTRIBUTING.md and requirements-test.txt. Over the whole repository with the CI's selection it reports nothing, so what the gate sees is unchanged.

Not touched: cryptography, pyopenssl, acme, certbot and josepy, the held set (see SECURITY.md, "Known dependency constraint").


How it was checked

  • Azure, reproduced and fixed with real certbot. The product's own Azure strategy builds the argument list and certbot 2.10.0 runs it against Let's Encrypt staging with a fake service principal. On the pinned stack it ends in the TypeError above; with azure-mgmt-dns 8.1.0 the same run goes on to the Azure authentication call. That is as far as a fake credential goes: no live Azure zone was used.
  • Azure tests. Four tests, red on 9.0.0 (all four, with the TypeError) and green on 8.1.0 in the same container, with only the SDK version changed. Removing the Dependabot ignore, or the reason written next to the pin, fails the test that guards the hold.
  • Deploy Now tests. Fifteen in a new file: the issue step by step; a failed run, a disabled hook and another domain's entry left alone; a renewal landing during the run; the two paths racing with real threads (200 rounds, with an invariant that must hold under any interleaving, recorded at the write that commits a renewal); and the claims, driven with a held run on each side. Five mechanisms were broken on purpose (claim always granted, no waiting, the old write-back, no release, the drop by key) and each turned at least one test red.
  • Lock and flake8. The lock check and the dependency-consistency tests pass; both architectures resolve the lock identically.

Don't miss a new certmate release

NewReleases is sending notifications on new releases.