determine_authenticator tests

This commit is contained in:
James Kasten
2015-02-19 19:33:54 -08:00
parent 6c8eb8be17
commit 119863d1ea
7 changed files with 82 additions and 21 deletions
+9 -14
View File
@@ -19,7 +19,6 @@ from letsencrypt.client import le_util
from letsencrypt.client import network from letsencrypt.client import network
from letsencrypt.client import reverter from letsencrypt.client import reverter
from letsencrypt.client import revoker from letsencrypt.client import revoker
from letsencrypt.client import standalone_authenticator
from letsencrypt.client.apache import configurator from letsencrypt.client.apache import configurator
from letsencrypt.client.display import ops from letsencrypt.client.display import ops
@@ -346,22 +345,17 @@ def init_csr(privkey, names, cert_dir):
return le_util.CSR(csr_filename, csr_der, "der") return le_util.CSR(csr_filename, csr_der, "der")
# This should be controlled by commandline parameters # This should be controlled by commandline parameters
def determine_authenticator(config): def determine_authenticator(all_auths):
"""Returns a valid IAuthenticator. """Returns a valid IAuthenticator.
:param config: Configuration. :param list all_auths: Where each is a tuple of the form
:type config: :class:`letsencrypt.client.interfaces.IConfig` ('description', 'IAuthenticator', *options..) where IAuthenticator is a
:class:`letsencrypt.client.interfaces.IAuthenticator` object or class
and options are the parameters used to initialize the authenticator.
:returns: Valid Authenticator object or None :returns: Valid Authenticator object or None
""" """
# list of (Description, Known Authenticator classes, init arguments)
all_auths = [
("Apache Web Server", configurator.ApacheConfigurator, config),
("Standalone Authenticator",
standalone_authenticator.StandaloneAuthenticator),
]
# Available Authenticator objects # Available Authenticator objects
avail_auths = [] avail_auths = []
# Error messages for misconfigured authenticators # Error messages for misconfigured authenticators
@@ -370,14 +364,15 @@ def determine_authenticator(config):
for pot_auth in all_auths: for pot_auth in all_auths:
try: try:
# I do not think this a great solution but haven't come up with # I do not think this a great solution but haven't come up with
# anything better yet... # anything better yet... other than constricting init functions for
# authenticators
if len(pot_auth) == 2: if len(pot_auth) == 2:
# pylint: disable=no-value-for-parameter # pylint: disable=no-value-for-parameter
avail_auths.append((pot_auth[0], pot_auth[1]())) avail_auths.append((pot_auth[0], pot_auth[1]()))
elif len(pot_auth) == 3: elif len(pot_auth) == 3:
avail_auths.append((pot_auth[0], pot_auth[1](pot_auth[2]))) avail_auths.append((pot_auth[0], pot_auth[1](pot_auth[2])))
else: else:
errors.LetsEncryptClientError( raise errors.LetsEncryptClientError(
"IAuthenticator: Number of parameters not supported") "IAuthenticator: Number of parameters not supported")
except errors.LetsEncryptMisconfigurationError as err: except errors.LetsEncryptMisconfigurationError as err:
errs[pot_auth[1]] = err errs[pot_auth[1]] = err
@@ -388,7 +383,7 @@ def determine_authenticator(config):
if len(avail_auths) > 1: if len(avail_auths) > 1:
auth = ops.choose_authenticator(avail_auths, errs) auth = ops.choose_authenticator(avail_auths, errs)
elif len(avail_auths) == 1: elif len(avail_auths) == 1:
auth = avail_auths[0] auth = avail_auths[0][1]
else: else:
auth = None auth = None
+2 -1
View File
@@ -23,7 +23,8 @@ def choose_authenticator(auths, errs):
:rtype: :class:`letsencrypt.client.interfaces.IAuthenticator` :rtype: :class:`letsencrypt.client.interfaces.IAuthenticator`
""" """
descs = [auth[0] for auth in auths] descs = [auth[0] if auth[1] not in errs else "%s (Misconfigured)" % auth[0]
for auth in auths]
iauths = [auth[1] for auth in auths] iauths = [auth[1] for auth in auths]
while True: while True:
+3
View File
@@ -175,6 +175,9 @@ class FileDisplay(object):
# pylint: disable=unused-argument # pylint: disable=unused-argument
"""Display a menu. """Display a menu.
.. todo:: This doesn't enable the help label/button (I wasn't sold on
any interface I came up with for this). It would be a nice feature
:param str message: title of menu :param str message: title of menu
:param choices: Menu lines, len must be > 0 :param choices: Menu lines, len must be > 0
:type choices: list of tuples (tag, item) or :type choices: list of tuples (tag, item) or
+1 -1
View File
@@ -57,7 +57,7 @@ class IAuthenticator(zope.interface.Interface):
""" """
def more_info(self): def more_info():
"""Human-readable string to help the user. """Human-readable string to help the user.
Should describe the steps taken and any relevant info to help the user Should describe the steps taken and any relevant info to help the user
@@ -414,4 +414,4 @@ class StandaloneAuthenticator(object):
"is attained, it will be saved in the " "is attained, it will be saved in the "
"(TODO) current working directory.{0}{0}" "(TODO) current working directory.{0}{0}"
"Port 443 must be open in order to use the " "Port 443 must be open in order to use the "
"Standalone Authenticator.") "Standalone Authenticator.".format(os.linesep))
+57 -1
View File
@@ -6,10 +6,66 @@ import mock
from letsencrypt.client import errors from letsencrypt.client import errors
class DetermineAuthenticatorTest(unittest.TestCase):
def setUp(self):
from letsencrypt.client.apache.configurator import ApacheConfigurator
from letsencrypt.client.standalone_authenticator \
import StandaloneAuthenticator
self.mock_stand = mock.MagicMock(spec=StandaloneAuthenticator)
self.mock_apache = mock.MagicMock(spec=ApacheConfigurator)
self.mock_config = mock.Mock()
self.all_auths = [
("Apache Web Server", self.mock_apache, self.mock_config),
("Standalone", self.mock_stand),
]
@classmethod
def _call(cls, all_auths):
from letsencrypt.client.client import determine_authenticator
return determine_authenticator(all_auths)
@mock.patch("letsencrypt.client.client.ops.choose_authenticator")
def test_accept_two(self, mock_choose):
mock_choose.return_value = self.mock_stand()
self.assertEqual(self._call(self.all_auths), self.mock_stand())
def test_accept_one(self):
self.assertEqual(
self._call(self.all_auths[:1]), self.mock_apache(self.mock_config))
def test_no_installation_one(self):
self.mock_apache.side_effect = errors.LetsEncryptNoInstallationError
self.assertEqual(self._call(self.all_auths), self.mock_stand())
def test_no_installations(self):
self.mock_apache.side_effect = errors.LetsEncryptNoInstallationError
self.mock_stand.side_effect = errors.LetsEncryptNoInstallationError
self.assertTrue(self._call(self.all_auths) is None)
@mock.patch("letsencrypt.client.client.logging")
@mock.patch("letsencrypt.client.client.ops.choose_authenticator")
def test_misconfigured(self, mock_choose, mock_log):
self.mock_apache.side_effect = errors.LetsEncryptMisconfigurationError
mock_choose.return_value = self.mock_apache
self.assertRaises(SystemExit, self._call, self.all_auths)
def test_too_many_params(self):
self.assertRaises(
errors.LetsEncryptClientError,
self._call,
[("desc", self.mock_apache, "1", "2", "3", "4", "5")])
class RollbackTest(unittest.TestCase): class RollbackTest(unittest.TestCase):
"""Test the rollback function.""" """Test the rollback function."""
def setUp(self): def setUp(self):
self.m_install = mock.MagicMock() from letsencrypt.client.apache.configurator import ApacheConfigurator
self.m_install = mock.MagicMock(spec=ApacheConfigurator)
@classmethod @classmethod
def _call(cls, checkpoints): def _call(cls, checkpoints):
+9 -3
View File
@@ -19,6 +19,8 @@ from letsencrypt.client import client
from letsencrypt.client import interfaces from letsencrypt.client import interfaces
from letsencrypt.client import le_util from letsencrypt.client import le_util
from letsencrypt.client import log from letsencrypt.client import log
from letsencrypt.client import standalone_authenticator
from letsencrypt.client.apache import configurator
from letsencrypt.client.display import util as display_util from letsencrypt.client.display import util as display_util
from letsencrypt.client.display import ops from letsencrypt.client.display import ops
@@ -134,9 +136,13 @@ def main(): # pylint: disable=too-many-branches
if not args.eula: if not args.eula:
display_eula() display_eula()
# Make sure we actually get an installer that is functioning properly # list of (Description, Known Authenticator classes, init arguments)
# before we begin to try to use it. all_auths = [
auth = client.determine_authenticator(config) ("Apache Web Server", configurator.ApacheConfigurator, config),
("Standalone Authenticator",
standalone_authenticator.StandaloneAuthenticator),
]
auth = client.determine_authenticator(all_auths)
if auth is None: if auth is None:
logging.critical("Unable to find a way to authenticate the server.") logging.critical("Unable to find a way to authenticate the server.")
sys.exit(4) sys.exit(4)