From f169e7374bedf11a77c860d522f7e9b7eaad0824 Mon Sep 17 00:00:00 2001 From: Joona Hoikkala Date: Wed, 27 Jun 2018 21:35:01 +0300 Subject: [PATCH] Interactive certificate selection with install verb (#6097) If either --cert-name or both --key-path and --cert-path (in which case the user requests installation for a certificate not managed by Certbot) are not provided, prompt the user with managed certificates and let them choose. Fixes: #5824 --- certbot/main.py | 7 +++++++ certbot/tests/main_test.py | 26 +++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/certbot/main.py b/certbot/main.py index a457919d4..6078f87a6 100644 --- a/certbot/main.py +++ b/certbot/main.py @@ -789,6 +789,13 @@ def install(config, plugins): 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") diff --git a/certbot/tests/main_test.py b/certbot/tests/main_test.py index 24d059e53..a2115a486 100644 --- a/certbot/tests/main_test.py +++ b/certbot/tests/main_test.py @@ -761,20 +761,25 @@ class MainTest(test_util.ConfigTestCase): # pylint: disable=too-many-public-met @mock.patch('certbot.main.plug_sel.record_chosen_plugins') @mock.patch('certbot.main.plug_sel.pick_installer') def test_installer_param_error(self, _inst, _rec): - self.assertRaises(errors.ConfigurationError, - self._call, - ['install', '--key-path', '/tmp/key_path']) - self.assertRaises(errors.ConfigurationError, - self._call, - ['install', '--cert-path', '/tmp/key_path']) - self.assertRaises(errors.ConfigurationError, - self._call, - ['install']) self.assertRaises(errors.ConfigurationError, self._call, ['install', '--cert-name', 'notfound', '--key-path', 'invalid']) + @mock.patch('certbot.main.plug_sel.record_chosen_plugins') + @mock.patch('certbot.main.plug_sel.pick_installer') + @mock.patch('certbot.cert_manager.get_certnames') + @mock.patch('certbot.main._install_cert') + def test_installer_select_cert(self, mock_inst, mock_getcert, _inst, _rec): + mock_lineage = mock.MagicMock(cert_path="/tmp/cert", chain_path="/tmp/chain", + fullchain_path="/tmp/chain", + key_path="/tmp/privkey") + with mock.patch("certbot.cert_manager.lineage_for_certname") as mock_getlin: + mock_getlin.return_value = mock_lineage + self._call(['install'], mockisfile=True) + self.assertTrue(mock_getcert.called) + self.assertTrue(mock_inst.called) + @mock.patch('certbot.main._report_new_cert') @mock.patch('certbot.util.exe_exists') def test_configurator_selection(self, mock_exe_exists, unused_report): @@ -1742,6 +1747,7 @@ class InstallTest(test_util.ConfigTestCase): mock_inst.return_value = null.Installer(self.config, "null") plugins = disco.PluginsRegistry.find_all() self.config.auto_hsts = True + self.config.certname = "nonexistent" self.assertRaises(errors.NotSupportedError, main.install, self.config, plugins) @@ -1753,6 +1759,8 @@ class InstallTest(test_util.ConfigTestCase): plugins = disco.PluginsRegistry.find_all() self.config.auto_hsts = True self.config.certname = None + self.config.key_path = "/tmp/nonexistent" + self.config.cert_path = "/tmp/nonexistent" self.assertRaises(errors.ConfigurationError, main.install, self.config, plugins)