From 6b653eda09e7516fa4033c120f3b660d7ea6b7b6 Mon Sep 17 00:00:00 2001 From: Chaptergy Date: Wed, 27 Nov 2024 19:30:26 +0100 Subject: [PATCH] Updates to Certbot 3.0 --- README.md | 2 +- certbot_dns_njalla/dns_njalla.py | 62 +++---------------- certbot_dns_njalla/dns_njalla_test.py | 29 ++------- ...yml.sh => generate_dnsplugins_snapcraft.sh | 28 +++++---- setup.py | 9 ++- snap/snapcraft.yaml | 17 +++-- 6 files changed, 48 insertions(+), 99 deletions(-) rename generate-snapcraft-yml.sh => generate_dnsplugins_snapcraft.sh (67%) mode change 100644 => 100755 diff --git a/README.md b/README.md index 3e8ccf5..abe0cfb 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Do the basic setup described in the [certbot snap readme](https://github.com/cer Run the following command in the repository root (so you are in the folder containing the `setup.py`): ```sh -sh generate-snap.sh +sh generate_dnsplugins_snapcraft.sh snapcraft clean --use-lxd snapcraft --debug --use-lxd ``` diff --git a/certbot_dns_njalla/dns_njalla.py b/certbot_dns_njalla/dns_njalla.py index 1128434..e86daf1 100644 --- a/certbot_dns_njalla/dns_njalla.py +++ b/certbot_dns_njalla/dns_njalla.py @@ -1,15 +1,12 @@ """DNS Authenticator for Njalla.""" import logging -from certbot.plugins import dns_common from certbot.plugins import dns_common_lexicon -from lexicon.providers import njalla - logger = logging.getLogger(__name__) -class Authenticator(dns_common.DNSAuthenticator): +class Authenticator(dns_common_lexicon.LexiconDNSAuthenticator): """DNS Authenticator for Njalla This Authenticator uses the Njalla REST API to fulfill a dns-01 challenge. @@ -20,7 +17,9 @@ class Authenticator(dns_common.DNSAuthenticator): def __init__(self, *args, **kwargs): super(Authenticator, self).__init__(*args, **kwargs) - self.credentials = None + self._add_provider_option('token', + f'Token for the Njalla API', + 'auth_token') @classmethod def add_parser_arguments(cls, add): @@ -35,54 +34,9 @@ def more_info(self): # pylint: disable=missing-docstring,no-self-use + "the Njalla REST API." ) - def _setup_credentials(self): - self._configure_file('credentials', - 'Absolute path to Njalla credentials INI file') - dns_common.validate_file_permissions(self.conf('credentials')) - self.credentials = self._configure_credentials( - "credentials", - "Njalla credentials INI file", - { - "token": "Token for the Njalla API.", - }, - ) - - def _remove_subdomains(self, domain): - split_domain = domain.split('.') - return f'{split_domain[-2]}.{split_domain[-1]}' - - def _perform(self, domain, validation_name, validation): - self._get_njalla_client().add_txt_record( - self._remove_subdomains(domain), validation_name, validation - ) - - def _cleanup(self, domain, validation_name, validation): - self._get_njalla_client().del_txt_record( - self._remove_subdomains(domain), validation_name, validation - ) - - def _get_njalla_client(self): - return _NjallaLexiconClient( - self.credentials.conf("token"), - self.ttl - ) - - -class _NjallaLexiconClient(dns_common_lexicon.LexiconClient): - """ - Encapsulates all communication with the Njalla API via Lexicon. - """ - - def __init__(self, api_token, ttl): - super(_NjallaLexiconClient, self).__init__() - - config = dns_common_lexicon.build_lexicon_config('njalla', { - 'ttl': ttl, - }, { - 'auth_token': api_token, - }) - - self.provider = njalla.Provider(config) + @property + def _provider_name(self) -> str: + return 'njalla' def _handle_http_error(self, e, domain_name): if domain_name in str(e) and ( @@ -92,4 +46,4 @@ def _handle_http_error(self, e, domain_name): str(e).startswith('404 Client Error: Not Found for url:') ): return # Expected errors when zone name guess is wrong - return super(_NjallaLexiconClient, self)._handle_http_error(e, domain_name) + return super()._handle_http_error(e, domain_name) diff --git a/certbot_dns_njalla/dns_njalla_test.py b/certbot_dns_njalla/dns_njalla_test.py index 75e6e05..7314986 100644 --- a/certbot_dns_njalla/dns_njalla_test.py +++ b/certbot_dns_njalla/dns_njalla_test.py @@ -16,10 +16,13 @@ class AuthenticatorTest(test_util.TempDirTestCase, - dns_test_common_lexicon.BaseLexiconAuthenticatorTest): + dns_test_common_lexicon.BaseLexiconDNSAuthenticatorTest): + + DOMAIN_NOT_FOUND = HTTPError('422 Client Error: Unprocessable Entity for url: {0}.'.format(DOMAIN)) + LOGIN_ERROR = HTTPError('401 Client Error: Unauthorized') def setUp(self): - super(AuthenticatorTest, self).setUp() + super().setUp() from certbot_dns_njalla.dns_njalla import Authenticator @@ -38,27 +41,5 @@ def setUp(self): self.auth = Authenticator(self.config, "njalla") - self.mock_client = mock.MagicMock() - # _get_njalla_client | pylint: disable=protected-access - self.auth._get_njalla_client = mock.MagicMock( - return_value=self.mock_client) - - -class NjallaLexiconClientTest(unittest.TestCase, - dns_test_common_lexicon.BaseLexiconClientTest): - DOMAIN_NOT_FOUND = HTTPError( - '422 Client Error: Unprocessable Entity for url: {0}.'.format(DOMAIN)) - LOGIN_ERROR = HTTPError('401 Client Error: Unauthorized') - - def setUp(self): - from certbot_dns_njalla.dns_njalla import _NjallaLexiconClient - - self.client = _NjallaLexiconClient( - api_token=API_TOKEN, ttl=0) - - self.provider_mock = mock.MagicMock() - self.client.provider = self.provider_mock - - if __name__ == "__main__": unittest.main() # pragma: no cover diff --git a/generate-snapcraft-yml.sh b/generate_dnsplugins_snapcraft.sh old mode 100644 new mode 100755 similarity index 67% rename from generate-snapcraft-yml.sh rename to generate_dnsplugins_snapcraft.sh index aa9b2b6..3a989af --- a/generate-snapcraft-yml.sh +++ b/generate_dnsplugins_snapcraft.sh @@ -1,22 +1,23 @@ #!/bin/bash +# Taken from https://github.com/certbot/certbot/blob/main/tools/snap/generate_dnsplugins_snapcraft.sh # Generate the snapcraft.yaml file for a DNS plugins # Usage: bash generate_dnsplugins_snapcraft.sh path/to/dns/plugin # For example, from the certbot home directory: # tools/snap/generate_dnsplugins_snapcraft.sh certbot-dns-dnsimple set -e -PLUGIN_PATH=./ +PLUGIN_PATH=$1 PLUGIN=$(grep "[^_a-zA-Z]name" "${PLUGIN_PATH}/setup.py" | sed -E 's|\s+name="(.*)",|\1|g') -SUMMARY=$(grep "[^_a-zA-Z]description" "${PLUGIN_PATH}/setup.py" | sed -E 's|\s+description="(.*)",|\1|g') +DESCRIPTION=$(sed -E -n "/[[:space:]]+description=/ s/[[:space:]]+description=['\"](.*)['\"],/\1/ p" "${PLUGIN_PATH}/setup.py") mkdir -p "${PLUGIN_PATH}/snap" cat < "${PLUGIN_PATH}/snap/snapcraft.yaml" # This file is generated automatically and should not be edited manually. name: ${PLUGIN} -summary: ${SUMMARY} -description: ${SUMMARY} +summary: ${DESCRIPTION} +description: ${DESCRIPTION} confinement: strict grade: stable -base: core20 +base: core24 adopt-info: ${PLUGIN} parts: @@ -24,15 +25,19 @@ parts: plugin: python source: . override-pull: | - snapcraftctl pull - snapcraftctl set-version \`grep ^version \$SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]" | tr -d '"'\` + craftctl default + craftctl set version=\$(grep ^version \$SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]") build-environment: + # We set this environment variable while building to try and increase the + # stability of fetching the rust crates needed to build the cryptography + # library. + - CARGO_NET_GIT_FETCH_WITH_CLI: "true" # Constraints are passed through the environment variable PIP_CONSTRAINTS instead of using the # parts.[part_name].constraints option available in snapcraft.yaml when the Python plugin is # used. This is done to let these constraints be applied not only on the certbot package # build, but also on any isolated build that pip could trigger when building wheels for # dependencies. See https://github.com/certbot/certbot/pull/8443 for more info. - # - PIP_CONSTRAINT: \$SNAPCRAFT_PART_SRC/snap-constraints.txt + - PIP_CONSTRAINT: \$SNAPCRAFT_PART_SRC/snap-constraints.txt - SNAP_BUILD: "True" # To build cryptography and cffi if needed build-packages: @@ -43,12 +48,13 @@ parts: - libffi-dev - python3-dev - cargo + - pkg-config certbot-metadata: plugin: dump source: . stage: [setup.py, certbot-shared] override-pull: | - snapcraftctl pull + craftctl default mkdir -p \$SNAPCRAFT_PART_SRC/certbot-shared slots: @@ -56,11 +62,11 @@ slots: interface: content content: certbot-1 read: - - \$SNAP/lib/python3.8/site-packages + - \$SNAP/lib/python3.12/site-packages plugs: certbot-metadata: interface: content content: metadata-1 target: \$SNAP/certbot-shared -EOF +EOF \ No newline at end of file diff --git a/setup.py b/setup.py index 1bb34c3..ed75f4d 100644 --- a/setup.py +++ b/setup.py @@ -2,11 +2,11 @@ from setuptools import setup from setuptools import find_packages -version = "1.0.2" +version = "2.0.0" install_requires = [ - 'certbot>=0.31.0', - 'dns-lexicon>=3.4.1', + 'certbot>=3.0.0', + 'dns-lexicon>=3.14.1', ] test_requirements = [ 'mock', @@ -51,6 +51,9 @@ packages=find_packages(), install_requires=install_requires, tests_require=test_requirements, + extras_require={ + 'test': test_requirements, + }, entry_points={ "certbot.plugins": [ "dns-njalla = certbot_dns_njalla.dns_njalla:Authenticator" diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 0610c2a..c81ecb4 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -4,7 +4,7 @@ summary: Njalla DNS Authenticator plugin for Certbot description: Njalla DNS Authenticator plugin for Certbot confinement: strict grade: stable -base: core20 +base: core24 adopt-info: certbot-dns-njalla parts: @@ -12,15 +12,19 @@ parts: plugin: python source: . override-pull: | - snapcraftctl pull - snapcraftctl set-version `grep ^version $SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]" | tr -d '"'` + craftctl default + craftctl set version=$(grep ^version $SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]") build-environment: + # We set this environment variable while building to try and increase the + # stability of fetching the rust crates needed to build the cryptography + # library. + - CARGO_NET_GIT_FETCH_WITH_CLI: "true" # Constraints are passed through the environment variable PIP_CONSTRAINTS instead of using the # parts.[part_name].constraints option available in snapcraft.yaml when the Python plugin is # used. This is done to let these constraints be applied not only on the certbot package # build, but also on any isolated build that pip could trigger when building wheels for # dependencies. See https://github.com/certbot/certbot/pull/8443 for more info. - # - PIP_CONSTRAINT: $SNAPCRAFT_PART_SRC/snap-constraints.txt + - PIP_CONSTRAINT: $SNAPCRAFT_PART_SRC/snap-constraints.txt - SNAP_BUILD: "True" # To build cryptography and cffi if needed build-packages: @@ -31,12 +35,13 @@ parts: - libffi-dev - python3-dev - cargo + - pkg-config certbot-metadata: plugin: dump source: . stage: [setup.py, certbot-shared] override-pull: | - snapcraftctl pull + craftctl default mkdir -p $SNAPCRAFT_PART_SRC/certbot-shared slots: @@ -44,7 +49,7 @@ slots: interface: content content: certbot-1 read: - - $SNAP/lib/python3.8/site-packages + - $SNAP/lib/python3.12/site-packages plugs: certbot-metadata: