Repository: certbot/certbot

Issue:
Third-party plugin breakages in Certbot 2.x
https://github.com/certbot/certbot/pull/9161 removed the old `IAuthenticator`, `IInstaller` etc classes from `certbot.interface`. We had a 14-month deprecation period for these classes and eventually removed them in the release of v2.0.0.

A number of third-party plugins no longer work on Certbot v2.0.0, due to them referencing the removed classes. We have received reports about this on the community forums, this issue tracker, and other project issue trackers.

```python
@zope.interface.implementer(interfaces.IAuthenticator)
@zope.interface.provider(interfaces.IPluginFactory)
class Authenticator(dns_common.DNSAuthenticator):
```

Fixing this in Certbot v1.18.0 and later is simple: removing the `zope` decorators. In the case of `dns_common.DNSAuthenticator`, the plugin is still registered as an authenticator due to the way the new `abc`-based classes work.

However, prior to Certbot v1.18.0, this results in the plugin no longer being registered:

    # certbot certonly -d example.com --dry-run --preferred-challenges dns -a certbot-dns-inwx:dns-inwx
    PluginEntryPoint#certbot-dns-inwx:dns-inwx does not provide IPluginFactory, skipping
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Could not choose appropriate plugin: The requested certbot-dns-inwx:dns-inwx plugin does not appear to be installed
    The requested certbot-dns-inwx:dns-inwx plugin does not appear to be installed

Plugin authors are stuck on their ability to support both old Certbot and new Certbot. Some integration projects have pinned Certbot back to v1.32.0 or told users to install Certbot v1.32.0 instead of v2.x, in order to deal with this problem. 

I think we should try to solve this issue for all the `dns_common.DNSAuthenticator`-based `certbot-dns-*` projects that appear to have real users (around 12,000+ based on UA statistics from April), if it is straightforward to do so. 

My proposal is to reintroduce some of the removed `zope` classes, without reintroducing zope itself. That approach can be seen [here](https://github.com/certbot/certbot/compare/master...alexzorin:zope-shim). The effect is that it will perform the required `zope`-based class registration in Certbot < v1.18.0, and be a no-operation in newer versions.

One downside is that we cannot entirely fix the problem. I'm not sure whether we can do anything about plugins that inherit from `certbot.plugins.common.Plugin` and then do `zope`-based registration to `IAuthenticator` or `IInstaller`,  without us backtracking on the `zope` removal. Based on the stats, I think total breakage in that case is less than 700 users. This number excludes a bunch from the Nextcloud project who I think are not affected due to pinning Certbot in their snap (at least, I can't see any complaints about it).




Discussion:

Resolving patch:
diff --git a/certbot/certbot/interfaces.py b/certbot/certbot/interfaces.py
--- a/certbot/certbot/interfaces.py
+++ b/certbot/certbot/interfaces.py
@@ -16,6 +16,11 @@
 from certbot import configuration
 from certbot.achallenges import AnnotatedChallenge
 
+try:
+    from zope.interface import Interface as ZopeInterface
+except ImportError:
+    ZopeInterface = object
+
 if TYPE_CHECKING:
     from certbot._internal.account import Account
 
@@ -465,3 +470,16 @@ def renew_deploy(self, lineage: RenewableCert, *args: Any, **kwargs: Any) -> Non
         :type lineage: RenewableCert
 
         """
+
+
+class IPluginFactory(ZopeInterface):
+    """Compatibility shim for plugins that still use Certbot's old zope.interface classes."""
+
+class IPlugin(ZopeInterface):
+    """Compatibility shim for plugins that still use Certbot's old zope.interface classes."""
+
+class IAuthenticator(IPlugin):
+    """Compatibility shim for plugins that still use Certbot's old zope.interface classes."""
+
+class IInstaller(IPlugin):
+    """Compatibility shim for plugins that still use Certbot's old zope.interface classes."""


Test patch: