Skip to content

Certbot v2.x Plugin Compatibility

alexzorin edited this page Nov 30, 2022 · 1 revision

This page is intended for authors of third-party Certbot plugins. For many plugins, this page is purely informational and will not require any action (Method 1 at the bottom of the page). Other plugins may need to make changes to remain compatible with all Certbot versions (Method 2 at the bottom of the page).

Certbot v1.18.0 introduced a new way for third-party plugins to register themselves to Certbot. Notably, the certbot.interfaces abc-based classes Plugin, Authenticator and Installer. These are the recommended way to write and register Certbot plugins.

With the release of Certbot v1.19.0, the old zope-based classes (notably IPluginFactory, IPlugin, IAuthenticator, IInstaller) for registering plugins were deprecated and subsequently removed in v2.0.0.

Certbot v2.1.0: Fixing compatibility with existing DNS plugins

With the release of Certbot v2.0.0, some users may have noticed that their Certbot would crash with an error:

$ certbot plugins
An unexpected error occurred:
AttributeError: module 'certbot.interfaces' has no attribute 'IAuthenticator'

This is due to having a plugin installed that still referenced the old zope-based classes.

We are re-adding empty versions these classes in Certbot v2.1.0 in order to fix compatibility with these third-party plugins. Any plugin which inherits from certbot.plugins.dns_common.DNSAuthenticator, depends on zope.interface and registers to the deprecated zope-based classes, should work again as of Certbot v2.1.0. (example of such a plugin).

These plugins should not require any changes once Certbot v2.1.0 is released.

Supporting new and old versions of Certbot in a plugin

Third-party plugins that wish to support both new (>= v2.0.0) and old (< v1.18.0) versions of Certbot need to register themselves to both the abc and zope-based plugin interfaces.

Since the abc-based classes do not exist prior to Certbot v1.18.0, there are a number of options to do this in a way that is compatible across all Certbot versions:

import zope.interface

from certbot import interfaces
from certbot.plugins import common
from certbot.plugins import dns_common

# Each method of registering a plugin here will work in every Certbot version,
# except for v2.0.0, but will work in v2.1.0 and later.
#
# All methods require "zope.interface" to be installed, declare this as a dependency
# of your plugin.


# Method 1, recommended for DNS authenticator plugins.
# abc-based registration for Certbot >= v1.18.0 by inheriting from .dns_common.DNSAuthenticator.
# zope-based registration for Certbot < v1.18.0.
#
# NO ACTION REQUIRED: Most DNS plugins are already written this way and will work as of v2.1.0.
@zope.interface.implementer(interfaces.IAuthenticator)
@zope.interface.provider(interfaces.IPluginFactory)
class DNSAuthenticator(dns_common.DNSAuthenticator):
    ...


# Method 2.
# Using custom decorators to perform both abc- and zope-based registration.
#
# ACTION REQUIRED: any plugin which does not inherit from `.dns_common.DNSAuthenticator` will need to
# make changes as shown here.
def register_authenticator(cls):
    try:
        interfaces.Authenticator.register(cls)  # or interfaces.Installer for installers
    except AttributeError:
        pass
    zope.interface.implementer(interfaces.IAuthenticator)(cls)  # or interfaces.IInstaller for installers 
    zope.interface.provider(interfaces.IPluginFactory)(cls)
    return cls 


# ... with or without inheriting from .common.Plugin
@register_authenticator
class Authenticator:
    ...