def setUp(self): super().setUp() get_display_patch = test_util.patch_display_util() self.mock_get_display = get_display_patch.start() self.addCleanup(get_display_patch.stop) 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, 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._internal.plugins.manual import Authenticator self.auth = Authenticator(self.config, name='manual')
def _test_error(self, enhance_error=False, restart_error=False): self.config.redirect = True with mock.patch('certbot._internal.client.logger') as mock_logger, \ test_util.patch_display_util() as mock_gu: self.assertRaises( errors.PluginError, self._test_with_all_supported) if enhance_error: self.assertEqual(mock_logger.error.call_count, 1) self.assertEqual('Unable to set the %s enhancement for %s.', mock_logger.error.call_args_list[0][0][0]) if restart_error: mock_logger.critical.assert_called_with( 'Rolling back to previous server configuration...')
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_display_util(): with self.assertRaises(errors.AuthorizationError) as error: self.handler.handle_authorizations(mock_order, self.mock_config, False) self.assertIn('Some challenges have failed.', str(error.exception)) self.assertEqual(self.mock_auth.cleanup.call_count, 1) self.assertEqual(self.mock_auth.cleanup.call_args[0][0][0].typ, "http-01")
def _help_output(self, args): "Run a command, and return the output string for scrutiny" output = io.StringIO() def write_msg(message, *args, **kwargs): # pylint: disable=missing-docstring,unused-argument output.write(message) with mock.patch('certbot._internal.main.sys.stdout', new=output): with test_util.patch_display_util() as mock_get_utility: mock_get_utility().notification.side_effect = write_msg with mock.patch('certbot._internal.main.sys.stderr'): self.assertRaises(SystemExit, self._unmocked_parse, args, output) return output.getvalue()
def test_obtain_certificate_dry_run_authz_deactivations_failed( self, mock_acme_crypto, mock_crypto, mock_log): from acme import messages csr = util.CSR(form="pem", file=None, data=CSR_SAN) mock_acme_crypto.make_csr.return_value = CSR_SAN mock_crypto.make_key.return_value = mock.sentinel.key_pem key = util.Key(file=None, pem=mock.sentinel.key_pem) self._set_mock_from_fullchain( mock_crypto.cert_and_chain_from_fullchain) self._mock_obtain_certificate() self.client.config.dry_run = True # Two authzs that are already valid and should get deactivated (dry run) authzrs = self._authzr_from_domains(["example.com", "www.example.com"]) for authzr in authzrs: authzr.body.status = messages.STATUS_VALID # One deactivation succeeds, one fails auth_handler = self.client.auth_handler auth_handler.deactivate_valid_authorizations.return_value = ([ authzrs[0] ], [authzrs[1]]) # Certificate should get issued despite one failed deactivation self.eg_order.authorizations = authzrs self.client.auth_handler.handle_authorizations.return_value = authzrs with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) self.assertEqual(result, (mock.sentinel.cert, mock.sentinel.chain, key, csr)) self._check_obtain_certificate(1) # Deactivation success/failure should have been handled properly self.assertEqual( auth_handler.deactivate_valid_authorizations.call_count, 1, "Deactivate authorizations should be called") self.assertEqual( self.acme.new_order.call_count, 2, "Order should be recreated due to successfully deactivated authorizations" ) mock_log.warning.assert_called_with( "Certbot was unable to obtain fresh authorizations for" " every domain. The dry run will continue, but results" " may not be accurate.")
def _test_obtain_certificate_common(self, key, csr, authzr_ret=None, auth_count=1): self._mock_obtain_certificate() # return_value is essentially set to (None, None) in # _mock_obtain_certificate(), which breaks this test. # Thus fixed by the next line. authzr = authzr_ret or self._authzr_from_domains(self.eg_domains) self.eg_order.authorizations = authzr self.client.auth_handler.handle_authorizations.return_value = authzr with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) self.assertEqual( result, (mock.sentinel.cert, mock.sentinel.chain, key, csr)) self._check_obtain_certificate(auth_count)
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._internal.auth_handler.AuthHandler._report_failed_authzrs') \ as mock_report: valid_authzr = self.handler.handle_authorizations( mock_order, self.mock_config, 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_display_util(): with self.assertRaises(errors.AuthorizationError) as error: self.handler.handle_authorizations(mock_order, self.mock_config, True) # Despite best_effort=True, process will fail because no authzr is valid. self.assertIn('All challenges have failed.', str(error.exception))
def test_deploy_cert_enable_new_vhost(self): # Create ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0]) self.config.parser.modules["ssl_module"] = None self.config.parser.modules["mod_ssl.c"] = None self.assertFalse(ssl_vhost.enabled) with certbot_util.patch_display_util(): self.config.deploy_cert("encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") self.assertTrue(ssl_vhost.enabled) # Make sure that we don't error out if symlink already exists ssl_vhost.enabled = False self.assertFalse(ssl_vhost.enabled) self.config.deploy_cert("encryption-example.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") self.assertTrue(ssl_vhost.enabled)
def test_deploy_cert_newssl(self): self.config = util.get_apache_configurator(self.config_path, self.vhost_path, self.config_dir, self.work_dir, version=(2, 4, 16)) self.config = self.mock_deploy_cert(self.config) self.config.parser.modules["ssl_module"] = None self.config.parser.modules["mod_ssl.c"] = None # Get the default 443 vhost self.config.assoc["random.demo"] = self.vh_truth[1] with certbot_util.patch_display_util(): self.config.deploy_cert("random.demo", "example/cert.pem", "example/key.pem", "example/cert_chain.pem", "example/fullchain.pem") self.config.save() # Verify ssl_module was enabled. self.assertTrue(self.vh_truth[1].enabled) self.assertTrue("ssl_module" in self.config.parser.modules) loc_cert = self.config.parser.find_dir("sslcertificatefile", "example/fullchain.pem", self.vh_truth[1].path) loc_key = self.config.parser.find_dir("sslcertificateKeyfile", "example/key.pem", self.vh_truth[1].path) # Verify one directive was found in the correct file self.assertEqual(len(loc_cert), 1) self.assertEqual(apache_util.get_file_path(loc_cert[0]), self.vh_truth[1].filep) self.assertEqual(len(loc_key), 1) self.assertEqual(apache_util.get_file_path(loc_key[0]), self.vh_truth[1].filep)
def test_obtain_certificate_get_order_partial_success(self, mock_remove, mock_crypto_util): from acme import messages csr = util.CSR(form="pem", file=mock.sentinel.csr_file, data=CSR_SAN) key = util.CSR(form="pem", file=mock.sentinel.key_file, data=CSR_SAN) mock_crypto_util.generate_csr.return_value = csr mock_crypto_util.generate_key.return_value = key self._set_mock_from_fullchain(mock_crypto_util.cert_and_chain_from_fullchain) self._mock_obtain_certificate() authzr = self._authzr_from_domains(self.eg_domains) self.eg_order.authorizations = authzr self.client.auth_handler.handle_authorizations.return_value = authzr identifier = messages.Identifier(typ=messages.IDENTIFIER_FQDN, value='example.com') subproblem = messages.Error.with_code('caa', detail='bar', title='title', identifier=identifier) error_with_subproblems = messages.Error.with_code('malformed', detail='foo', title='title', subproblems=[subproblem]) self.client.acme.new_order.side_effect = [error_with_subproblems, mock.DEFAULT] self.config.allow_subset_of_names = True with test_util.patch_display_util(): result = self.client.obtain_certificate(self.eg_domains) self.assertEqual( result, (mock.sentinel.cert, mock.sentinel.chain, key, csr)) self.assertEqual(self.client.auth_handler.handle_authorizations.call_count, 1) self.assertEqual(self.acme.new_order.call_count, 2) successful_domains = [d for d in self.eg_domains if d != 'example.com'] self.assertEqual(mock_crypto_util.generate_key.call_count, 2) mock_crypto_util.generate_csr.assert_has_calls([ mock.call(key, self.eg_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions), mock.call(key, successful_domains, self.config.csr_dir, self.config.must_staple, self.config.strict_permissions)]) self.assertEqual(mock_remove.call_count, 2) self.assertEqual(mock_crypto_util.cert_and_chain_from_fullchain.call_count, 1)
def setUp(self): get_utility_patch = test_util.patch_display_util() self.mock_get_utility = get_utility_patch.start() self.addCleanup(get_utility_patch.stop) self.config = mock.MagicMock() self.config.certname = None
def parse(*args, **kwargs): """Mocks zope.component.getUtility and calls _unmocked_parse.""" with test_util.patch_display_util(): return ParseTest._unmocked_parse(*args, **kwargs)
def _call_set_by_cli(var, args, verb): with mock.patch('certbot._internal.cli.helpful_parser') as mock_parser: with test_util.patch_display_util(): mock_parser.args = args mock_parser.verb = verb return cli.set_by_cli(var)