Allow _acme-challenge as a zone (#5707)

* Allow _acme-challenge as a zone

Like described here:
https://github.com/lukas2511/dehydrated/wiki/example-dns-01-nsupdate-script

Not using this patch may be an issue if the parent zone has been (where a wildcard certificate has been requested.) signed by DNSSEC.

Please consider this also for inclusion before dns-01 will be allowed for wildcards.

* Update dns_rfc2136.py

forgot one domain_name reference

* Update dns_rfc2136.py

moved domain up & added assignment.

* Update dns_rfc2136_test.py

tests adjusted to new calls.

* Update dns_rfc2136_test.py

Forgot on DOMAIN...

* Update dns_rfc2136_test.py

* Update dns_rfc2136.py

pydoc updates.

* Update dns_rfc2136.py
This commit is contained in:
noci2012 2018-03-20 21:29:24 +01:00 committed by Brad Warren
parent 41ce108881
commit c0dc31fd88
2 changed files with 20 additions and 22 deletions

View file

@ -70,11 +70,11 @@ class Authenticator(dns_common.DNSAuthenticator):
self._validate_algorithm
)
def _perform(self, domain, validation_name, validation):
self._get_rfc2136_client().add_txt_record(domain, validation_name, validation, self.ttl)
def _perform(self, _domain, validation_name, validation):
self._get_rfc2136_client().add_txt_record(validation_name, validation, self.ttl)
def _cleanup(self, domain, validation_name, validation):
self._get_rfc2136_client().del_txt_record(domain, validation_name, validation)
def _cleanup(self, _domain, validation_name, validation):
self._get_rfc2136_client().del_txt_record(validation_name, validation)
def _get_rfc2136_client(self):
return _RFC2136Client(self.credentials.conf('server'),
@ -95,18 +95,17 @@ class _RFC2136Client(object):
})
self.algorithm = key_algorithm
def add_txt_record(self, domain_name, record_name, record_content, record_ttl):
def add_txt_record(self, record_name, record_content, record_ttl):
"""
Add a TXT record using the supplied information.
:param str domain: The domain to use to find the closest SOA.
:param str record_name: The record name (typically beginning with '_acme-challenge.').
:param str record_content: The record content (typically the challenge validation).
:param int record_ttl: The record TTL (number of seconds that the record may be cached).
:raises certbot.errors.PluginError: if an error occurs communicating with the DNS server
"""
domain = self._find_domain(domain_name)
domain = self._find_domain(record_name)
n = dns.name.from_text(record_name)
o = dns.name.from_text(domain)
@ -131,18 +130,17 @@ class _RFC2136Client(object):
raise errors.PluginError('Received response from server: {0}'
.format(dns.rcode.to_text(rcode)))
def del_txt_record(self, domain_name, record_name, record_content):
def del_txt_record(self, record_name, record_content):
"""
Delete a TXT record using the supplied information.
:param str domain: The domain to use to find the closest SOA.
:param str record_name: The record name (typically beginning with '_acme-challenge.').
:param str record_content: The record content (typically the challenge validation).
:param int record_ttl: The record TTL (number of seconds that the record may be cached).
:raises certbot.errors.PluginError: if an error occurs communicating with the DNS server
"""
domain = self._find_domain(domain_name)
domain = self._find_domain(record_name)
n = dns.name.from_text(record_name)
o = dns.name.from_text(domain)
@ -167,17 +165,17 @@ class _RFC2136Client(object):
raise errors.PluginError('Received response from server: {0}'
.format(dns.rcode.to_text(rcode)))
def _find_domain(self, domain_name):
def _find_domain(self, record_name):
"""
Find the closest domain with an SOA record for a given domain name.
:param str domain_name: The domain name for which to find the closest SOA record.
:param str record_name: The record name for which to find the closest SOA record.
:returns: The domain, if found.
:rtype: str
:raises certbot.errors.PluginError: if no SOA record can be found.
"""
domain_name_guesses = dns_common.base_domain_name_guesses(domain_name)
domain_name_guesses = dns_common.base_domain_name_guesses(record_name)
# Loop through until we find an authoritative SOA record
for guess in domain_name_guesses:
@ -185,7 +183,7 @@ class _RFC2136Client(object):
return guess
raise errors.PluginError('Unable to determine base domain for {0} using names: {1}.'
.format(domain_name, domain_name_guesses))
.format(record_name, domain_name_guesses))
def _query_soa(self, domain_name):
"""

View file

@ -41,7 +41,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
def test_perform(self):
self.auth.perform([self.achall])
expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)]
expected = [mock.call.add_txt_record('_acme-challenge.'+DOMAIN, mock.ANY, mock.ANY)]
self.assertEqual(expected, self.mock_client.mock_calls)
def test_cleanup(self):
@ -49,7 +49,7 @@ class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthentic
self.auth._attempt_cleanup = True
self.auth.cleanup([self.achall])
expected = [mock.call.del_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY)]
expected = [mock.call.del_txt_record('_acme-challenge.'+DOMAIN, mock.ANY)]
self.assertEqual(expected, self.mock_client.mock_calls)
def test_invalid_algorithm_raises(self):
@ -82,7 +82,7 @@ class RFC2136ClientTest(unittest.TestCase):
# _find_domain | pylint: disable=protected-access
self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com")
self.rfc2136_client.add_txt_record(DOMAIN, "bar", "baz", 42)
self.rfc2136_client.add_txt_record("bar", "baz", 42)
query_mock.assert_called_with(mock.ANY, SERVER)
self.assertTrue("bar. 42 IN TXT \"baz\"" in str(query_mock.call_args[0][0]))
@ -96,7 +96,7 @@ class RFC2136ClientTest(unittest.TestCase):
self.assertRaises(
errors.PluginError,
self.rfc2136_client.add_txt_record,
DOMAIN, "bar", "baz", 42)
"bar", "baz", 42)
@mock.patch("dns.query.tcp")
def test_add_txt_record_server_error(self, query_mock):
@ -107,7 +107,7 @@ class RFC2136ClientTest(unittest.TestCase):
self.assertRaises(
errors.PluginError,
self.rfc2136_client.add_txt_record,
DOMAIN, "bar", "baz", 42)
"bar", "baz", 42)
@mock.patch("dns.query.tcp")
def test_del_txt_record(self, query_mock):
@ -115,7 +115,7 @@ class RFC2136ClientTest(unittest.TestCase):
# _find_domain | pylint: disable=protected-access
self.rfc2136_client._find_domain = mock.MagicMock(return_value="example.com")
self.rfc2136_client.del_txt_record(DOMAIN, "bar", "baz")
self.rfc2136_client.del_txt_record("bar", "baz")
query_mock.assert_called_with(mock.ANY, SERVER)
self.assertTrue("bar. 0 NONE TXT \"baz\"" in str(query_mock.call_args[0][0]))
@ -129,7 +129,7 @@ class RFC2136ClientTest(unittest.TestCase):
self.assertRaises(
errors.PluginError,
self.rfc2136_client.del_txt_record,
DOMAIN, "bar", "baz")
"bar", "baz")
@mock.patch("dns.query.tcp")
def test_del_txt_record_server_error(self, query_mock):
@ -140,7 +140,7 @@ class RFC2136ClientTest(unittest.TestCase):
self.assertRaises(
errors.PluginError,
self.rfc2136_client.del_txt_record,
DOMAIN, "bar", "baz")
"bar", "baz")
def test_find_domain(self):
# _query_soa | pylint: disable=protected-access