diff --git a/PKG-INFO b/PKG-INFO index c208e5d..4d5a45c 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: certbot-dns-rfc2136 -Version: 1.3.0 +Version: 1.10.1 Summary: RFC 2136 DNS Authenticator plugin for Certbot Home-page: https://github.com/certbot/certbot Author: Certbot Project @@ -17,15 +17,15 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Security Classifier: Topic :: System :: Installation/Setup Classifier: Topic :: System :: Networking Classifier: Topic :: System :: Systems Administration Classifier: Topic :: Utilities -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.* Provides-Extra: docs diff --git a/certbot_dns_rfc2136/__init__.py b/certbot_dns_rfc2136/__init__.py index 12b3609..da8ef34 100644 --- a/certbot_dns_rfc2136/__init__.py +++ b/certbot_dns_rfc2136/__init__.py @@ -99,11 +99,10 @@ This configuration limits the scope of the TSIG key to just be able to add and remove TXT records for one specific host for the purpose of completing the ``dns-01`` challenge. If your version of BIND doesn't - support the - `update-policy `_ - directive then you can use the less-secure - `allow-update `_ - directive instead. + support the ``update-policy`` directive, then you can use the less-secure + ``allow-update`` directive instead. `See the BIND documentation + `_ + for details. Examples -------- diff --git a/certbot_dns_rfc2136/_internal/dns_rfc2136.py b/certbot_dns_rfc2136/_internal/dns_rfc2136.py index 3bb4f44..a3a9436 100644 --- a/certbot_dns_rfc2136/_internal/dns_rfc2136.py +++ b/certbot_dns_rfc2136/_internal/dns_rfc2136.py @@ -1,3 +1,13 @@ +# type: ignore +# pylint: disable=no-member +# Many attributes of dnspython are now dynamically defined which causes both +# mypy and pylint to error about accessing attributes they think do not exist. +# This is the case even in up-to-date versions of mypy and pylint which as of +# writing this are 0.790 and 2.6.0 respectively. This problem may be fixed in +# dnspython 2.1.0. See https://github.com/rthalley/dnspython/issues/598. For +# now, let's disable these checks. This is done at the very top of the file +# like this because "type: ignore" must be the first line in the file to be +# respected by mypy. """DNS Authenticator using RFC 2136 Dynamic Updates.""" import logging @@ -18,6 +28,7 @@ logger = logging.getLogger(__name__) +DEFAULT_NETWORK_TIMEOUT = 45 @zope.interface.implementer(interfaces.IAuthenticator) @zope.interface.provider(interfaces.IPluginFactory) @@ -91,13 +102,15 @@ """ Encapsulates all communication with the target DNS server. """ - def __init__(self, server, port, key_name, key_secret, key_algorithm): + def __init__(self, server, port, key_name, key_secret, key_algorithm, + timeout=DEFAULT_NETWORK_TIMEOUT): self.server = server self.port = port self.keyring = dns.tsigkeyring.from_text({ key_name: key_secret }) self.algorithm = key_algorithm + self._default_timeout = timeout def add_txt_record(self, record_name, record_content, record_ttl): """ @@ -122,7 +135,7 @@ update.add(rel, record_ttl, dns.rdatatype.TXT, record_content) try: - response = dns.query.tcp(update, self.server, port=self.port) + response = dns.query.tcp(update, self.server, self._default_timeout, self.port) except Exception as e: raise errors.PluginError('Encountered error adding TXT record: {0}' .format(e)) @@ -157,7 +170,7 @@ update.delete(rel, dns.rdatatype.TXT, record_content) try: - response = dns.query.tcp(update, self.server, port=self.port) + response = dns.query.tcp(update, self.server, self._default_timeout, self.port) except Exception as e: raise errors.PluginError('Encountered error deleting TXT record: {0}' .format(e)) @@ -207,10 +220,10 @@ try: try: - response = dns.query.tcp(request, self.server, port=self.port) - except OSError as e: + response = dns.query.tcp(request, self.server, self._default_timeout, self.port) + except (OSError, dns.exception.Timeout) as e: logger.debug('TCP query failed, fallback to UDP: %s', e) - response = dns.query.udp(request, self.server, port=self.port) + response = dns.query.udp(request, self.server, self._default_timeout, self.port) rcode = response.rcode() # Authoritative Answer bit should be set diff --git a/certbot_dns_rfc2136.egg-info/PKG-INFO b/certbot_dns_rfc2136.egg-info/PKG-INFO index c208e5d..4d5a45c 100644 --- a/certbot_dns_rfc2136.egg-info/PKG-INFO +++ b/certbot_dns_rfc2136.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: certbot-dns-rfc2136 -Version: 1.3.0 +Version: 1.10.1 Summary: RFC 2136 DNS Authenticator plugin for Certbot Home-page: https://github.com/certbot/certbot Author: Certbot Project @@ -17,15 +17,15 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Security Classifier: Topic :: System :: Installation/Setup Classifier: Topic :: System :: Networking Classifier: Topic :: System :: Systems Administration Classifier: Topic :: Utilities -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.* Provides-Extra: docs diff --git a/certbot_dns_rfc2136.egg-info/requires.txt b/certbot_dns_rfc2136.egg-info/requires.txt index 1ffaac3..cddf2e9 100644 --- a/certbot_dns_rfc2136.egg-info/requires.txt +++ b/certbot_dns_rfc2136.egg-info/requires.txt @@ -1,9 +1,11 @@ +dnspython +setuptools +zope.interface acme>=0.29.0 certbot>=1.1.0 -dnspython + +[:python_version < "3.3"] mock -setuptools -zope.interface [docs] Sphinx>=1.0 diff --git a/docs/conf.py b/docs/conf.py index 731b9cb..bc0e9c8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -93,7 +93,7 @@ # a list of builtin themes. # -# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs +# https://docs.readthedocs.io/en/stable/faq.html#i-want-to-use-the-read-the-docs-theme-locally # on_rtd is whether we are on readthedocs.org on_rtd = os.environ.get('READTHEDOCS', None) == 'True' if not on_rtd: # only import and set the theme if we're building docs locally diff --git a/docs/make.bat b/docs/make.bat index 47b6a59..2ec3096 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -22,7 +22,7 @@ echo.Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ + echo.https://www.sphinx-doc.org/ exit /b 1 ) diff --git a/setup.py b/setup.py index 42c6f11..d3b3741 100644 --- a/setup.py +++ b/setup.py @@ -1,40 +1,45 @@ +from distutils.version import LooseVersion +import os import sys +from setuptools import __version__ as setuptools_version from setuptools import find_packages from setuptools import setup -from setuptools.command.test import test as TestCommand -version = '1.3.0' +version = '1.10.1' # Remember to update local-oldest-requirements.txt when changing the minimum # acme/certbot version. install_requires = [ - 'acme>=0.29.0', - 'certbot>=1.1.0', 'dnspython', - 'mock', 'setuptools', 'zope.interface', ] + +if not os.environ.get('SNAP_BUILD'): + install_requires.extend([ + 'acme>=0.29.0', + 'certbot>=1.1.0', + ]) +elif 'bdist_wheel' in sys.argv[1:]: + raise RuntimeError('Unset SNAP_BUILD when building wheels ' + 'to include certbot dependencies.') +if os.environ.get('SNAP_BUILD'): + install_requires.append('packaging') + +setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) +if setuptools_known_environment_markers: + install_requires.append('mock ; python_version < "3.3"') +elif 'bdist_wheel' in sys.argv[1:]: + raise RuntimeError('Error, you are trying to build certbot wheels using an old version ' + 'of setuptools. Version 36.2+ of setuptools is required.') +elif sys.version_info < (3,3): + install_requires.append('mock') docs_extras = [ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags 'sphinx_rtd_theme', ] - -class PyTest(TestCommand): - user_options = [] - - def initialize_options(self): - TestCommand.initialize_options(self) - self.pytest_args = '' - - def run_tests(self): - import shlex - # import here, cause outside the eggs aren't loaded - import pytest - errno = pytest.main(shlex.split(self.pytest_args)) - sys.exit(errno) setup( name='certbot-dns-rfc2136', @@ -44,7 +49,7 @@ author="Certbot Project", author_email='client-dev@letsencrypt.org', license='Apache License 2.0', - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', @@ -55,10 +60,10 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', 'Topic :: Internet :: WWW/HTTP', 'Topic :: Security', 'Topic :: System :: Installation/Setup', @@ -78,7 +83,4 @@ 'dns-rfc2136 = certbot_dns_rfc2136._internal.dns_rfc2136:Authenticator', ], }, - tests_require=["pytest"], - test_suite='certbot_dns_rfc2136', - cmdclass={"test": PyTest}, ) diff --git a/tests/dns_rfc2136_test.py b/tests/dns_rfc2136_test.py index c767dba..dc4a73a 100644 --- a/tests/dns_rfc2136_test.py +++ b/tests/dns_rfc2136_test.py @@ -5,7 +5,10 @@ import dns.flags import dns.rcode import dns.tsig -import mock +try: + import mock +except ImportError: # pragma: no cover + from unittest import mock # type: ignore from certbot import errors from certbot.compat import os @@ -18,7 +21,7 @@ NAME = 'a-tsig-key.' SECRET = 'SSB3b25kZXIgd2hvIHdpbGwgYm90aGVyIHRvIGRlY29kZSB0aGlzIHRleHQK' VALID_CONFIG = {"rfc2136_server": SERVER, "rfc2136_name": NAME, "rfc2136_secret": SECRET} - +TIMEOUT = 45 class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest): @@ -75,7 +78,8 @@ def setUp(self): from certbot_dns_rfc2136._internal.dns_rfc2136 import _RFC2136Client - self.rfc2136_client = _RFC2136Client(SERVER, PORT, NAME, SECRET, dns.tsig.HMAC_MD5) + self.rfc2136_client = _RFC2136Client(SERVER, PORT, NAME, SECRET, dns.tsig.HMAC_MD5, + TIMEOUT) @mock.patch("dns.query.tcp") def test_add_txt_record(self, query_mock): @@ -85,7 +89,7 @@ self.rfc2136_client.add_txt_record("bar", "baz", 42) - query_mock.assert_called_with(mock.ANY, SERVER, port=PORT) + query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) self.assertTrue("bar. 42 IN TXT \"baz\"" in str(query_mock.call_args[0][0])) @mock.patch("dns.query.tcp") @@ -118,7 +122,7 @@ self.rfc2136_client.del_txt_record("bar", "baz") - query_mock.assert_called_with(mock.ANY, SERVER, port=PORT) + query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) self.assertTrue("bar. 0 NONE TXT \"baz\"" in str(query_mock.call_args[0][0])) @mock.patch("dns.query.tcp") @@ -150,7 +154,7 @@ # _find_domain | pylint: disable=protected-access domain = self.rfc2136_client._find_domain('foo.bar.'+DOMAIN) - self.assertTrue(domain == DOMAIN) + self.assertEqual(domain, DOMAIN) def test_find_domain_wraps_errors(self): # _query_soa | pylint: disable=protected-access @@ -170,7 +174,7 @@ # _query_soa | pylint: disable=protected-access result = self.rfc2136_client._query_soa(DOMAIN) - query_mock.assert_called_with(mock.ANY, SERVER, port=PORT) + query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) self.assertTrue(result) @mock.patch("dns.query.tcp") @@ -180,7 +184,7 @@ # _query_soa | pylint: disable=protected-access result = self.rfc2136_client._query_soa(DOMAIN) - query_mock.assert_called_with(mock.ANY, SERVER, port=PORT) + query_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) self.assertFalse(result) @mock.patch("dns.query.tcp") @@ -203,8 +207,8 @@ # _query_soa | pylint: disable=protected-access result = self.rfc2136_client._query_soa(DOMAIN) - tcp_mock.assert_called_with(mock.ANY, SERVER, port=PORT) - udp_mock.assert_called_with(mock.ANY, SERVER, port=PORT) + tcp_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) + udp_mock.assert_called_with(mock.ANY, SERVER, TIMEOUT, PORT) self.assertTrue(result)