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 run(config, plugins): """Obtain a certificate and install. :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None """ # TODO: Make run as close to auth + install as possible # Possible difficulties: config.csr was hacked into auth try: installer, authenticator = plug_sel.choose_configurator_plugins( config, plugins, "run") except errors.PluginSelectionError as e: return str(e) # Preflight check for enhancement support by the selected installer if not enhancements.are_supported(config, installer): raise errors.NotSupportedError( "One ore more of the requested enhancements " "are not supported by the selected installer") # TODO: Handle errors from _init_le_client? le_client = _init_le_client(config, authenticator, installer) domains, certname = _find_domains_or_certname(config, installer) should_get_cert, lineage = _find_cert(config, domains, certname) new_lineage = lineage if should_get_cert: new_lineage = _get_and_save_cert(le_client, config, domains, certname, lineage) cert_path = new_lineage.cert_path if new_lineage else None fullchain_path = new_lineage.fullchain_path if new_lineage else None key_path = new_lineage.key_path if new_lineage else None if should_get_cert: _report_new_cert(config, cert_path, fullchain_path, key_path) _install_cert(config, le_client, domains, new_lineage) if enhancements.are_requested(config) and new_lineage: enhancements.enable(new_lineage, domains, installer, config) if lineage is None or not should_get_cert: display_ops.success_installation(domains) else: display_ops.success_renewal(domains) _suggest_donation_if_appropriate(config) eff.handle_subscription(config, le_client.account) return None
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, redirect_default=False) if enhancements.are_requested(config): enhancements.enable(lineage, domains, installer, config) return None
def certonly(config, plugins): """Authenticate & obtain cert, but do not install it. This implements the 'certonly' subcommand. :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :returns: `None` :rtype: None :raises errors.Error: If specified plugin could not be used """ # SETUP: Select plugins and construct a client instance try: # installers are used in auth mode to determine domain names installer, auth = plug_sel.choose_configurator_plugins( config, plugins, "certonly") except errors.PluginSelectionError as e: logger.info("Could not choose appropriate plugin: %s", e) raise le_client = _init_le_client(config, auth, installer) if config.csr: cert_path, fullchain_path = _csr_get_and_save_cert(config, le_client) _report_new_cert(config, cert_path, fullchain_path) _suggest_donation_if_appropriate(config) eff.handle_subscription(config, le_client.account) return domains, certname = _find_domains_or_certname(config, installer) should_get_cert, lineage = _find_cert(config, domains, certname) if not should_get_cert: notify = zope.component.getUtility(interfaces.IDisplay).notification notify("Certificate not yet due for renewal; no action taken.", pause=False) return lineage = _get_and_save_cert(le_client, config, domains, certname, lineage) cert_path = lineage.cert_path if lineage else None fullchain_path = lineage.fullchain_path if lineage else None key_path = lineage.key_path if lineage else None _report_new_cert(config, cert_path, fullchain_path, key_path) _suggest_donation_if_appropriate(config) eff.handle_subscription(config, le_client.account)
def renew_cert(config, plugins, lineage): """Renew & save an existing cert. Do not install it. :param config: Configuration object :type config: interfaces.IConfig :param plugins: List of plugins :type plugins: `list` of `str` :param lineage: Certificate lineage object :type lineage: storage.RenewableCert :returns: `None` :rtype: None :raises errors.PluginSelectionError: MissingCommandlineFlag if supplied parameters do not pass """ try: # installers are used in auth mode to determine domain names installer, auth = plug_sel.choose_configurator_plugins( config, plugins, "certonly") except errors.PluginSelectionError as e: logger.info("Could not choose appropriate plugin: %s", e) raise le_client = _init_le_client(config, auth, installer) renewed_lineage = _get_and_save_cert(le_client, config, lineage=lineage) notify = zope.component.getUtility(interfaces.IDisplay).notification if installer is None: notify( "new certificate deployed without reload, fullchain is {0}".format( lineage.fullchain), pause=False) else: # In case of a renewal, reload server to pick up new certificate. # In principle we could have a configuration option to inhibit this # from happening. # Run deployer updater.run_renewal_deployer(config, renewed_lineage, installer) installer.restart() notify( "new certificate deployed with reload of {0} server; fullchain is {1}" .format(config.installer, lineage.fullchain), pause=False)
def request_cert(args, config): root_cert_advise() key, csr = csr_util.prepare(args.email, config, key_path=args.key_path, usage=args.usage) ## Reparse for including --csr arguments cli_args = prepare_cli_args(args) if (args.dry_run): cli_args.extend(['--dry-run']) for email in args.email: cli_args.extend(['-d', email]) cli_args.extend(['--csr', csr.file]) if (args.imap): cli_args.extend(['-a', 'castle-imap']) cli_args.extend(['--castle-imap-login', args.login]) cli_args.extend(['--castle-imap-password', args.password]) cli_args.extend(['--castle-imap-host', args.host]) if (args.port): cli_args.extend(['--castle-imap-port', args.port]) if (args.ssl): cli_args.extend(['--castle-imap-ssl']) if (args.smtp_method): cli_args.extend(['--castle-imap-smtp-method', args.smtp_method]) if (args.smtp_login): cli_args.extend(['--castle-imap-smtp-login', args.smtp_login]) if (args.smtp_password): cli_args.extend( ['--castle-imap-smtp-password', args.smtp_password]) cli_args.extend(['--castle-imap-smtp-host', args.smtp_host]) if (args.smtp_port): cli_args.extend(['--castle-imap-smtp-port', args.smtp_port]) elif (args.outlook): cli_args.extend(['-a', 'castle-mapi']) cli_args.extend(['--castle-mapi-account', args.outlook_account]) else: cli_args.extend(['-a', 'castle-interactive']) cli_args.extend(['-i', 'castle-installer']) if (args.no_passphrase): cli_args.extend(['--castle-installer-no-passphrase']) elif (args.passphrase): cli_args.extend(['--castle-installer-passphrase', args.passphrase]) cli_args.extend(['-m', args.contact]) if (args.agree_tos): cli_args.extend(['--agree-tos']) config, plugins = prepare_config(cli_args) config.cert_path = config.live_dir + '/cert.pem' config.chain_path = config.live_dir + '/ca.pem' config.fullchain_path = config.live_dir + '/chain.pem' config.key_path = key.file try: # installers are used in auth mode to determine domain names installer, auth = plug_sel.choose_configurator_plugins( config, plugins, "certonly") except errors.PluginSelectionError as e: logger.info("Could not choose appropriate plugin: %s", e) raise le_client = certbot_main._init_le_client(config, auth, installer) cert_path, chain_path, fullchain_path = certbot_main._csr_get_and_save_cert( config, le_client) config.cert_path = cert_path config.fullchain_path = fullchain_path config.chain_path = chain_path certbot_main._csr_report_new_cert(config, cert_path, chain_path, fullchain_path) if (not config.dry_run): certbot_main._install_cert(config, le_client, args.email) else: util.safely_remove(csr.file)