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
This commit is contained in:
Joona Hoikkala 2018-06-27 21:35:01 +03:00 committed by Brad Warren
parent 2304f7fcda
commit f169e7374b
2 changed files with 24 additions and 9 deletions

View file

@ -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")

View file

@ -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)