dns-digitalocean: use a 30 second TTL (#8693)

Fixes an issue with long TTLs and caching behavior on DigitalOcean's
DNS hosting service.
This commit is contained in:
alexzorin
2021-03-09 15:56:51 -08:00
committed by GitHub
parent c02b2d30f2
commit 76895457c9
5 changed files with 22 additions and 12 deletions
@@ -21,6 +21,7 @@ class Authenticator(dns_common.DNSAuthenticator):
description = 'Obtain certificates using a DNS TXT record (if you are ' + \
'using DigitalOcean for DNS).'
ttl = 30
def __init__(self, *args, **kwargs):
super(Authenticator, self).__init__(*args, **kwargs)
@@ -45,7 +46,8 @@ class Authenticator(dns_common.DNSAuthenticator):
)
def _perform(self, domain, validation_name, validation):
self._get_digitalocean_client().add_txt_record(domain, validation_name, validation)
self._get_digitalocean_client().add_txt_record(domain, validation_name, validation,
self.ttl)
def _cleanup(self, domain, validation_name, validation):
self._get_digitalocean_client().del_txt_record(domain, validation_name, validation)
@@ -62,13 +64,15 @@ class _DigitalOceanClient:
def __init__(self, token):
self.manager = digitalocean.Manager(token=token)
def add_txt_record(self, domain_name, record_name, record_content):
def add_txt_record(self, domain_name: str, record_name: str, record_content: str,
record_ttl: int):
"""
Add a TXT record using the supplied information.
:param str domain_name: The domain to use to associate the record with.
: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.
:raises certbot.errors.PluginError: if an error occurs communicating with the DigitalOcean
API
"""
@@ -89,7 +93,8 @@ class _DigitalOceanClient:
result = domain.create_new_domain_record(
type='TXT',
name=self._compute_record_name(domain, record_name),
data=record_content)
data=record_content,
ttl=record_ttl) # ttl kwarg is only effective starting python-digitalocean 1.15.0
record_id = result['domain_record']['id']
@@ -99,7 +104,7 @@ class _DigitalOceanClient:
raise errors.PluginError('Error adding TXT record using the DigitalOcean API: {0}'
.format(e))
def del_txt_record(self, domain_name, record_name, record_content):
def del_txt_record(self, domain_name: str, record_name: str, record_content: str):
"""
Delete a TXT record using the supplied information.
+1 -1
View File
@@ -9,7 +9,7 @@ version = '1.14.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.
install_requires = [
'python-digitalocean>=1.11',
'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support
'setuptools>=39.0.1',
'zope.interface',
]
@@ -40,7 +40,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)]
expected = [mock.call.add_txt_record(DOMAIN, '_acme-challenge.'+DOMAIN, mock.ANY, 30)]
self.assertEqual(expected, self.mock_client.mock_calls)
def test_cleanup(self):
@@ -58,6 +58,7 @@ class DigitalOceanClientTest(unittest.TestCase):
record_prefix = "_acme-challenge"
record_name = record_prefix + "." + DOMAIN
record_content = "bar"
record_ttl = 60
def setUp(self):
from certbot_dns_digitalocean._internal.dns_digitalocean import _DigitalOceanClient
@@ -78,25 +79,27 @@ class DigitalOceanClientTest(unittest.TestCase):
self.manager.get_all_domains.return_value = [wrong_domain_mock, domain_mock]
self.digitalocean_client.add_txt_record(DOMAIN, self.record_name, self.record_content)
self.digitalocean_client.add_txt_record(DOMAIN, self.record_name, self.record_content,
self.record_ttl)
domain_mock.create_new_domain_record.assert_called_with(type='TXT',
name=self.record_prefix,
data=self.record_content)
data=self.record_content,
ttl=self.record_ttl)
def test_add_txt_record_fail_to_find_domain(self):
self.manager.get_all_domains.return_value = []
self.assertRaises(errors.PluginError,
self.digitalocean_client.add_txt_record,
DOMAIN, self.record_name, self.record_content)
DOMAIN, self.record_name, self.record_content, self.record_ttl)
def test_add_txt_record_error_finding_domain(self):
self.manager.get_all_domains.side_effect = API_ERROR
self.assertRaises(errors.PluginError,
self.digitalocean_client.add_txt_record,
DOMAIN, self.record_name, self.record_content)
DOMAIN, self.record_name, self.record_content, self.record_ttl)
def test_add_txt_record_error_creating_record(self):
domain_mock = mock.MagicMock()
@@ -107,7 +110,7 @@ class DigitalOceanClientTest(unittest.TestCase):
self.assertRaises(errors.PluginError,
self.digitalocean_client.add_txt_record,
DOMAIN, self.record_name, self.record_content)
DOMAIN, self.record_name, self.record_content, self.record_ttl)
def test_del_txt_record(self):
first_record_mock = mock.MagicMock()
+1
View File
@@ -11,6 +11,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
### Changed
* certbot-auto no longer checks for updates on any operating system.
* The DigitalOcean plugin now creates TXT records for the DNS-01 challenge with a lower 30s TTL.
### Fixed
+2 -1
View File
@@ -51,6 +51,7 @@ jedi==0.17.1
Jinja2==2.9.6
jmespath==0.9.4
josepy==1.1.0
jsonpickle==2.0.0
jsonschema==2.6.0
lazy-object-proxy==1.4.3
logger==1.4
@@ -93,7 +94,7 @@ pytest-xdist==1.22.5
pytest-sugar==0.9.2
pytest-rerunfailures==4.2
python-dateutil==2.8.1
python-digitalocean==1.11
python-digitalocean==1.15.0
python-dotenv==0.14.0
pywin32==300
PyYAML==5.3.1