def test_no_match(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "other.com.conf" from certbot import cert_manager self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), None) self.assertTrue(mock_make_or_verify_dir.called)
def test_no_renewal_file(self, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.side_effect = errors.CertStorageError() from certbot import cert_manager self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), None) self.assertTrue(mock_make_or_verify_dir.called)
def _find_lineage_for_domains_and_certname(config, domains, certname): """Find appropriate lineage based on given domains and/or certname. :returns: Two-element tuple containing desired new-certificate behavior as a string token ("reinstall", "renew", or "newcert"), plus either a RenewableCert instance or None if renewal shouldn't occur. :raises .Error: If the user would like to rerun the client again. """ if not certname: return _find_lineage_for_domains(config, domains) else: lineage = cert_manager.lineage_for_certname(config, certname) if lineage: if domains: if set(cert_manager.domains_for_certname(config, certname)) != set(domains): _ask_user_to_confirm_new_names(config, domains, certname, lineage.names()) # raises if no return "renew", lineage # unnecessarily specified domains or no domains specified return _handle_identical_cert_request(config, lineage) else: if domains: return "newcert", None else: raise errors.ConfigurationError("No certificate with name {0} found. " "Use -d to specify domains, or run certbot --certificates to see " "possible certificate names.".format(certname))
def test_rename_cert(self, mock_check, unused_get_utility): mock_check.return_value = True self._call(self.config) from certbot import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) self.assertTrue(updated_lineage is not None) self.assertEqual(updated_lineage.lineagename, self.config.new_certname)
def _find_lineage_for_domains_and_certname(config, domains, certname): """Find appropriate lineage based on given domains and/or certname. :returns: Two-element tuple containing desired new-certificate behavior as a string token ("reinstall", "renew", or "newcert"), plus either a RenewableCert instance or None if renewal shouldn't occur. :raises .Error: If the user would like to rerun the client again. """ if not certname: return _find_lineage_for_domains(config, domains) else: lineage = cert_manager.lineage_for_certname(config, certname) if lineage: if domains: if set(cert_manager.domains_for_certname( config, certname)) != set(domains): _ask_user_to_confirm_new_names( config, domains, certname, lineage.names()) # raises if no return "renew", lineage # unnecessarily specified domains or no domains specified return _handle_identical_cert_request(config, lineage) else: if domains: return "newcert", None else: raise errors.ConfigurationError( "No certificate with name {0} found. " "Use -d to specify domains, or run certbot --certificates to see " "possible certificate names.".format(certname))
def install(config, plugins): """Install a previously obtained cert in a server. :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None """ # XXX: Update for renewer/RenewableCert # FIXME: be consistent about whether errors are raised or returned from # this function ... try: installer, _ = plug_sel.choose_configurator_plugins(config, plugins, "install") except errors.PluginSelectionError as e: return str(e) custom_cert = (config.key_path and config.cert_path) if not config.certname and not custom_cert: certname_question = "Which certificate would you like to install?" config.certname = cert_manager.get_certnames( config, "install", allow_multiple=False, custom_prompt=certname_question)[0] if not enhancements.are_supported(config, installer): raise errors.NotSupportedError("One ore more of the requested enhancements " "are not supported by the selected installer") # If cert-path is defined, populate missing (ie. not overridden) values. # Unfortunately this can't be done in argument parser, as certificate # manager needs the access to renewal directory paths if config.certname: config = _populate_from_certname(config) elif enhancements.are_requested(config): # Preflight config check raise errors.ConfigurationError("One or more of the requested enhancements " "require --cert-name to be provided") if config.key_path and config.cert_path: _check_certificate_and_key(config) domains, _ = _find_domains_or_certname(config, installer) le_client = _init_le_client(config, authenticator=None, installer=installer) _install_cert(config, le_client, domains) else: raise errors.ConfigurationError("Path to certificate or key was not defined. " "If your certificate is managed by Certbot, please use --cert-name " "to define which certificate you would like to install.") if enhancements.are_requested(config): # In the case where we don't have certname, we have errored out already lineage = cert_manager.lineage_for_certname(config, config.certname) enhancements.enable(lineage, domains, installer, config) return None
def test_no_match(self, mock_renewable_cert, mock_renewal_conf_files, mock_make_or_verify_dir, mock_renewer_config): mock_renewal_conf_files.return_value = ["somefile.conf"] mock_match = mock.Mock(lineagename="other.com") mock_renewable_cert.return_value = mock_match from certbot import cert_manager self.assertEqual(cert_manager.lineage_for_certname(None, "example.com"), None) self.assertTrue(mock_make_or_verify_dir.called) self.assertTrue(mock_renewer_config)
def test_found_match(self, mock_renewable_cert, mock_renewal_conf_file, mock_make_or_verify_dir): mock_renewal_conf_file.return_value = "somefile.conf" mock_match = mock.Mock(lineagename="example.com") mock_renewable_cert.return_value = mock_match from certbot import cert_manager self.assertEqual(cert_manager.lineage_for_certname(self.config, "example.com"), mock_match) self.assertTrue(mock_make_or_verify_dir.called)
def enhance(config, plugins): """Add security enhancements to existing configuration :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None """ supported_enhancements = ["hsts", "redirect", "uir", "staple"] # Check that at least one enhancement was requested on command line oldstyle_enh = any([getattr(config, enh) for enh in supported_enhancements]) if not enhancements.are_requested(config) and not oldstyle_enh: msg = ("Please specify one or more enhancement types to configure. To list " "the available enhancement types, run:\n\n%s --help enhance\n") logger.warning(msg, sys.argv[0]) raise errors.MisconfigurationError("No enhancements requested, exiting.") try: installer, _ = plug_sel.choose_configurator_plugins(config, plugins, "enhance") except errors.PluginSelectionError as e: return str(e) if not enhancements.are_supported(config, installer): raise errors.NotSupportedError("One ore more of the requested enhancements " "are not supported by the selected installer") certname_question = ("Which certificate would you like to use to enhance " "your configuration?") config.certname = cert_manager.get_certnames( config, "enhance", allow_multiple=False, custom_prompt=certname_question)[0] cert_domains = cert_manager.domains_for_certname(config, config.certname) if config.noninteractive_mode: domains = cert_domains else: domain_question = ("Which domain names would you like to enable the " "selected enhancements for?") domains = display_ops.choose_values(cert_domains, domain_question) if not domains: raise errors.Error("User cancelled the domain selection. No domains " "defined, exiting.") lineage = cert_manager.lineage_for_certname(config, config.certname) if not config.chain_path: config.chain_path = lineage.chain_path if oldstyle_enh: le_client = _init_le_client(config, authenticator=None, installer=installer) le_client.enhance_config(domains, config.chain_path, ask_redirect=False) if enhancements.are_requested(config): enhancements.enable(lineage, domains, installer, config) return None
def install(config, plugins): """Install a previously obtained cert in a server. :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None """ # XXX: Update for renewer/RenewableCert # FIXME: be consistent about whether errors are raised or returned from # this function ... try: installer, _ = plug_sel.choose_configurator_plugins(config, plugins, "install") except errors.PluginSelectionError as e: return str(e) custom_cert = (config.key_path and config.cert_path) if not config.certname and not custom_cert: certname_question = "Which certificate would you like to install?" config.certname = cert_manager.get_certnames( config, "install", allow_multiple=False, custom_prompt=certname_question)[0] if not enhancements.are_supported(config, installer): raise errors.NotSupportedError("One ore more of the requested enhancements " "are not supported by the selected installer") # If cert-path is defined, populate missing (ie. not overridden) values. # Unfortunately this can't be done in argument parser, as certificate # manager needs the access to renewal directory paths if config.certname: config = _populate_from_certname(config) elif enhancements.are_requested(config): # Preflight config check raise errors.ConfigurationError("One or more of the requested enhancements " "require --cert-name to be provided") if config.key_path and config.cert_path: _check_certificate_and_key(config) domains, _ = _find_domains_or_certname(config, installer) le_client = _init_le_client(config, authenticator=None, installer=installer) _install_cert(config, le_client, domains) else: raise errors.ConfigurationError("Path to certificate or key was not defined. " "If your certificate is managed by Certbot, please use --cert-name " "to define which certificate you would like to install.") if enhancements.are_requested(config): # In the case where we don't have certname, we have errored out already lineage = cert_manager.lineage_for_certname(config, config.certname) enhancements.enable(lineage, domains, installer, config)
def test_rename_cert_interactive_certname(self, mock_check, mock_get_utility): mock_check.return_value = True self.config.certname = None util_mock = mock_get_utility() util_mock.menu.return_value = (display_util.OK, 0) self._call(self.config) from certbot import cert_manager updated_lineage = cert_manager.lineage_for_certname(self.config, self.config.new_certname) self.assertTrue(updated_lineage is not None) self.assertEqual(updated_lineage.lineagename, self.config.new_certname)
def enhance(config, plugins): """Add security enhancements to existing configuration :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None """ supported_enhancements = ["hsts", "redirect", "uir", "staple"] # Check that at least one enhancement was requested on command line oldstyle_enh = any([getattr(config, enh) for enh in supported_enhancements]) if not enhancements.are_requested(config) and not oldstyle_enh: msg = ("Please specify one or more enhancement types to configure. To list " "the available enhancement types, run:\n\n%s --help enhance\n") logger.warning(msg, sys.argv[0]) raise errors.MisconfigurationError("No enhancements requested, exiting.") try: installer, _ = plug_sel.choose_configurator_plugins(config, plugins, "enhance") except errors.PluginSelectionError as e: return str(e) if not enhancements.are_supported(config, installer): raise errors.NotSupportedError("One ore more of the requested enhancements " "are not supported by the selected installer") certname_question = ("Which certificate would you like to use to enhance " "your configuration?") config.certname = cert_manager.get_certnames( config, "enhance", allow_multiple=False, custom_prompt=certname_question)[0] cert_domains = cert_manager.domains_for_certname(config, config.certname) if config.noninteractive_mode: domains = cert_domains else: domain_question = ("Which domain names would you like to enable the " "selected enhancements for?") domains = display_ops.choose_values(cert_domains, domain_question) if not domains: raise errors.Error("User cancelled the domain selection. No domains " "defined, exiting.") lineage = cert_manager.lineage_for_certname(config, config.certname) if not config.chain_path: config.chain_path = lineage.chain_path if oldstyle_enh: le_client = _init_le_client(config, authenticator=None, installer=installer) le_client.enhance_config(domains, config.chain_path, ask_redirect=False) if enhancements.are_requested(config): enhancements.enable(lineage, domains, installer, config)
def test_rename_cert(self, mock_rv, mock_check, unused_get_utility, unused_update_symlinks): # Mock relevant_values() to claim that all values are relevant here # (to avoid instantiating parser) mock_rv.side_effect = lambda x: x mock_check.return_value = True mock_config = self.mock_config self._call(mock_config) from certbot import cert_manager updated_lineage = cert_manager.lineage_for_certname(mock_config, mock_config.new_certname) self.assertTrue(updated_lineage is not None) self.assertEqual(updated_lineage.lineagename, mock_config.new_certname)
def _populate_from_certname(config): """Helper function for install to populate missing config values from lineage defined by --cert-name.""" lineage = cert_manager.lineage_for_certname(config, config.certname) if not lineage: return config if not config.key_path: config.namespace.key_path = lineage.key_path if not config.cert_path: config.namespace.cert_path = lineage.cert_path if not config.chain_path: config.namespace.chain_path = lineage.chain_path if not config.fullchain_path: config.namespace.fullchain_path = lineage.fullchain_path return config
def test_rename_cert_interactive_certname(self, mock_rv, mock_check, mock_get_utility, unused_update_symlinks): # python 3.4 and 3.5 order things differently, so remove other.com for this test os.remove(self.configs["other.com"].filename) mock_rv.side_effect = lambda x: x mock_check.return_value = True mock_config = self.mock_config mock_config.certname = None util_mock = mock.Mock() util_mock.menu.return_value = (display_util.OK, 0) mock_get_utility.return_value = util_mock self._call(mock_config) from certbot import cert_manager updated_lineage = cert_manager.lineage_for_certname(mock_config, mock_config.new_certname) self.assertTrue(updated_lineage is not None) self.assertEqual(updated_lineage.lineagename, mock_config.new_certname)