This commit is contained in:
Jean Rougé 2026-05-20 13:08:26 +00:00 committed by GitHub
commit 085a54e99d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 5 deletions

View file

@ -49,8 +49,9 @@ class Authenticator(common.Plugin, interfaces.Authenticator):
@classmethod
def add_parser_arguments(cls, add: Callable[..., None]) -> None:
# This authenticator currently adds no extra arguments.
pass
add('hosted-zone-id',
type=str,
help='Route 53 zone ID to use to create the verification record')
def auth_hint(self, failed_achalls: list[achallenges.AnnotatedChallenge]) -> str:
return (
@ -128,7 +129,9 @@ class Authenticator(common.Plugin, interfaces.Authenticator):
return zones[0][1]
def _change_txt_record(self, action: str, validation_domain_name: str, validation: str) -> str:
zone_id = self._find_zone_id_for_domain(validation_domain_name)
zone_id = self.conf('hosted-zone-id')
if not zone_id:
zone_id = self._find_zone_id_for_domain(validation_domain_name)
rrecords = self._resource_records[validation_domain_name]
challenge = {"Value": '"{0}"'.format(validation)}

View file

@ -2,6 +2,8 @@
import sys
import unittest
from dataclasses import dataclass
from typing import Optional
from unittest import mock
from botocore.exceptions import ClientError
@ -20,6 +22,11 @@ from certbot.tests import util as test_util
KEY = jose.jwk.JWKRSA.load(test_util.load_vector("rsa512_key.pem"))
@dataclass
class Route53TestConfig:
route53_hosted_zone_id: Optional[str] = None
class AuthenticatorTest(unittest.TestCase):
# pylint: disable=protected-access
@ -33,7 +40,7 @@ class AuthenticatorTest(unittest.TestCase):
super().setUp()
self.config = mock.MagicMock()
self.config = Route53TestConfig()
# Set up dummy credentials for testing
os.environ["AWS_ACCESS_KEY_ID"] = "dummy_access_key"
@ -143,7 +150,7 @@ class ClientTest(unittest.TestCase):
def setUp(self):
from certbot_dns_route53._internal.dns_route53 import Authenticator
self.config = mock.MagicMock()
self.config = Route53TestConfig()
# Set up dummy credentials for testing
os.environ["AWS_ACCESS_KEY_ID"] = "dummy_access_key"
@ -269,6 +276,37 @@ class ClientTest(unittest.TestCase):
assert self.client.r53.get_change.called
def test_change_txt_record_with_explicit_zone_id(self):
self.client.config.route53_hosted_zone_id = "EXPLICIT-ZONE-ID"
# _find_zone_id_for_domain should NOT be called if the config is present
self.client._find_zone_id_for_domain = mock.MagicMock() # type: ignore[method-assign, unused-ignore]
self.client.r53.change_resource_record_sets = mock.MagicMock(
return_value={"ChangeInfo": {"Id": 1}}
)
self.client._change_txt_record("UPSERT", DOMAIN, "val123")
# we didn't try to auto-detect the zone
assert not self.client._find_zone_id_for_domain.called
# and we used the right zone ID
call_kwargs = self.client.r53.change_resource_record_sets.call_args.kwargs
assert call_kwargs["HostedZoneId"] == "EXPLICIT-ZONE-ID"
def test_change_txt_record_without_zone_id_falls_back_to_lookup(self):
self.client._find_zone_id_for_domain = mock.MagicMock(return_value="LOOKED-UP") # type: ignore[method-assign, unused-ignore]
self.client.r53.change_resource_record_sets = mock.MagicMock(
return_value={"ChangeInfo": {"Id": 1}}
)
self.client._change_txt_record("UPSERT", DOMAIN, "val456")
self.client._find_zone_id_for_domain.assert_called_once_with(DOMAIN)
call_kwargs = self.client.r53.change_resource_record_sets.call_args.kwargs
assert call_kwargs["HostedZoneId"] == "LOOKED-UP"
if __name__ == "__main__":
sys.exit(pytest.main(sys.argv[1:] + [__file__])) # pragma: no cover