Compare commits

...

3 Commits

Author SHA1 Message Date
Alba Mendez
955a22d203 Update test case 2018-09-03 15:11:36 +02:00
Alba Mendez
69e252d74a Update and expand dns-route53 docs on credentials 2018-09-03 15:11:36 +02:00
Alba Mendez
0b91c4e670 Add --dns-route53-credentials option 2018-09-03 15:11:36 +02:00
3 changed files with 61 additions and 17 deletions

View File

@@ -12,6 +12,8 @@ Named Arguments
to propagate before asking the ACME
server to verify the DNS record.
(Default: 10)
``--dns-route53-credentials`` Load AWS credentials from specified
file. (Default: None)
======================================== =====================================
@@ -62,26 +64,40 @@ the required permissions <https://docs.aws.amazon.com/Route53/latest
The `access keys <https://docs.aws.amazon.com/general/latest/gr
/aws-sec-cred-types.html#access-keys-and-secret-access-keys>`_ for an account
with these permissions must be supplied in one of the following ways, which are
discussed in more detail in the Boto3 library's documentation about `configuring
credentials <https://boto3.readthedocs.io/en/latest/guide/configuration.html
#best-practices-for-configuring-credentials>`_.
* Using the ``AWS_ACCESS_KEY_ID`` and ``AWS_SECRET_ACCESS_KEY`` environment
variables.
* Using a credentials configuration file at the default location,
``~/.aws/config``.
* Using a credentials configuration file at a path supplied using the
``AWS_CONFIG_FILE`` environment variable.
with these permissions should be supplied by setting the
``--dns-route53-credentials`` option to a credentials file using standard format:
.. code-block:: ini
:name: config.ini
:caption: Example credentials config file:
:caption: Example AWS credentials config file:
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
**It is recommended to set ``--dns-route53-credentials``.** Otherwise Boto3 will
attempt to obtain credentials using files at ``$HOME`` or from
environment variables, which can differ at renewals. The following sources will
be tried (this is discussed in more detail in the Boto3 library's documentation
about `configuring credentials <https://boto3.readthedocs.io/en/latest
/guide/configuration.html#best-practices-for-configuring-credentials>`_):
* Using the ``AWS_ACCESS_KEY_ID`` and ``AWS_SECRET_ACCESS_KEY`` environment
variables.
* Using a shared credentials file at the default location,
``~/.aws/credentials``.
* Using a shared credentials file at a path supplied using the
``AWS_SHARED_CREDENTIALS_FILE`` environment variable.
* Using a credentials configuration file at the default location,
``~/.aws/config``.
* Using a credentials configuration file at a path supplied using the
``AWS_CONFIG_FILE`` environment variable..
Finally, if any of the above methods is used, and certbot is running in an EC2
instance which has an `IAM role attached <https://docs.aws.amazon.com/AWSEC2
/latest/UserGuide/iam-roles-for-amazon-ec2.html>`_, credentials for that role
will be used.
.. caution::
You should protect these API credentials as you would a password. Users who
can read this file can use these credentials to issue some types of API calls

View File

@@ -6,6 +6,7 @@ import time
import boto3
import zope.interface
from botocore.exceptions import NoCredentialsError, ClientError
from botocore.credentials import SharedCredentialProvider
from certbot import errors
from certbot import interfaces
@@ -35,9 +36,21 @@ class Authenticator(dns_common.DNSAuthenticator):
def __init__(self, *args, **kwargs):
super(Authenticator, self).__init__(*args, **kwargs)
self.r53 = boto3.client("route53")
if self.conf("credentials"):
creds = SharedCredentialProvider(self.conf("credentials")).load()
if creds is None:
raise errors.PluginError("Couldn't load AWS credentials")
self.r53 = boto3.client("route53",
aws_access_key_id=creds.access_key, aws_secret_access_key=creds.secret_key)
else:
self.r53 = boto3.client("route53")
self._resource_records = collections.defaultdict(list) # type: DefaultDict[str, List[Dict[str, str]]]
@classmethod
def add_parser_arguments(cls, add): # pylint: disable=arguments-differ
super(Authenticator, cls).add_parser_arguments(add)
add('credentials', help='Load AWS credentials from specified file.')
def more_info(self): # pylint: disable=missing-docstring,no-self-use
return "Solve a DNS01 challenge using AWS Route53"

View File

@@ -1,5 +1,6 @@
"""Tests for certbot_dns_route53.dns_route53.Authenticator"""
import os
import unittest
import mock
@@ -8,9 +9,15 @@ from botocore.exceptions import NoCredentialsError, ClientError
from certbot import errors
from certbot.plugins import dns_test_common
from certbot.plugins.dns_test_common import DOMAIN
from certbot.tests import util as test_util
CREDS_FILE = '''[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
'''
class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest):
class AuthenticatorTest(test_util.TempDirTestCase, dns_test_common.BaseAuthenticatorTest):
# pylint: disable=protected-access
def setUp(self):
@@ -18,7 +25,11 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest
super(AuthenticatorTest, self).setUp()
self.config = mock.MagicMock()
path = os.path.join(self.tempdir, '.ini')
with open(path, "w") as creds_file:
creds_file.write(CREDS_FILE)
self.config = mock.MagicMock(route53_credentials=path)
self.auth = Authenticator(self.config, "route53")
@@ -75,7 +86,7 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest
self.auth.cleanup([self.achall])
class ClientTest(unittest.TestCase):
class ClientTest(test_util.TempDirTestCase):
# pylint: disable=protected-access
PRIVATE_ZONE = {
@@ -115,7 +126,11 @@ class ClientTest(unittest.TestCase):
super(ClientTest, self).setUp()
self.config = mock.MagicMock()
path = os.path.join(self.tempdir, '.ini')
with open(path, "w") as creds_file:
creds_file.write(CREDS_FILE)
self.config = mock.MagicMock(route53_credentials=path)
self.client = Authenticator(self.config, "route53")