Ejemplo n.º 1
0
def _find_duplicative_certs(config, domains):
    """Find existing certs that duplicate the request."""

    identical_names_cert, subset_names_cert = None, None

    cli_config = configuration.RenewerConfiguration(config)
    configs_dir = cli_config.renewal_configs_dir
    # Verify the directory is there
    le_util.make_or_verify_dir(configs_dir, mode=0o755, uid=os.geteuid())

    for renewal_file in renewal.renewal_conf_files(cli_config):
        try:
            candidate_lineage = storage.RenewableCert(renewal_file, cli_config)
        except (errors.CertStorageError, IOError):
            logger.warning("Renewal conf file %s is broken. Skipping.",
                           renewal_file)
            logger.debug("Traceback was:\n%s", traceback.format_exc())
            continue
        # TODO: Handle these differently depending on whether they are
        #       expired or still valid?
        candidate_names = set(candidate_lineage.names())
        if candidate_names == set(domains):
            identical_names_cert = candidate_lineage
        elif candidate_names.issubset(set(domains)):
            # This logic finds and returns the largest subset-names cert
            # in the case where there are several available.
            if subset_names_cert is None:
                subset_names_cert = candidate_lineage
            elif len(candidate_names) > len(subset_names_cert.names()):
                subset_names_cert = candidate_lineage

    return identical_names_cert, subset_names_cert
Ejemplo n.º 2
0
def _find_duplicative_certs(config, domains):
    """Find existing certs that duplicate the request."""

    identical_names_cert, subset_names_cert = None, None

    cli_config = configuration.RenewerConfiguration(config)
    configs_dir = cli_config.renewal_configs_dir
    # Verify the directory is there
    le_util.make_or_verify_dir(configs_dir, mode=0o755, uid=os.geteuid())

    for renewal_file in os.listdir(configs_dir):
        try:
            full_path = os.path.join(configs_dir, renewal_file)
            candidate_lineage = storage.RenewableCert(full_path, cli_config)
        except (CertStorageError, IOError):
            logger.warning(
                "Renewal configuration file %s is broken. "
                "Skipping.", full_path)
            continue
        # TODO: Handle these differently depending on whether they are
        #       expired or still valid?
        candidate_names = set(candidate_lineage.names())
        if candidate_names == set(domains):
            identical_names_cert = candidate_lineage
        elif candidate_names.issubset(set(domains)):
            subset_names_cert = candidate_lineage

    return identical_names_cert, subset_names_cert
Ejemplo n.º 3
0
def _find_duplicative_certs(domains, config, renew_config):
    """Find existing certs that duplicate the request."""

    identical_names_cert, subset_names_cert = None, None

    configs_dir = renew_config.renewal_configs_dir
    cli_config = configuration.RenewerConfiguration(config)
    for renewal_file in os.listdir(configs_dir):
        try:
            full_path = os.path.join(configs_dir, renewal_file)
            rc_config = configobj.ConfigObj(renew_config.renewer_config_file)
            rc_config.merge(configobj.ConfigObj(full_path))
            rc_config.filename = full_path
            candidate_lineage = storage.RenewableCert(rc_config,
                                                      config_opts=None,
                                                      cli_config=cli_config)
        except (configobj.ConfigObjError, errors.CertStorageError, IOError):
            logger.warning(
                "Renewal configuration file %s is broken. "
                "Skipping.", full_path)
            continue
        # TODO: Handle these differently depending on whether they are
        #       expired or still valid?
        candidate_names = set(candidate_lineage.names())
        if candidate_names == set(domains):
            identical_names_cert = candidate_lineage
        elif candidate_names.issubset(set(domains)):
            subset_names_cert = candidate_lineage

    return identical_names_cert, subset_names_cert
Ejemplo n.º 4
0
    def setUp(self):
        from letsencrypt import storage
        self.tempdir = tempfile.mkdtemp()

        self.cli_config = configuration.RenewerConfiguration(
            namespace=mock.MagicMock(
                config_dir=self.tempdir,
                work_dir=self.tempdir,
                logs_dir=self.tempdir,
            ))

        # TODO: maybe provide RenewerConfiguration.make_dirs?
        # TODO: main() should create those dirs, c.f. #902
        os.makedirs(os.path.join(self.tempdir, "live", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "archive", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "renewal"))

        config = configobj.ConfigObj()
        for kind in ALL_FOUR:
            config[kind] = os.path.join(self.tempdir, "live", "example.org",
                                        kind + ".pem")
        config.filename = os.path.join(self.tempdir, "renewal",
                                       "example.org.conf")
        config.write()
        self.config = config

        self.defaults = configobj.ConfigObj()
        self.test_rc = storage.RenewableCert(config.filename, self.cli_config)
Ejemplo n.º 5
0
def main(cli_args=sys.argv[1:]):
    """Main function for autorenewer script."""
    # TODO: Distinguish automated invocation from manual invocation,
    #       perhaps by looking at sys.argv[0] and inhibiting automated
    #       invocations if /etc/letsencrypt/renewal.conf defaults have
    #       turned it off. (The boolean parameter should probably be
    #       called renewer_enabled.)

    # TODO: When we have a more elaborate renewer command line, we will
    #       presumably also be able to specify a config file on the
    #       command line, which, if provided, should take precedence over
    #       te default config files

    zope.component.provideUtility(display_util.FileDisplay(sys.stdout))

    args = _create_parser().parse_args(cli_args)

    uid = os.geteuid()
    le_util.make_or_verify_dir(args.logs_dir, 0o700, uid)
    cli.setup_logging(args, _cli_log_handler, logfile='renewer.log')

    cli_config = configuration.RenewerConfiguration(args)

    # Ensure that all of the needed folders have been created before continuing
    le_util.make_or_verify_dir(cli_config.work_dir,
                               constants.CONFIG_DIRS_MODE, uid)

    for renewal_file in os.listdir(cli_config.renewal_configs_dir):
        print "Processing", renewal_file
        try:
            # TODO: Before trying to initialize the RenewableCert object,
            #       we could check here whether the combination of the config
            #       and the rc_config together disables all autorenewal and
            #       autodeployment applicable to this cert.  In that case, we
            #       can simply continue and don't need to instantiate a
            #       RenewableCert object for this cert at all, which could
            #       dramatically improve performance for large deployments
            #       where autorenewal is widely turned off.
            cert = storage.RenewableCert(renewal_file, cli_config)
        except errors.CertStorageError:
            # This indicates an invalid renewal configuration file, such
            # as one missing a required parameter (in the future, perhaps
            # also one that is internally inconsistent or is missing a
            # required parameter).  As a TODO, maybe we should warn the
            # user about the existence of an invalid or corrupt renewal
            # config rather than simply ignoring it.
            continue
        if cert.should_autorenew():
            # Note: not cert.current_version() because the basis for
            # the renewal is the latest version, even if it hasn't been
            # deployed yet!
            old_version = cert.latest_common_version()
            renew(cert, old_version)
            notify.notify("Autorenewed a cert!!!", "root", "It worked!")
            # TODO: explain what happened
        if cert.should_autodeploy():
            cert.update_all_links_to(cert.latest_common_version())
            # TODO: restart web server (invoke IInstaller.restart() method)
            notify.notify("Autodeployed a cert!!!", "root", "It worked!")
Ejemplo n.º 6
0
def _reconstitute(config, full_path):
    """Try to instantiate a RenewableCert, updating config with relevant items.

    This is specifically for use in renewal and enforces several checks
    and policies to ensure that we can try to proceed with the renwal
    request. The config argument is modified by including relevant options
    read from the renewal configuration file.

    :param configuration.NamespaceConfig config: configuration for the
        current lineage
    :param str full_path: Absolute path to the configuration file that
        defines this lineage

    :returns: the RenewableCert object or None if a fatal error occurred
    :rtype: `storage.RenewableCert` or NoneType

    """
    try:
        renewal_candidate = storage.RenewableCert(
            full_path, configuration.RenewerConfiguration(config))
    except (errors.CertStorageError, IOError):
        logger.warning("Renewal configuration file %s is broken. Skipping.",
                       full_path)
        logger.debug("Traceback was:\n%s", traceback.format_exc())
        return None
    if "renewalparams" not in renewal_candidate.configuration:
        logger.warning(
            "Renewal configuration file %s lacks "
            "renewalparams. Skipping.", full_path)
        return None
    renewalparams = renewal_candidate.configuration["renewalparams"]
    if "authenticator" not in renewalparams:
        logger.warning(
            "Renewal configuration file %s does not specify "
            "an authenticator. Skipping.", full_path)
        return None
    # Now restore specific values along with their data types, if
    # those elements are present.
    try:
        _restore_required_config_elements(config, renewalparams)
        _restore_plugin_configs(config, renewalparams)
    except (ValueError, errors.Error) as error:
        logger.warning(
            "An error occurred while parsing %s. The error was %s. "
            "Skipping the file.", full_path, error.message)
        logger.debug("Traceback was:\n%s", traceback.format_exc())
        return None

    try:
        for d in renewal_candidate.names():
            cli.process_domain(config, d)
    except errors.ConfigurationError as error:
        logger.warning(
            "Renewal configuration file %s references a cert "
            "that contains an invalid domain name. The problem "
            "was: %s. Skipping.", full_path, error)
        return None

    return renewal_candidate
Ejemplo n.º 7
0
 def test_ancient_webroot_renewal_conf(self, mock_set_by_cli):
     mock_set_by_cli.return_value = False
     rc_path = self._make_test_renewal_conf('sample-renewal-ancient.conf')
     args = mock.MagicMock(account=None, email=None, webroot_path=None)
     config = configuration.NamespaceConfig(args)
     lineage = storage.RenewableCert(
         rc_path, configuration.RenewerConfiguration(config))
     renewalparams = lineage.configuration["renewalparams"]
     # pylint: disable=protected-access
     renewal._restore_webroot_config(config, renewalparams)
     self.assertEqual(config.webroot_path, ["/var/www/"])
Ejemplo n.º 8
0
def main(config=None):
    """Main function for autorenewer script."""
    # TODO: Distinguish automated invocation from manual invocation,
    #       perhaps by looking at sys.argv[0] and inhibiting automated
    #       invocations if /etc/letsencrypt/renewal.conf defaults have
    #       turned it off. (The boolean parameter should probably be
    #       called renewer_enabled.)

    config = storage.config_with_defaults(config)
    # Now attempt to read the renewer config file and augment or replace
    # the renewer defaults with any options contained in that file.  If
    # renewer_config_file is undefined or if the file is nonexistent or
    # empty, this .merge() will have no effect.  TODO: when we have a more
    # elaborate renewer command line, we will presumably also be able to
    # specify a config file on the command line, which, if provided, should
    # take precedence over this one.
    config.merge(configobj.ConfigObj(config.get("renewer_config_file", "")))

    for i in os.listdir(config["renewal_configs_dir"]):
        print "Processing", i
        if not i.endswith(".conf"):
            continue
        rc_config = configobj.ConfigObj(
            os.path.join(config["renewal_configs_dir"], i))
        try:
            # TODO: Before trying to initialize the RenewableCert object,
            #       we could check here whether the combination of the config
            #       and the rc_config together disables all autorenewal and
            #       autodeployment applicable to this cert.  In that case, we
            #       can simply continue and don't need to instantiate a
            #       RenewableCert object for this cert at all, which could
            #       dramatically improve performance for large deployments
            #       where autorenewal is widely turned off.
            cert = storage.RenewableCert(rc_config)
        except ValueError:
            # This indicates an invalid renewal configuration file, such
            # as one missing a required parameter (in the future, perhaps
            # also one that is internally inconsistent or is missing a
            # required parameter).  As a TODO, maybe we should warn the
            # user about the existence of an invalid or corrupt renewal
            # config rather than simply ignoring it.
            continue
        if cert.should_autodeploy():
            cert.update_all_links_to(cert.latest_common_version())
            # TODO: restart web server (invoke IInstaller.restart() method)
            notify.notify("Autodeployed a cert!!!", "root", "It worked!")
            # TODO: explain what happened
        if cert.should_autorenew():
            # Note: not cert.current_version() because the basis for
            # the renewal is the latest version, even if it hasn't been
            # deployed yet!
            old_version = cert.latest_common_version()
            renew(cert, old_version)
            notify.notify("Autorenewed a cert!!!", "root", "It worked!")
 def setUp(self):
     from letsencrypt import storage
     self.tempdir = tempfile.mkdtemp()
     os.makedirs(os.path.join(self.tempdir, "live", "example.org"))
     os.makedirs(os.path.join(self.tempdir, "archive", "example.org"))
     os.makedirs(os.path.join(self.tempdir, "configs"))
     defaults = configobj.ConfigObj()
     defaults["live_dir"] = os.path.join(self.tempdir, "live")
     defaults["archive_dir"] = os.path.join(self.tempdir, "archive")
     defaults["renewal_configs_dir"] = os.path.join(self.tempdir, "configs")
     config = configobj.ConfigObj()
     for kind in ALL_FOUR:
         config[kind] = os.path.join(self.tempdir, "live", "example.org",
                                     kind + ".pem")
     config.filename = os.path.join(self.tempdir, "configs",
                                    "example.org.conf")
     self.defaults = defaults  # for main() test
     self.test_rc = storage.RenewableCert(config, defaults)
Ejemplo n.º 10
0
    def setUp(self):
        from letsencrypt import storage
        self.tempdir = tempfile.mkdtemp()

        self.cli_config = configuration.RenewerConfiguration(
            namespace=mock.MagicMock(config_dir=self.tempdir))
        # TODO: maybe provide RenewerConfiguration.make_dirs?
        os.makedirs(os.path.join(self.tempdir, "live", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "archive", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "configs"))

        config = configobj.ConfigObj()
        for kind in ALL_FOUR:
            config[kind] = os.path.join(self.tempdir, "live", "example.org",
                                        kind + ".pem")
        config.filename = os.path.join(self.tempdir, "configs",
                                       "example.org.conf")

        self.defaults = configobj.ConfigObj()
        self.test_rc = storage.RenewableCert(config, self.defaults,
                                             self.cli_config)
Ejemplo n.º 11
0
    def setUp(self):
        from letsencrypt import storage
        self.tempdir = tempfile.mkdtemp()

        self.cli_config = configuration.RenewerConfiguration(
            namespace=mock.MagicMock(
                config_dir=self.tempdir,
                work_dir=self.tempdir,
                logs_dir=self.tempdir,
            ))

        # TODO: maybe provide RenewerConfiguration.make_dirs?
        # TODO: main() should create those dirs, c.f. #902
        os.makedirs(os.path.join(self.tempdir, "live", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "archive", "example.org"))
        os.makedirs(os.path.join(self.tempdir, "renewal"))

        config = configobj.ConfigObj()
        for kind in ALL_FOUR:
            config[kind] = os.path.join(self.tempdir, "live", "example.org",
                                        kind + ".pem")
        config.filename = os.path.join(self.tempdir, "renewal",
                                       "example.org.conf")
        config.write()
        self.config = config

        # We also create a file that isn't a renewal config in the same
        # location to test that logic that reads in all-and-only renewal
        # configs will ignore it and NOT attempt to parse it.
        junk = open(os.path.join(self.tempdir, "renewal", "IGNORE.THIS"), "w")
        junk.write("This file should be ignored!")
        junk.close()

        self.defaults = configobj.ConfigObj()

        with mock.patch(
                "letsencrypt.storage.RenewableCert._check_symlinks") as check:
            check.return_value = True
            self.test_rc = storage.RenewableCert(config.filename,
                                                 self.cli_config)