def setUp(self): from certbot.auth_handler import challb_to_achall from certbot.auth_handler import AuthHandler # Account and network are mocked... self.mock_net = mock.MagicMock() self.handler = AuthHandler(None, self.mock_net, mock.Mock(key="mock_key"), []) self.doms = ["0", "1", "2"] self.handler.authzr[self.doms[0]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[0], [acme_util.HTTP01, acme_util.TLSSNI01], [messages.STATUS_PENDING] * 2, False) self.handler.authzr[self.doms[1]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[1], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.handler.authzr[self.doms[2]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[2], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.chall_update = {} for dom in self.doms: self.chall_update[dom] = [ challb_to_achall(challb, mock.Mock(key="dummy_key"), dom) for challb in self.handler.authzr[dom].body.challenges ]
class ChallengeFactoryTest(unittest.TestCase): # pylint: disable=protected-access def setUp(self): from certbot.auth_handler import AuthHandler # Account is mocked... self.handler = AuthHandler(None, None, mock.Mock(key="mock_key"), []) self.authzr = acme_util.gen_authzr( messages.STATUS_PENDING, "test", acme_util.CHALLENGES, [messages.STATUS_PENDING] * 6, False) def test_all(self): achalls = self.handler._challenge_factory( self.authzr, range(0, len(acme_util.CHALLENGES))) self.assertEqual( [achall.chall for achall in achalls], acme_util.CHALLENGES) def test_one_tls_sni(self): achalls = self.handler._challenge_factory(self.authzr, [1]) self.assertEqual( [achall.chall for achall in achalls], [acme_util.TLSSNI01]) def test_unrecognized(self): authzr = acme_util.gen_authzr( messages.STATUS_PENDING, "test", [mock.Mock(chall="chall", typ="unrecognized")], [messages.STATUS_PENDING]) self.assertRaises( errors.Error, self.handler._challenge_factory, authzr, [0])
def setUp(self): from certbot.auth_handler import challb_to_achall from certbot.auth_handler import AuthHandler, AnnotatedAuthzr # Account and network are mocked... self.mock_net = mock.MagicMock() self.handler = AuthHandler(None, self.mock_net, mock.Mock(key="mock_key"), []) self.doms = ["0", "1", "2"] self.aauthzrs = [ AnnotatedAuthzr( acme_util.gen_authzr(messages.STATUS_PENDING, self.doms[0], [acme_util.HTTP01, acme_util.TLSSNI01], [messages.STATUS_PENDING] * 2, False), []), AnnotatedAuthzr( acme_util.gen_authzr(messages.STATUS_PENDING, self.doms[1], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), []), AnnotatedAuthzr( acme_util.gen_authzr(messages.STATUS_PENDING, self.doms[2], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False), []) ] self.chall_update = { } # type: Dict[int, achallenges.KeyAuthorizationAnnotatedChallenge] for i, aauthzr in enumerate(self.aauthzrs): self.chall_update[i] = [ challb_to_achall(challb, mock.Mock(key="dummy_key"), self.doms[i]) for challb in aauthzr.authzr.body.challenges ]
def setUp(self): from certbot.auth_handler import AuthHandler # Account is mocked... self.handler = AuthHandler(None, None, mock.Mock(key="mock_key"), []) self.authzr = acme_util.gen_authzr( messages.STATUS_PENDING, "test", acme_util.CHALLENGES, [messages.STATUS_PENDING] * 6, False)
def setUp(self): from certbot.auth_handler import challb_to_achall from certbot.auth_handler import AuthHandler # Account and network are mocked... self.mock_net = mock.MagicMock() self.handler = AuthHandler( None, self.mock_net, mock.Mock(key="mock_key"), []) self.doms = ["0", "1", "2"] self.handler.authzr[self.doms[0]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[0], [acme_util.HTTP01, acme_util.TLSSNI01], [messages.STATUS_PENDING] * 2, False) self.handler.authzr[self.doms[1]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[1], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.handler.authzr[self.doms[2]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[2], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.chall_update = {} for dom in self.doms: self.chall_update[dom] = [ challb_to_achall(challb, mock.Mock(key="dummy_key"), dom) for challb in self.handler.authzr[dom].body.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 setUp(self): from certbot.auth_handler import AuthHandler 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 = 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 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=le_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 setUp(self): from certbot.auth_handler import AuthHandler 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 = 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)
class HandleAuthorizationsTest(unittest.TestCase): # pylint: disable=too-many-public-methods """handle_authorizations test. This tests everything except for all functions under _poll_challenges. """ def setUp(self): from certbot.auth_handler import AuthHandler 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 = 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.mock_net.acme_version = 1 self.mock_net.retry_after.side_effect = acme_client.Client.retry_after self.handler = AuthHandler( self.mock_auth, self.mock_net, self.mock_account, []) logging.disable(logging.CRITICAL) def tearDown(self): logging.disable(logging.NOTSET) def _test_name1_tls_sni_01_1_common(self, combos): authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos) mock_order = mock.MagicMock(authorizations=[authzr]) self.mock_net.poll.side_effect = _gen_mock_on_poll(retry=1, wait_value=30) with mock.patch('certbot.auth_handler.time') as mock_time: authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(self.mock_net.poll.call_count, 2) # Because there is one retry self.assertEqual(mock_time.sleep.call_count, 2) # Retry-After header is 30 seconds, but at the time sleep is invoked, several # instructions are executed, and next pool is in less than 30 seconds. self.assertTrue(mock_time.sleep.call_args_list[1][0][0] <= 30) # However, assert that we did not took the default value of 3 seconds. self.assertTrue(mock_time.sleep.call_args_list[1][0][0] > 3) 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) def test_name1_tls_sni_01_1_acme_1(self): self._test_name1_tls_sni_01_1_common(combos=True) def test_name1_tls_sni_01_1_acme_2(self): self.mock_net.acme_version = 2 self._test_name1_tls_sni_01_1_common(combos=False) def test_name1_tls_sni_01_1_http_01_1_dns_1_acme_1(self): self.mock_net.poll.side_effect = _gen_mock_on_poll() self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01) self.mock_auth.get_chall_pref.return_value.append(challenges.DNS01) authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False) mock_order = mock.MagicMock(authorizations=[authzr]) authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 3) self.assertEqual(self.mock_net.poll.call_count, 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) def test_name1_tls_sni_01_1_http_01_1_dns_1_acme_2(self): self.mock_net.acme_version = 2 self.mock_net.poll.side_effect = _gen_mock_on_poll() self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01) self.mock_auth.get_chall_pref.return_value.append(challenges.DNS01) authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False) mock_order = mock.MagicMock(authorizations=[authzr]) authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(self.mock_net.poll.call_count, 1) self.assertEqual(self.mock_auth.cleanup.call_count, 1) cleaned_up_achalls = self.mock_auth.cleanup.call_args[0][0] self.assertEqual(len(cleaned_up_achalls), 1) self.assertEqual(cleaned_up_achalls[0].typ, "tls-sni-01") # Length of authorizations list self.assertEqual(len(authzr), 1) def _test_name3_tls_sni_01_3_common(self, combos): self.mock_net.request_domain_challenges.side_effect = functools.partial( gen_dom_authzr, challs=acme_util.CHALLENGES, combos=combos) authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES), gen_dom_authzr(domain="1", challs=acme_util.CHALLENGES), gen_dom_authzr(domain="2", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_net.poll.side_effect = _gen_mock_on_poll() authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 3) # Check poll call self.assertEqual(self.mock_net.poll.call_count, 3) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual(len(authzr), 3) def test_name3_tls_sni_01_3_common_acme_1(self): self._test_name3_tls_sni_01_3_common(combos=True) def test_name3_tls_sni_01_3_common_acme_2(self): self.mock_net.acme_version = 2 self._test_name3_tls_sni_01_3_common(combos=False) def test_debug_challenges(self): zope.component.provideUtility( mock.Mock(debug_challenges=True), interfaces.IConfig) authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_net.poll.side_effect = _gen_mock_on_poll() self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(self.mock_display.notification.call_count, 1) def test_perform_failure(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_auth.perform.side_effect = errors.AuthorizationError self.assertRaises( errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_max_retries_exceeded(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) # We will return STATUS_PENDING twice before returning STATUS_VALID. self.mock_net.poll.side_effect = _gen_mock_on_poll(retry=2) with self.assertRaises(errors.AuthorizationError) as error: # We retry only once, so retries will be exhausted before STATUS_VALID is returned. self.handler.handle_authorizations(mock_order, False, 1) self.assertTrue('All authorizations were not finalized by the CA.' in str(error.exception)) def test_no_domains(self): mock_order = mock.MagicMock(authorizations=[]) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def _test_preferred_challenge_choice_common(self, combos): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01) self.handler.pref_challs.extend((challenges.HTTP01.typ, challenges.DNS01.typ,)) self.mock_net.poll.side_effect = _gen_mock_on_poll() self.handler.handle_authorizations(mock_order) 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_challenge_choice_common_acme_1(self): self._test_preferred_challenge_choice_common(combos=True) def test_preferred_challenge_choice_common_acme_2(self): self.mock_net.acme_version = 2 self._test_preferred_challenge_choice_common(combos=False) def _test_preferred_challenges_not_supported_common(self, combos): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos)] mock_order = mock.MagicMock(authorizations=authzrs) self.handler.pref_challs.append(challenges.HTTP01.typ) self.assertRaises( errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_preferred_challenges_not_supported_acme_1(self): self._test_preferred_challenges_not_supported_common(combos=True) def test_preferred_challenges_not_supported_acme_2(self): self.mock_net.acme_version = 2 self._test_preferred_challenges_not_supported_common(combos=False) def test_dns_only_challenge_not_supported(self): authzrs = [gen_dom_authzr(domain="0", challs=[acme_util.DNS01])] mock_order = mock.MagicMock(authorizations=authzrs) self.assertRaises( errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_perform_error(self): self.mock_auth.perform.side_effect = errors.AuthorizationError authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=True) mock_order = mock.MagicMock(authorizations=[authzr]) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual( self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") def test_answer_error(self): self.mock_net.answer_challenge.side_effect = errors.AuthorizationError authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.assertRaises( errors.AuthorizationError, self.handler.handle_authorizations, mock_order) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual( self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") def test_incomplete_authzr_error(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_net.poll.side_effect = _gen_mock_on_poll(status=messages.STATUS_INVALID) with test_util.patch_get_utility(): with self.assertRaises(errors.AuthorizationError) as error: self.handler.handle_authorizations(mock_order, False) self.assertTrue('Some challenges have failed.' in str(error.exception)) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual( self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") def test_best_effort(self): def _conditional_mock_on_poll(authzr): """This mock will invalidate one authzr, and invalidate the other one""" valid_mock = _gen_mock_on_poll(messages.STATUS_VALID) invalid_mock = _gen_mock_on_poll(messages.STATUS_INVALID) if authzr.body.identifier.value == 'will-be-invalid': return invalid_mock(authzr) return valid_mock(authzr) # Two authzrs. Only one will be valid. authzrs = [gen_dom_authzr(domain="will-be-valid", challs=acme_util.CHALLENGES), gen_dom_authzr(domain="will-be-invalid", challs=acme_util.CHALLENGES)] self.mock_net.poll.side_effect = _conditional_mock_on_poll mock_order = mock.MagicMock(authorizations=authzrs) with mock.patch('certbot.auth_handler._report_failed_authzrs') as mock_report: valid_authzr = self.handler.handle_authorizations(mock_order, True) # Because best_effort=True, we did not blow up. Instead ... self.assertEqual(len(valid_authzr), 1) # ... the valid authzr has been processed self.assertEqual(mock_report.call_count, 1) # ... the invalid authzr has been reported self.mock_net.poll.side_effect = _gen_mock_on_poll(status=messages.STATUS_INVALID) with test_util.patch_get_utility(): with self.assertRaises(errors.AuthorizationError) as error: self.handler.handle_authorizations(mock_order, True) # Despite best_effort=True, process will fail because no authzr is valid. self.assertTrue('All challenges have failed.' in str(error.exception)) def test_validated_challenge_not_rerun(self): # With pending challenge, we expect the challenge to be tried, and fail. authzr = acme_util.gen_authzr( messages.STATUS_PENDING, "0", [acme_util.HTTP01], [messages.STATUS_PENDING], False) mock_order = mock.MagicMock(authorizations=[authzr]) self.assertRaises( errors.AuthorizationError, self.handler.handle_authorizations, mock_order) # With validated challenge; we expect the challenge not be tried again, and succeed. authzr = acme_util.gen_authzr( messages.STATUS_VALID, "0", [acme_util.HTTP01], [messages.STATUS_VALID], False) mock_order = mock.MagicMock(authorizations=[authzr]) self.handler.handle_authorizations(mock_order) @mock.patch("certbot.auth_handler.logger") def test_tls_sni_logs(self, logger): self._test_name1_tls_sni_01_1_common(combos=True) self.assertTrue("deprecated" in logger.warning.call_args[0][0])
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)
class PollChallengesTest(unittest.TestCase): # pylint: disable=protected-access """Test poll challenges.""" def setUp(self): from certbot.auth_handler import challb_to_achall from certbot.auth_handler import AuthHandler # Account and network are mocked... self.mock_net = mock.MagicMock() self.handler = AuthHandler( None, self.mock_net, mock.Mock(key="mock_key"), []) self.doms = ["0", "1", "2"] self.handler.authzr[self.doms[0]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[0], [acme_util.HTTP01, acme_util.TLSSNI01], [messages.STATUS_PENDING] * 2, False) self.handler.authzr[self.doms[1]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[1], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.handler.authzr[self.doms[2]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[2], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.chall_update = {} for dom in self.doms: self.chall_update[dom] = [ challb_to_achall(challb, mock.Mock(key="dummy_key"), dom) for challb in self.handler.authzr[dom].body.challenges] @mock.patch("certbot.auth_handler.time") def test_poll_challenges(self, unused_mock_time): self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid self.handler._poll_challenges(self.chall_update, False) for authzr in self.handler.authzr.values(): self.assertEqual(authzr.body.status, messages.STATUS_VALID) @mock.patch("certbot.auth_handler.time") def test_poll_challenges_failure_best_effort(self, unused_mock_time): self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid self.handler._poll_challenges(self.chall_update, True) for authzr in self.handler.authzr.values(): self.assertEqual(authzr.body.status, messages.STATUS_PENDING) @mock.patch("certbot.auth_handler.time") @test_util.patch_get_utility() def test_poll_challenges_failure(self, unused_mock_time, unused_mock_zope): self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid self.assertRaises( errors.AuthorizationError, self.handler._poll_challenges, self.chall_update, False) @mock.patch("certbot.auth_handler.time") def test_unable_to_find_challenge_status(self, unused_mock_time): from certbot.auth_handler import challb_to_achall self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid self.chall_update[self.doms[0]].append( challb_to_achall(acme_util.DNS01_P, "key", self.doms[0])) self.assertRaises( errors.AuthorizationError, self.handler._poll_challenges, self.chall_update, False) def test_verify_authzr_failure(self): self.assertRaises( errors.AuthorizationError, self.handler.verify_authzr_complete) def _mock_poll_solve_one_valid(self, authzr): # Pending here because my dummy script won't change the full status. # Basically it didn't raise an error and it stopped earlier than # Making all challenges invalid which would make mock_poll_solve_one # change authzr to invalid return self._mock_poll_solve_one_chall(authzr, messages.STATUS_VALID) def _mock_poll_solve_one_invalid(self, authzr): return self._mock_poll_solve_one_chall(authzr, messages.STATUS_INVALID) def _mock_poll_solve_one_chall(self, authzr, desired_status): # pylint: disable=no-self-use """Dummy method that solves one chall at a time to desired_status. When all are solved.. it changes authzr.status to desired_status """ new_challbs = authzr.body.challenges for challb in authzr.body.challenges: if challb.status != desired_status: new_challbs = tuple( challb_temp if challb_temp != challb else acme_util.chall_to_challb(challb.chall, desired_status) for challb_temp in authzr.body.challenges ) break if all(test_challb.status == desired_status for test_challb in new_challbs): status_ = desired_status else: status_ = authzr.body.status new_authzr = messages.AuthorizationResource( uri=authzr.uri, new_cert_uri=authzr.new_cert_uri, body=messages.Authorization( identifier=authzr.body.identifier, challenges=new_challbs, combinations=authzr.body.combinations, status=status_, ), ) return (new_authzr, "response")
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)
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)
class PollChallengesTest(unittest.TestCase): # pylint: disable=protected-access """Test poll challenges.""" def setUp(self): from certbot.auth_handler import challb_to_achall from certbot.auth_handler import AuthHandler # Account and network are mocked... self.mock_net = mock.MagicMock() self.handler = AuthHandler(None, self.mock_net, mock.Mock(key="mock_key"), []) self.doms = ["0", "1", "2"] self.handler.authzr[self.doms[0]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[0], [acme_util.HTTP01, acme_util.TLSSNI01], [messages.STATUS_PENDING] * 2, False) self.handler.authzr[self.doms[1]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[1], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.handler.authzr[self.doms[2]] = acme_util.gen_authzr( messages.STATUS_PENDING, self.doms[2], acme_util.CHALLENGES, [messages.STATUS_PENDING] * 3, False) self.chall_update = {} for dom in self.doms: self.chall_update[dom] = [ challb_to_achall(challb, mock.Mock(key="dummy_key"), dom) for challb in self.handler.authzr[dom].body.challenges ] @mock.patch("certbot.auth_handler.time") def test_poll_challenges(self, unused_mock_time): self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid self.handler._poll_challenges(self.chall_update, False) for authzr in self.handler.authzr.values(): self.assertEqual(authzr.body.status, messages.STATUS_VALID) @mock.patch("certbot.auth_handler.time") def test_poll_challenges_failure_best_effort(self, unused_mock_time): self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid self.handler._poll_challenges(self.chall_update, True) for authzr in self.handler.authzr.values(): self.assertEqual(authzr.body.status, messages.STATUS_PENDING) @mock.patch("certbot.auth_handler.time") @test_util.patch_get_utility() def test_poll_challenges_failure(self, unused_mock_time, unused_mock_zope): self.mock_net.poll.side_effect = self._mock_poll_solve_one_invalid self.assertRaises(errors.AuthorizationError, self.handler._poll_challenges, self.chall_update, False) @mock.patch("certbot.auth_handler.time") def test_unable_to_find_challenge_status(self, unused_mock_time): from certbot.auth_handler import challb_to_achall self.mock_net.poll.side_effect = self._mock_poll_solve_one_valid self.chall_update[self.doms[0]].append( challb_to_achall(acme_util.DNS01_P, "key", self.doms[0])) self.assertRaises(errors.AuthorizationError, self.handler._poll_challenges, self.chall_update, False) def test_verify_authzr_failure(self): self.assertRaises(errors.AuthorizationError, self.handler.verify_authzr_complete) def _mock_poll_solve_one_valid(self, authzr): # Pending here because my dummy script won't change the full status. # Basically it didn't raise an error and it stopped earlier than # Making all challenges invalid which would make mock_poll_solve_one # change authzr to invalid return self._mock_poll_solve_one_chall(authzr, messages.STATUS_VALID) def _mock_poll_solve_one_invalid(self, authzr): return self._mock_poll_solve_one_chall(authzr, messages.STATUS_INVALID) def _mock_poll_solve_one_chall(self, authzr, desired_status): # pylint: disable=no-self-use """Dummy method that solves one chall at a time to desired_status. When all are solved.. it changes authzr.status to desired_status """ new_challbs = authzr.body.challenges for challb in authzr.body.challenges: if challb.status != desired_status: new_challbs = tuple( challb_temp if challb_temp != challb else acme_util. chall_to_challb(challb.chall, desired_status) for challb_temp in authzr.body.challenges) break if all(test_challb.status == desired_status for test_challb in new_challbs): status_ = desired_status else: status_ = authzr.body.status new_authzr = messages.AuthorizationResource( uri=authzr.uri, body=messages.Authorization( identifier=authzr.body.identifier, challenges=new_challbs, combinations=authzr.body.combinations, status=status_, ), ) return new_authzr, "response"
class HandleAuthorizationsTest(unittest.TestCase): """handle_authorizations test. This tests everything except for all functions under _poll_challenges. """ def setUp(self): from certbot.auth_handler import AuthHandler 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 = 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.mock_net.acme_version = 1 self.handler = AuthHandler(self.mock_auth, self.mock_net, self.mock_account, []) logging.disable(logging.CRITICAL) def tearDown(self): logging.disable(logging.NOTSET) def _test_name1_tls_sni_01_1_common(self, combos): authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos) mock_order = mock.MagicMock(authorizations=[authzr]) with mock.patch("certbot.auth_handler.AuthHandler._poll_challenges" ) as mock_poll: mock_poll.side_effect = self._validate_all authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(mock_poll.call_count, 1) chall_update = mock_poll.call_args[0][1] 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) def test_name1_tls_sni_01_1_acme_1(self): self._test_name1_tls_sni_01_1_common(combos=True) def test_name1_tls_sni_01_1_acme_2(self): self.mock_net.acme_version = 2 self._test_name1_tls_sni_01_1_common(combos=False) @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges") def test_name1_tls_sni_01_1_http_01_1_dns_1_acme_1(self, mock_poll): 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 = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False) mock_order = mock.MagicMock(authorizations=[authzr]) authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 3) self.assertEqual(mock_poll.call_count, 1) chall_update = mock_poll.call_args[0][1] 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_name1_tls_sni_01_1_http_01_1_dns_1_acme_2(self, mock_poll): self.mock_net.acme_version = 2 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 = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=False) mock_order = mock.MagicMock(authorizations=[authzr]) authzr = self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(mock_poll.call_count, 1) chall_update = mock_poll.call_args[0][1] self.assertEqual(list(six.iterkeys(chall_update)), [0]) self.assertEqual(len(chall_update.values()), 1) self.assertEqual(self.mock_auth.cleanup.call_count, 1) cleaned_up_achalls = self.mock_auth.cleanup.call_args[0][0] self.assertEqual(len(cleaned_up_achalls), 1) self.assertEqual(cleaned_up_achalls[0].typ, "tls-sni-01") # Length of authorizations list self.assertEqual(len(authzr), 1) def _test_name3_tls_sni_01_3_common(self, combos): self.mock_net.request_domain_challenges.side_effect = functools.partial( gen_dom_authzr, challs=acme_util.CHALLENGES, combos=combos) authzrs = [ gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES), gen_dom_authzr(domain="1", challs=acme_util.CHALLENGES), gen_dom_authzr(domain="2", challs=acme_util.CHALLENGES) ] mock_order = mock.MagicMock(authorizations=authzrs) with mock.patch("certbot.auth_handler.AuthHandler._poll_challenges" ) as mock_poll: mock_poll.side_effect = self._validate_all authzr = self.handler.handle_authorizations(mock_order) 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][1] 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_name3_tls_sni_01_3_common_acme_1(self): self._test_name3_tls_sni_01_3_common(combos=True) def test_name3_tls_sni_01_3_common_acme_2(self): self.mock_net.acme_version = 2 self._test_name3_tls_sni_01_3_common(combos=False) @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) authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) mock_poll.side_effect = self._validate_all self.handler.handle_authorizations(mock_order) self.assertEqual(self.mock_net.answer_challenge.call_count, 1) self.assertEqual(self.mock_display.notification.call_count, 1) def test_perform_failure(self): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_auth.perform.side_effect = errors.AuthorizationError self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_no_domains(self): mock_order = mock.MagicMock(authorizations=[]) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def _test_preferred_challenge_choice_common(self, combos): authzrs = [ gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos) ] mock_order = mock.MagicMock(authorizations=authzrs) self.mock_auth.get_chall_pref.return_value.append(challenges.HTTP01) self.handler.pref_challs.extend(( challenges.HTTP01.typ, challenges.DNS01.typ, )) with mock.patch("certbot.auth_handler.AuthHandler._poll_challenges" ) as mock_poll: mock_poll.side_effect = self._validate_all self.handler.handle_authorizations(mock_order) 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_challenge_choice_common_acme_1(self): self._test_preferred_challenge_choice_common(combos=True) def test_preferred_challenge_choice_common_acme_2(self): self.mock_net.acme_version = 2 self._test_preferred_challenge_choice_common(combos=False) def _test_preferred_challenges_not_supported_common(self, combos): authzrs = [ gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=combos) ] mock_order = mock.MagicMock(authorizations=authzrs) self.handler.pref_challs.append(challenges.HTTP01.typ) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_preferred_challenges_not_supported_acme_1(self): self._test_preferred_challenges_not_supported_common(combos=True) def test_preferred_challenges_not_supported_acme_2(self): self.mock_net.acme_version = 2 self._test_preferred_challenges_not_supported_common(combos=False) def test_dns_only_challenge_not_supported(self): authzrs = [gen_dom_authzr(domain="0", challs=[acme_util.DNS01])] mock_order = mock.MagicMock(authorizations=authzrs) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) def test_perform_error(self): self.mock_auth.perform.side_effect = errors.AuthorizationError authzr = gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES, combos=True) mock_order = mock.MagicMock(authorizations=[authzr]) self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") @mock.patch("certbot.auth_handler.AuthHandler._respond") def test_respond_error(self, mock_respond): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) mock_respond.side_effect = errors.AuthorizationError self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") @mock.patch("certbot.auth_handler.AuthHandler._poll_challenges") @mock.patch("certbot.auth_handler.AuthHandler.verify_authzr_complete") def test_incomplete_authzr_error(self, mock_verify, mock_poll): authzrs = [gen_dom_authzr(domain="0", challs=acme_util.CHALLENGES)] mock_order = mock.MagicMock(authorizations=authzrs) mock_verify.side_effect = errors.AuthorizationError mock_poll.side_effect = self._validate_all self.assertRaises(errors.AuthorizationError, self.handler.handle_authorizations, mock_order) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ, "tls-sni-01") def _validate_all(self, aauthzrs, unused_1, unused_2): for i, aauthzr in enumerate(aauthzrs): azr = aauthzr.authzr updated_azr = acme_util.gen_authzr( messages.STATUS_VALID, azr.body.identifier.value, [challb.chall for challb in azr.body.challenges], [messages.STATUS_VALID] * len(azr.body.challenges), azr.body.combinations) aauthzrs[i] = type(aauthzr)(updated_azr, aauthzr.achalls)
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)