Exemple #1
0
    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.dns_achall_2 = acme_util.DNS01_A_2
        self.tls_sni_achall = acme_util.TLSSNI01_A
        self.achalls = [
            self.http_achall, self.dns_achall, self.tls_sni_achall,
            self.dns_achall_2
        ]
        for d in ["config_dir", "work_dir", "in_progress"]:
            os.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0,
            manual_auth_hook=None,
            manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False,
            noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(self.tempdir,
                                             "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"),
            tls_sni_01_port=5001)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')
    def setUp(self):
        from certbot.plugins.manual import Authenticator
        self.config = mock.MagicMock(
            http01_port=8080, manual_test_mode=False,
            manual_public_ip_logging_ok=False, noninteractive_mode=True)
        self.auth = Authenticator(config=self.config, name="manual")
        self.achalls = [achallenges.KeyAuthorizationAnnotatedChallenge(
            challb=acme_util.HTTP01_P, domain="foo.com", account_key=KEY)]

        config_test_mode = mock.MagicMock(
            http01_port=8080, manual_test_mode=True, noninteractive_mode=True)
        self.auth_test_mode = Authenticator(
            config=config_test_mode, name="manual")
Exemple #3
0
    def setUp(self):
        from certbot.plugins.manual import Authenticator
        self.config = mock.MagicMock(
            http01_port=8080, manual_test_mode=False,
            manual_public_ip_logging_ok=False, noninteractive_mode=True)
        self.auth = Authenticator(config=self.config, name="manual")
        self.achalls = [achallenges.KeyAuthorizationAnnotatedChallenge(
            challb=acme_util.HTTP01_P, domain="foo.com", account_key=KEY)]

        config_test_mode = mock.MagicMock(
            http01_port=8080, manual_test_mode=True, noninteractive_mode=True)
        self.auth_test_mode = Authenticator(
            config=config_test_mode, name="manual")
Exemple #4
0
    def setUp(self):
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.achalls = [self.http_achall, self.dns_achall]
        self.config = mock.MagicMock(http01_port=0,
                                     manual_auth_hook=None,
                                     manual_cleanup_hook=None,
                                     manual_public_ip_logging_ok=False,
                                     noninteractive_mode=False,
                                     validate_hooks=False)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')
Exemple #5
0
    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.tls_sni_achall = acme_util.TLSSNI01_A
        self.achalls = [self.http_achall, self.dns_achall, self.tls_sni_achall]
        for d in ["config_dir", "work_dir", "in_progress"]:
            os.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(
                                        self.tempdir, "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"),
            tls_sni_01_port=5001)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')
Exemple #6
0
    def setUp(self):
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.achalls = [self.http_achall, self.dns_achall]
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')
Exemple #7
0
class AuthenticatorTest(test_util.TempDirTestCase):
    """Tests for certbot.plugins.manual.Authenticator."""

    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.dns_achall_2 = acme_util.DNS01_A_2
        self.achalls = [self.http_achall, self.dns_achall, self.dns_achall_2]
        for d in ["config_dir", "work_dir", "in_progress"]:
            filesystem.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(
                                        self.tempdir, "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"))

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(self.auth.get_chall_pref('example.org'),
                         [challenges.HTTP01, challenges.DNS01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            '{0} -c "from __future__ import print_function;'
            'from certbot.compat import os;  print(os.environ.get(\'CERTBOT_DOMAIN\'));'
            'print(os.environ.get(\'CERTBOT_TOKEN\', \'notoken\'));'
            'print(os.environ.get(\'CERTBOT_VALIDATION\', \'novalidation\'));"'
            .format(sys.executable))
        dns_expected = '{0}\n{1}\n{2}'.format(
            self.dns_achall.domain, 'notoken',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall]['CERTBOT_AUTH_OUTPUT'],
            http_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            self.assertTrue(
                achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = ('{0} -c "import sys; sys.stdout.write(\'foo\')"'
                                        .format(sys.executable))
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            if isinstance(achall.chall, (challenges.HTTP01, challenges.DNS01)):
                self.assertEqual(
                    os.environ['CERTBOT_VALIDATION'],
                    achall.validation(achall.account_key))
            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(
                    os.environ['CERTBOT_TOKEN'],
                    achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
Exemple #8
0
class AuthenticatorTest(unittest.TestCase):
    """Tests for certbot.plugins.manual.Authenticator."""

    def setUp(self):
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.achalls = [self.http_achall, self.dns_achall]
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(self.auth.get_chall_pref('example.org'),
                         [challenges.HTTP01, challenges.DNS01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            'echo $CERTBOT_DOMAIN; echo ${CERTBOT_TOKEN:-notoken}; '
            'echo $CERTBOT_VALIDATION;')
        dns_expected = '{0}\n{1}\n{2}'.format(
            self.dns_achall.domain, 'notoken',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            http_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            self.assertTrue(achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = 'echo foo;'
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            self.assertEqual(
                os.environ['CERTBOT_VALIDATION'],
                achall.validation(achall.account_key))

            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(
                    os.environ['CERTBOT_TOKEN'],
                    achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
Exemple #9
0
class AuthenticatorTest(unittest.TestCase):
    """Tests for certbot.plugins.manual.Authenticator."""
    def setUp(self):
        from certbot.plugins.manual import Authenticator
        self.config = mock.MagicMock(http01_port=8080,
                                     manual_test_mode=False,
                                     manual_public_ip_logging_ok=False,
                                     noninteractive_mode=True)
        self.auth = Authenticator(config=self.config, name="manual")

        self.http01 = achallenges.KeyAuthorizationAnnotatedChallenge(
            challb=acme_util.HTTP01_P, domain="foo.com", account_key=KEY)
        self.dns01 = achallenges.KeyAuthorizationAnnotatedChallenge(
            challb=acme_util.DNS01_P, domain="foo.com", account_key=KEY)

        self.achalls = [self.http01, self.dns01]

        config_test_mode = mock.MagicMock(http01_port=8080,
                                          manual_test_mode=True,
                                          noninteractive_mode=True)
        self.auth_test_mode = Authenticator(config=config_test_mode,
                                            name="manual")

    def test_prepare(self):
        self.assertRaises(errors.PluginError, self.auth.prepare)
        self.auth_test_mode.prepare()  # error not raised

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), str))

    def test_get_chall_pref(self):
        self.assertTrue(
            all(
                issubclass(pref, challenges.Challenge)
                for pref in self.auth.get_chall_pref("foo.com")))

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    def test_perform_empty(self, mock_interaction):
        mock_interaction().yesno.return_value = True
        self.assertEqual([], self.auth.perform([]))

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    @mock.patch("certbot.plugins.manual.sys.stdout")
    @mock.patch("acme.challenges.HTTP01Response.simple_verify")
    @mock.patch("six.moves.input")
    def test_perform(self, mock_raw_input, mock_verify, mock_stdout,
                     mock_interaction):
        mock_verify.return_value = True
        mock_interaction().yesno.return_value = True

        resp_http = self.http01.response(KEY)
        resp_dns = self.dns01.response(KEY)

        self.assertEqual([resp_http, resp_dns],
                         self.auth.perform(self.achalls))
        self.assertEqual(2, mock_raw_input.call_count)
        mock_verify.assert_called_with(self.http01.challb.chall, "foo.com",
                                       KEY.public_key(), 8080)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertTrue(self.http01.chall.encode("token") in message)

        mock_verify.return_value = False
        with mock.patch("certbot.plugins.manual.logger") as mock_logger:
            self.auth.perform(self.achalls)
            self.assertEqual(2, mock_logger.warning.call_count)

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    @mock.patch("acme.challenges.DNS01Response.simple_verify")
    @mock.patch("six.moves.input")
    def test_perform_missing_dependency(self, mock_raw_input, mock_verify,
                                        mock_interaction):
        mock_interaction().yesno.return_value = True
        mock_verify.side_effect = acme_errors.DependencyError()

        with mock.patch("certbot.plugins.manual.logger") as mock_logger:
            self.auth.perform([self.dns01])
            self.assertEqual(1, mock_logger.warning.call_count)

        mock_raw_input.assert_called_once_with("Press ENTER to continue")

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    @mock.patch("certbot.plugins.manual.Authenticator._notify_and_wait")
    def test_disagree_with_ip_logging(self, mock_notify, mock_interaction):
        mock_interaction().yesno.return_value = False
        mock_notify.side_effect = errors.Error("Exception not raised, \
            continued execution even after disagreeing with IP logging")

        self.assertRaises(errors.PluginError, self.auth.perform, self.achalls)

    @mock.patch("certbot.plugins.manual.subprocess.Popen", autospec=True)
    def test_perform_test_command_oserror(self, mock_popen):
        mock_popen.side_effect = OSError
        self.assertEqual([False], self.auth_test_mode.perform([self.http01]))

    @mock.patch("certbot.plugins.manual.socket.socket")
    @mock.patch("certbot.plugins.manual.time.sleep", autospec=True)
    @mock.patch("certbot.plugins.manual.subprocess.Popen", autospec=True)
    def test_perform_test_command_run_failure(self, mock_popen,
                                              unused_mock_sleep,
                                              unused_mock_socket):
        mock_popen.poll.return_value = 10
        mock_popen.return_value.pid = 1234
        self.assertRaises(errors.Error, self.auth_test_mode.perform,
                          self.achalls)

    def test_cleanup_test_mode_already_terminated(self):
        # pylint: disable=protected-access
        self.auth_test_mode._httpd = httpd = mock.Mock()
        httpd.poll.return_value = 0
        self.auth_test_mode.cleanup(self.achalls)

    def test_cleanup_test_mode_kills_still_running(self):
        # pylint: disable=protected-access
        self.auth_test_mode._httpd = httpd = mock.Mock(pid=1234)
        httpd.poll.return_value = None
        self.auth_test_mode.cleanup(self.achalls)
        httpd.terminate.assert_called_once_with()
Exemple #10
0
class AuthenticatorTest(test_util.TempDirTestCase):
    """Tests for certbot.plugins.manual.Authenticator."""

    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.tls_sni_achall = acme_util.TLSSNI01_A
        self.achalls = [self.http_achall, self.dns_achall, self.tls_sni_achall]
        for d in ["config_dir", "work_dir", "in_progress"]:
            os.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(
                                        self.tempdir, "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"),
            tls_sni_01_port=5001)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(self.auth.get_chall_pref('example.org'),
                         [challenges.HTTP01,
                          challenges.DNS01,
                          challenges.TLSSNI01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            'echo ${CERTBOT_DOMAIN}; '
            'echo ${CERTBOT_TOKEN:-notoken}; '
            'echo ${CERTBOT_CERT_PATH:-nocert}; '
            'echo ${CERTBOT_KEY_PATH:-nokey}; '
            'echo ${CERTBOT_SNI_DOMAIN:-nosnidomain}; '
            'echo ${CERTBOT_VALIDATION:-novalidation};')
        dns_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.dns_achall.domain, 'notoken',
            'nocert', 'nokey', 'nosnidomain',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            'nocert', 'nokey', 'nosnidomain',
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            http_expected)
        # tls_sni_01 challenge must be perform()ed above before we can
        # get the cert_path and key_path.
        tls_sni_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.tls_sni_achall.domain, 'notoken',
            self.auth.tls_sni_01.get_cert_path(self.tls_sni_achall),
            self.auth.tls_sni_01.get_key_path(self.tls_sni_achall),
            self.auth.tls_sni_01.get_z_domain(self.tls_sni_achall),
            'novalidation')
        self.assertEqual(
            self.auth.env[self.tls_sni_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            tls_sni_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            if isinstance(achall.chall, challenges.TLSSNI01):
                self.assertTrue(
                        self.auth.tls_sni_01.get_cert_path(
                            self.tls_sni_achall) in args[0])
            else:
                self.assertTrue(
                        achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = 'echo foo;'
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            if (isinstance(achall.chall, challenges.HTTP01) or
                isinstance(achall.chall, challenges.DNS01)):
                self.assertEqual(
                    os.environ['CERTBOT_VALIDATION'],
                    achall.validation(achall.account_key))
            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(
                    os.environ['CERTBOT_TOKEN'],
                    achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
            if isinstance(achall.chall, challenges.TLSSNI01):
                self.assertEqual(
                    os.environ['CERTBOT_CERT_PATH'],
                    self.auth.tls_sni_01.get_cert_path(achall))
                self.assertEqual(
                    os.environ['CERTBOT_KEY_PATH'],
                    self.auth.tls_sni_01.get_key_path(achall))
                self.assertFalse(
                    os.path.exists(os.environ['CERTBOT_CERT_PATH']))
                self.assertFalse(
                    os.path.exists(os.environ['CERTBOT_KEY_PATH']))
class AuthenticatorTest(test_util.TempDirTestCase):
    """Tests for certbot.plugins.manual.Authenticator."""

    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.dns_achall_2 = acme_util.DNS01_A_2
        self.achalls = [self.http_achall, self.dns_achall, self.dns_achall_2]
        for d in ["config_dir", "work_dir", "in_progress"]:
            os.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0, manual_auth_hook=None, manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False, noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(
                                        self.tempdir, "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"))

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(self.auth.get_chall_pref('example.org'),
                         [challenges.HTTP01, challenges.DNS01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            '{0} -c "from __future__ import print_function;'
            'import os;  print(os.environ.get(\'CERTBOT_DOMAIN\'));'
            'print(os.environ.get(\'CERTBOT_TOKEN\', \'notoken\'));'
            'print(os.environ.get(\'CERTBOT_VALIDATION\', \'novalidation\'));"'
            .format(sys.executable))
        dns_expected = '{0}\n{1}\n{2}'.format(
            self.dns_achall.domain, 'notoken',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall]['CERTBOT_AUTH_OUTPUT'],
            http_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            self.assertTrue(
                achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    @test_util.broken_on_windows
    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = 'echo foo;'
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            if (isinstance(achall.chall, challenges.HTTP01) or
                isinstance(achall.chall, challenges.DNS01)):
                self.assertEqual(
                    os.environ['CERTBOT_VALIDATION'],
                    achall.validation(achall.account_key))
            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(
                    os.environ['CERTBOT_TOKEN'],
                    achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
class AuthenticatorTest(unittest.TestCase):
    """Tests for certbot.plugins.manual.Authenticator."""

    def setUp(self):
        from certbot.plugins.manual import Authenticator
        self.config = mock.MagicMock(
            http01_port=8080, manual_test_mode=False,
            manual_public_ip_logging_ok=False, noninteractive_mode=True)
        self.auth = Authenticator(config=self.config, name="manual")
        self.achalls = [achallenges.KeyAuthorizationAnnotatedChallenge(
            challb=acme_util.HTTP01_P, domain="foo.com", account_key=KEY)]

        config_test_mode = mock.MagicMock(
            http01_port=8080, manual_test_mode=True, noninteractive_mode=True)
        self.auth_test_mode = Authenticator(
            config=config_test_mode, name="manual")

    def test_prepare(self):
        self.assertRaises(errors.PluginError, self.auth.prepare)
        self.auth_test_mode.prepare()  # error not raised

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), str))

    def test_get_chall_pref(self):
        self.assertTrue(all(issubclass(pref, challenges.Challenge)
                            for pref in self.auth.get_chall_pref("foo.com")))

    def test_perform_empty(self):
        self.assertEqual([], self.auth.perform([]))

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    @mock.patch("certbot.plugins.manual.sys.stdout")
    @mock.patch("acme.challenges.HTTP01Response.simple_verify")
    @mock.patch("six.moves.input")
    def test_perform(self, mock_raw_input, mock_verify, mock_stdout, mock_interaction):
        mock_verify.return_value = True
        mock_interaction().yesno.return_value = True

        resp = self.achalls[0].response(KEY)
        self.assertEqual([resp], self.auth.perform(self.achalls))
        self.assertEqual(1, mock_raw_input.call_count)
        mock_verify.assert_called_with(
            self.achalls[0].challb.chall, "foo.com", KEY.public_key(), 8080)

        message = mock_stdout.write.mock_calls[0][1][0]
        self.assertTrue(self.achalls[0].chall.encode("token") in message)

        mock_verify.return_value = False
        with mock.patch("certbot.plugins.manual.logger") as mock_logger:
            self.auth.perform(self.achalls)
            mock_logger.warning.assert_called_once_with(mock.ANY)

    @mock.patch("certbot.plugins.manual.zope.component.getUtility")
    @mock.patch("certbot.plugins.manual.Authenticator._notify_and_wait")
    def test_disagree_with_ip_logging(self, mock_notify, mock_interaction):
        mock_interaction().yesno.return_value = False
        mock_notify.side_effect = errors.Error("Exception not raised, \
            continued execution even after disagreeing with IP logging")

        self.assertRaises(errors.PluginError, self.auth.perform, self.achalls)

    @mock.patch("certbot.plugins.manual.subprocess.Popen", autospec=True)
    def test_perform_test_command_oserror(self, mock_popen):
        mock_popen.side_effect = OSError
        self.assertEqual([False], self.auth_test_mode.perform(self.achalls))

    @mock.patch("certbot.plugins.manual.socket.socket")
    @mock.patch("certbot.plugins.manual.time.sleep", autospec=True)
    @mock.patch("certbot.plugins.manual.subprocess.Popen", autospec=True)
    def test_perform_test_command_run_failure(
            self, mock_popen, unused_mock_sleep, unused_mock_socket):
        mock_popen.poll.return_value = 10
        mock_popen.return_value.pid = 1234
        self.assertRaises(
            errors.Error, self.auth_test_mode.perform, self.achalls)

    def test_cleanup_test_mode_already_terminated(self):
        # pylint: disable=protected-access
        self.auth_test_mode._httpd = httpd = mock.Mock()
        httpd.poll.return_value = 0
        self.auth_test_mode.cleanup(self.achalls)

    @mock.patch("certbot.plugins.manual.os.killpg", autospec=True)
    def test_cleanup_test_mode_kills_still_running(self, mock_killpg):
        # pylint: disable=protected-access
        self.auth_test_mode._httpd = httpd = mock.Mock(pid=1234)
        httpd.poll.return_value = None
        self.auth_test_mode.cleanup(self.achalls)
        mock_killpg.assert_called_once_with(1234, signal.SIGTERM)
Exemple #13
0
class AuthenticatorTest(unittest.TestCase):
    """Tests for certbot.plugins.manual.Authenticator."""
    def setUp(self):
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.achalls = [self.http_achall, self.dns_achall]
        self.config = mock.MagicMock(http01_port=0,
                                     manual_auth_hook=None,
                                     manual_cleanup_hook=None,
                                     manual_public_ip_logging_ok=False,
                                     noninteractive_mode=False,
                                     validate_hooks=False)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(self.auth.get_chall_pref('example.org'),
                         [challenges.HTTP01, challenges.DNS01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            'echo $CERTBOT_DOMAIN; echo ${CERTBOT_TOKEN:-notoken}; '
            'echo $CERTBOT_VALIDATION;')
        dns_expected = '{0}\n{1}\n{2}'.format(
            self.dns_achall.domain, 'notoken',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            http_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(
                mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            self.assertTrue(achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = 'echo foo;'
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            self.assertEqual(os.environ['CERTBOT_VALIDATION'],
                             achall.validation(achall.account_key))

            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(os.environ['CERTBOT_TOKEN'],
                                 achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
Exemple #14
0
class AuthenticatorTest(test_util.TempDirTestCase):
    """Tests for certbot.plugins.manual.Authenticator."""
    def setUp(self):
        super(AuthenticatorTest, self).setUp()
        self.http_achall = acme_util.HTTP01_A
        self.dns_achall = acme_util.DNS01_A
        self.tls_sni_achall = acme_util.TLSSNI01_A
        self.achalls = [self.http_achall, self.dns_achall, self.tls_sni_achall]
        for d in ["config_dir", "work_dir", "in_progress"]:
            os.mkdir(os.path.join(self.tempdir, d))
            # "backup_dir" and "temp_checkpoint_dir" get created in
            # certbot.util.make_or_verify_dir() during the Reverter
            # initialization.
        self.config = mock.MagicMock(
            http01_port=0,
            manual_auth_hook=None,
            manual_cleanup_hook=None,
            manual_public_ip_logging_ok=False,
            noninteractive_mode=False,
            validate_hooks=False,
            config_dir=os.path.join(self.tempdir, "config_dir"),
            work_dir=os.path.join(self.tempdir, "work_dir"),
            backup_dir=os.path.join(self.tempdir, "backup_dir"),
            temp_checkpoint_dir=os.path.join(self.tempdir,
                                             "temp_checkpoint_dir"),
            in_progress_dir=os.path.join(self.tempdir, "in_progess"),
            tls_sni_01_port=5001)

        from certbot.plugins.manual import Authenticator
        self.auth = Authenticator(self.config, name='manual')

    def test_prepare_no_hook_noninteractive(self):
        self.config.noninteractive_mode = True
        self.assertRaises(errors.PluginError, self.auth.prepare)

    def test_prepare_bad_hook(self):
        self.config.manual_auth_hook = os.path.abspath(os.sep)  # is / on UNIX
        self.config.validate_hooks = True
        self.assertRaises(errors.HookCommandNotFound, self.auth.prepare)

    def test_more_info(self):
        self.assertTrue(isinstance(self.auth.more_info(), six.string_types))

    def test_get_chall_pref(self):
        self.assertEqual(
            self.auth.get_chall_pref('example.org'),
            [challenges.HTTP01, challenges.DNS01, challenges.TLSSNI01])

    @test_util.patch_get_utility()
    def test_ip_logging_not_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = False
        self.assertRaises(errors.PluginError, self.auth.perform, [])

    @test_util.patch_get_utility()
    def test_ip_logging_ok(self, mock_get_utility):
        mock_get_utility().yesno.return_value = True
        self.auth.perform([])
        self.assertTrue(self.config.manual_public_ip_logging_ok)

    def test_script_perform(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = (
            'echo ${CERTBOT_DOMAIN}; '
            'echo ${CERTBOT_TOKEN:-notoken}; '
            'echo ${CERTBOT_CERT_PATH:-nocert}; '
            'echo ${CERTBOT_KEY_PATH:-nokey}; '
            'echo ${CERTBOT_SNI_DOMAIN:-nosnidomain}; '
            'echo ${CERTBOT_VALIDATION:-novalidation};')
        dns_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.dns_achall.domain, 'notoken', 'nocert', 'nokey',
            'nosnidomain',
            self.dns_achall.validation(self.dns_achall.account_key))
        http_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.http_achall.domain, self.http_achall.chall.encode('token'),
            'nocert', 'nokey', 'nosnidomain',
            self.http_achall.validation(self.http_achall.account_key))

        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        self.assertEqual(
            self.auth.env[self.dns_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            dns_expected)
        self.assertEqual(
            self.auth.env[self.http_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            http_expected)
        # tls_sni_01 challenge must be perform()ed above before we can
        # get the cert_path and key_path.
        tls_sni_expected = '{0}\n{1}\n{2}\n{3}\n{4}\n{5}'.format(
            self.tls_sni_achall.domain, 'notoken',
            self.auth.tls_sni_01.get_cert_path(self.tls_sni_achall),
            self.auth.tls_sni_01.get_key_path(self.tls_sni_achall),
            self.auth.tls_sni_01.get_z_domain(self.tls_sni_achall),
            'novalidation')
        self.assertEqual(
            self.auth.env[self.tls_sni_achall.domain]['CERTBOT_AUTH_OUTPUT'],
            tls_sni_expected)

    @test_util.patch_get_utility()
    def test_manual_perform(self, mock_get_utility):
        self.config.manual_public_ip_logging_ok = True
        self.assertEqual(
            self.auth.perform(self.achalls),
            [achall.response(achall.account_key) for achall in self.achalls])
        for i, (args, kwargs) in enumerate(
                mock_get_utility().notification.call_args_list):
            achall = self.achalls[i]
            if isinstance(achall.chall, challenges.TLSSNI01):
                self.assertTrue(
                    self.auth.tls_sni_01.get_cert_path(self.tls_sni_achall) in
                    args[0])
            else:
                self.assertTrue(
                    achall.validation(achall.account_key) in args[0])
            self.assertFalse(kwargs['wrap'])

    def test_cleanup(self):
        self.config.manual_public_ip_logging_ok = True
        self.config.manual_auth_hook = 'echo foo;'
        self.config.manual_cleanup_hook = '# cleanup'
        self.auth.perform(self.achalls)

        for achall in self.achalls:
            self.auth.cleanup([achall])
            self.assertEqual(os.environ['CERTBOT_AUTH_OUTPUT'], 'foo')
            self.assertEqual(os.environ['CERTBOT_DOMAIN'], achall.domain)
            if (isinstance(achall.chall, challenges.HTTP01)
                    or isinstance(achall.chall, challenges.DNS01)):
                self.assertEqual(os.environ['CERTBOT_VALIDATION'],
                                 achall.validation(achall.account_key))
            if isinstance(achall.chall, challenges.HTTP01):
                self.assertEqual(os.environ['CERTBOT_TOKEN'],
                                 achall.chall.encode('token'))
            else:
                self.assertFalse('CERTBOT_TOKEN' in os.environ)
            if isinstance(achall.chall, challenges.TLSSNI01):
                self.assertEqual(os.environ['CERTBOT_CERT_PATH'],
                                 self.auth.tls_sni_01.get_cert_path(achall))
                self.assertEqual(os.environ['CERTBOT_KEY_PATH'],
                                 self.auth.tls_sni_01.get_key_path(achall))
                self.assertFalse(
                    os.path.exists(os.environ['CERTBOT_CERT_PATH']))
                self.assertFalse(os.path.exists(
                    os.environ['CERTBOT_KEY_PATH']))