Exemplo n.º 1
0
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
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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)