Example #1
0
class GetAuthorizationsTest(unittest.TestCase):
    """get_authorizations test.

    This tests everything except for all functions under _poll_challenges.

    """
    def setUp(self):
        from certbot.auth_handler import AuthHandler

        self.mock_auth = mock.MagicMock(name="ApacheConfigurator")

        self.mock_auth.get_chall_pref.return_value = [challenges.TLSSNI01]

        self.mock_auth.perform.side_effect = gen_auth_resp

        self.mock_account = mock.Mock(key=util.Key("file_path", "PEM"))
        self.mock_net = mock.MagicMock(spec=acme_client.Client)

        self.handler = AuthHandler(self.mock_auth, self.mock_net,
                                   self.mock_account)

        logging.disable(logging.CRITICAL)

    def tearDown(self):
        logging.disable(logging.NOTSET)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 1)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(chall_update.keys(), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ,
                         "tls-sni-01")

        self.assertEqual(len(authzr), 1)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1_http_01_1_dns_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES, combos=False)

        mock_poll.side_effect = self._validate_all
        self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01)
        self.mock_auth.get_chall_pref.return_value.append(challenges.DNS)

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(chall_update.keys(), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        for achall in self.mock_auth.cleanup.call_args[0][0]:
            self.assertTrue(achall.typ in ["tls-sni-01", "http-01", "dns"])

        # Length of authorizations list
        self.assertEqual(len(authzr), 1)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name3_tls_sni_01_3(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        authzr = self.handler.get_authorizations(["0", "1", "2"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        # Check poll call
        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(len(chall_update.keys()), 3)
        self.assertTrue("0" in chall_update.keys())
        self.assertEqual(len(chall_update["0"]), 1)
        self.assertTrue("1" in chall_update.keys())
        self.assertEqual(len(chall_update["1"]), 1)
        self.assertTrue("2" in chall_update.keys())
        self.assertEqual(len(chall_update["2"]), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)

        self.assertEqual(len(authzr), 3)

    def test_perform_failure(self):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)
        self.mock_auth.perform.side_effect = errors.AuthorizationError

        self.assertRaises(errors.AuthorizationError,
                          self.handler.get_authorizations, ["0"])

    def test_no_domains(self):
        self.assertRaises(errors.AuthorizationError,
                          self.handler.get_authorizations, [])

    def _validate_all(self, unused_1, unused_2):
        for dom in self.handler.authzr.keys():
            azr = self.handler.authzr[dom]
            self.handler.authzr[dom] = acme_util.gen_authzr(
                messages.STATUS_VALID, dom,
                [challb.chall for challb in azr.body.challenges],
                [messages.STATUS_VALID] * len(azr.body.challenges),
                azr.body.combinations)
Example #2
0
class GetAuthorizationsTest(unittest.TestCase):
    """get_authorizations test.

    This tests everything except for all functions under _poll_challenges.

    """
    def setUp(self):
        from certbot.auth_handler import AuthHandler
        from certbot_external_auth.plugin import AuthenticatorOut

        self.name = 'certbot-external-auth'
        self.name_cfg = self.name.replace('-', '_') + '_'
        self.tempdir = tempfile.mkdtemp(dir=tempfile.gettempdir())
        self.config = configuration.NamespaceConfig(
            mock.MagicMock(**constants.CLI_DEFAULTS))

        self.patch_tls = mock.patch(
            'acme.challenges.TLSSNI01Response.simple_verify')
        self.patch_http = mock.patch(
            'acme.challenges.HTTP01Response.simple_verify')
        self.patch_dns = mock.patch(
            'acme.challenges.DNS01Response.simple_verify')

        self.patch_tls.start()
        self.patch_http.start()
        self.patch_dns.start()

        self.config.verb = "certonly"
        self.config.config_dir = os.path.join(self.tempdir, 'config')
        self.config.work_dir = os.path.join(self.tempdir, 'work')
        self.config.logs_dir = os.path.join(self.tempdir, 'logs')
        self.config.cert_path = constants.CLI_DEFAULTS['auth_cert_path']
        self.config.fullchain_path = constants.CLI_DEFAULTS['auth_chain_path']
        self.config.chain_path = constants.CLI_DEFAULTS['auth_chain_path']
        self.config.server = "example.com"
        self.config.__setattr__(self.name_cfg + 'handler', None)
        self.config.__setattr__(self.name_cfg + 'public_ip_logging_ok', True)
        self.config.__setattr__(self.name_cfg + 'test_mode', False)
        self.config.__setattr__(self.name_cfg + 'text_mode', False)
        self.config.__setattr__(self.name_cfg + 'dehydrated_dns', False)

        self.mock_display = mock.Mock()
        zope.component.provideUtility(self.mock_display, interfaces.IDisplay)
        zope.component.provideUtility(mock.Mock(debug_challenges=False),
                                      interfaces.IConfig)

        self.mock_auth = AuthenticatorOut(self.config, self.name)

        self.mock_auth.get_chall_pref = mock.MagicMock()
        self.mock_auth.get_chall_pref.return_value = [challenges.TLSSNI01]

        self.mock_data = []
        self.mock_json_out = mock.MagicMock(side_effect=self._update_data)
        self.mock_auth._json_out_and_wait = self.mock_json_out

        self.mock_auth.cleanup = mock.Mock()

        self.key_mock = mock.Mock()
        self.key_mock.key = mock.Mock()
        self.key_mock.key.file_path = 'PEM'
        self.key_mock.thumbprint = mock.MagicMock(
            return_value=b'00001234567890000')

        self.mock_account = mock.Mock(key=self.key_mock)
        self.mock_net = mock.MagicMock(spec=acme_client.Client)

        self.handler = AuthHandler(self.mock_auth, self.mock_net,
                                   self.mock_account, [])

        self.input_patch = mock.patch('six.moves.input')
        self.input_patch.start()

        logging.disable(logging.CRITICAL)

    def tearDown(self):
        shutil.rmtree(self.tempdir)
        logging.disable(logging.NOTSET)
        self.input_patch.stop()
        self.patch_tls.stop()
        self.patch_http.stop()
        self.patch_dns.stop()

    def _help_output(self, args):
        "Run a command, and return the output string for scrutiny"

        output = six.StringIO()

        def write_msg(message, *args, **kwargs):  # pylint: disable=missing-docstring,unused-argument
            output.write(message)

        with mock.patch('certbot.main.sys.stdout', new=output):
            with test_util.patch_get_utility() as mock_get_utility:
                mock_get_utility().notification.side_effect = write_msg
                with mock.patch('certbot.main.sys.stderr'):
                    self.assertRaises(SystemExit, self._unmocked_parse, args,
                                      output)

        return output.getvalue()

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 1)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(list(six.iterkeys(chall_update)), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ,
                         "tls-sni-01")

        self.assertEqual(len(authzr), 1)
        self.assertEqual(self.mock_json_out.call_count, 1)
        self.assertEqual(len(self.mock_data), 1)
        self.assertIn('cmd', self.mock_data[0])
        self.assertIn('token', self.mock_data[0])
        self.assertIn('validation', self.mock_data[0])
        self.assertTrue(len(self.mock_data[0]['validation']) > 5)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1_http_01_1_dns_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES, combos=False)

        mock_poll.side_effect = self._validate_all
        self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01)
        self.mock_auth.get_chall_pref.return_value.append(challenges.DNS01)

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(list(six.iterkeys(chall_update)), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        for achall in self.mock_auth.cleanup.call_args[0][0]:
            self.assertTrue(achall.typ in ["tls-sni-01", "http-01", "dns-01"])

        # Length of authorizations list
        self.assertEqual(len(authzr), 1)
        self.assertEqual(self.mock_json_out.call_count, 3)
        self.assertEqual(len(self.mock_data), 3)
        for msg in self.mock_data:
            self.assertIn('cmd', msg)
            self.assertIn('token', msg)
            self.assertIn('validation', msg)
            self.assertTrue(len(msg['validation']) > 5)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name3_tls_sni_01_3(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        with mock.patch('certbot.util.safe_open') as mock_open:
            mock_open.return_value = mock.MagicMock()
            authzr = self.handler.get_authorizations(["0", "1", "2"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        # Check poll call
        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(len(list(six.iterkeys(chall_update))), 3)
        self.assertTrue("0" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["0"]), 1)
        self.assertTrue("1" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["1"]), 1)
        self.assertTrue("2" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["2"]), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)

        self.assertEqual(len(authzr), 3)

        self.assertEqual(self.mock_json_out.call_count, 3)
        self.assertEqual(len(self.mock_data), 3)
        for msg in self.mock_data:
            self.assertIn('cmd', msg)
            self.assertIn('token', msg)
            self.assertIn('validation', msg)
            self.assertTrue(len(msg['validation']) > 5)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_debug_challenges(self, mock_poll):
        zope.component.provideUtility(mock.Mock(debug_challenges=True),
                                      interfaces.IConfig)
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 1)
        self.assertEqual(self.mock_display.notification.call_count, 1)

    def test_perform_failure(self):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        self.mock_auth.perform = mock.Mock()
        self.mock_auth.perform.side_effect = errors.AuthorizationError

        self.assertRaises(errors.AuthorizationError,
                          self.handler.get_authorizations, ["0"])

    def test_no_domains(self):
        self.assertRaises(errors.AuthorizationError,
                          self.handler.get_authorizations, [])

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_preferred_challenge_choice(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all
        self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01)

        self.handler.pref_challs.extend((
            challenges.HTTP01.typ,
            challenges.DNS01.typ,
        ))

        self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ,
                         "http-01")

    def test_preferred_challenges_not_supported(self):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)
        self.handler.pref_challs.append(challenges.HTTP01.typ)
        self.assertRaises(errors.AuthorizationError,
                          self.handler.get_authorizations, ["0"])

    def _validate_all(self, unused_1, unused_2):
        for dom in six.iterkeys(self.handler.authzr):
            azr = self.handler.authzr[dom]
            self.handler.authzr[dom] = acme_util.gen_authzr(
                messages.STATUS_VALID, dom,
                [challb.chall for challb in azr.body.challenges],
                [messages.STATUS_VALID] * len(azr.body.challenges),
                azr.body.combinations)

    def _update_data(self, x):
        self.mock_data.append(x)
Example #3
0
class GetAuthorizationsTest(unittest.TestCase):
    """get_authorizations test.

    This tests everything except for all functions under _poll_challenges.

    """

    def setUp(self):
        from certbot.auth_handler import AuthHandler

        self.mock_auth = mock.MagicMock(name="ApacheConfigurator")

        self.mock_auth.get_chall_pref.return_value = [challenges.TLSSNI01]

        self.mock_auth.perform.side_effect = gen_auth_resp

        self.mock_account = mock.Mock(key=util.Key("file_path", "PEM"))
        self.mock_net = mock.MagicMock(spec=acme_client.Client)

        self.handler = AuthHandler(
            self.mock_auth, self.mock_net, self.mock_account, [])

        logging.disable(logging.CRITICAL)

    def tearDown(self):
        logging.disable(logging.NOTSET)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 1)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(list(six.iterkeys(chall_update)), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        self.assertEqual(
            self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01")

        self.assertEqual(len(authzr), 1)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name1_tls_sni_01_1_http_01_1_dns_1(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES, combos=False)

        mock_poll.side_effect = self._validate_all
        self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01)
        self.mock_auth.get_chall_pref.return_value.append(challenges.DNS01)

        authzr = self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(list(six.iterkeys(chall_update)), ["0"])
        self.assertEqual(len(chall_update.values()), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        # Test if list first element is TLSSNI01, use typ because it is an achall
        for achall in self.mock_auth.cleanup.call_args[0][0]:
            self.assertTrue(achall.typ in ["tls-sni-01", "http-01", "dns-01"])

        # Length of authorizations list
        self.assertEqual(len(authzr), 1)

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_name3_tls_sni_01_3(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all

        authzr = self.handler.get_authorizations(["0", "1", "2"])

        self.assertEqual(self.mock_net.answer_challenge.call_count, 3)

        # Check poll call
        self.assertEqual(mock_poll.call_count, 1)
        chall_update = mock_poll.call_args[0][0]
        self.assertEqual(len(list(six.iterkeys(chall_update))), 3)
        self.assertTrue("0" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["0"]), 1)
        self.assertTrue("1" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["1"]), 1)
        self.assertTrue("2" in list(six.iterkeys(chall_update)))
        self.assertEqual(len(chall_update["2"]), 1)

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)

        self.assertEqual(len(authzr), 3)

    def test_perform_failure(self):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)
        self.mock_auth.perform.side_effect = errors.AuthorizationError

        self.assertRaises(
            errors.AuthorizationError, self.handler.get_authorizations, ["0"])

    def test_no_domains(self):
        self.assertRaises(errors.AuthorizationError, self.handler.get_authorizations, [])

    @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges")
    def test_preferred_challenge_choice(self, mock_poll):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)

        mock_poll.side_effect = self._validate_all
        self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01)

        self.handler.pref_challs.extend((challenges.HTTP01.typ,
                                         challenges.DNS01.typ,))

        self.handler.get_authorizations(["0"])

        self.assertEqual(self.mock_auth.cleanup.call_count, 1)
        self.assertEqual(
            self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01")

    def test_preferred_challenges_not_supported(self):
        self.mock_net.request_domain_challenges.side_effect = functools.partial(
            gen_dom_authzr, challs=acme_util.CHALLENGES)
        self.handler.pref_challs.append(challenges.HTTP01.typ)
        self.assertRaises(
            errors.AuthorizationError, self.handler.get_authorizations, ["0"])

    def _validate_all(self, unused_1, unused_2):
        for dom in six.iterkeys(self.handler.authzr):
            azr = self.handler.authzr[dom]
            self.handler.authzr[dom] = acme_util.gen_authzr(
                messages.STATUS_VALID,
                dom,
                [challb.chall for challb in azr.body.challenges],
                [messages.STATUS_VALID] * len(azr.body.challenges),
                azr.body.combinations)