Esempio n. 1
0
def _search_lineages(cli_config: configuration.NamespaceConfig, func: Callable[..., T],
                     initial_rv: T, *args: Any) -> T:
    """Iterate func over unbroken lineages, allowing custom return conditions.

    Allows flexible customization of return values, including multiple
    return values and complex checks.

    :param `configuration.NamespaceConfig` cli_config: parsed command line arguments
    :param function func: function used while searching over lineages
    :param initial_rv: initial return value of the function (any type)

    :returns: Whatever was specified by `func` if a match is found.
    """
    configs_dir = cli_config.renewal_configs_dir
    # Verify the directory is there
    util.make_or_verify_dir(configs_dir, mode=0o755)

    rv = initial_rv
    for renewal_file in storage.renewal_conf_files(cli_config):
        try:
            candidate_lineage = storage.RenewableCert(renewal_file, cli_config)
        except (errors.CertStorageError, IOError):
            logger.debug("Renewal conf file %s is broken. Skipping.", renewal_file)
            logger.debug("Traceback was:\n%s", traceback.format_exc())
            continue
        rv = func(candidate_lineage, rv, *args)
    return rv
Esempio n. 2
0
    def test_new_key(self):
        # When renewing with both reuse_key and new_key, the key should be regenerated,
        # the key type, key parameters and reuse_key should be kept.
        self.config.reuse_key = True
        self.config.new_key = True
        self.config.dry_run = True
        config = configuration.NamespaceConfig(self.config)

        rc_path = test_util.make_lineage(self.config.config_dir,
                                         'sample-renewal.conf')
        lineage = storage.RenewableCert(rc_path, config)

        le_client = mock.MagicMock()
        le_client.obtain_certificate.return_value = (None, None, None, None)

        from certbot._internal import renewal

        with mock.patch('certbot._internal.renewal.hooks.renew_hook'):
            renewal.renew_cert(self.config, None, le_client, lineage)

        self.assertEqual(self.config.rsa_key_size, 2048)
        self.assertEqual(self.config.key_type, 'rsa')
        self.assertTrue(self.config.reuse_key)
        # None is passed as the existing key, i.e. the key is not actually being reused.
        le_client.obtain_certificate.assert_called_with(mock.ANY, None)
Esempio n. 3
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 renewal
    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, config)
    except (errors.CertStorageError, IOError) as error:
        logger.error("Renewal configuration file %s is broken.", full_path)
        logger.error("The error was: %s\nSkipping.", str(error))
        logger.debug("Traceback was:\n%s", traceback.format_exc())
        return None
    if "renewalparams" not in renewal_candidate.configuration:
        logger.error(
            "Renewal configuration file %s lacks "
            "renewalparams. Skipping.", full_path)
        return None
    renewalparams = renewal_candidate.configuration["renewalparams"]
    if "authenticator" not in renewalparams:
        logger.error(
            "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.
    renewalparams = _remove_deprecated_config_elements(renewalparams)
    try:
        restore_required_config_elements(config, renewalparams)
        _restore_plugin_configs(config, renewalparams)
    except (ValueError, errors.Error) as error:
        logger.error(
            "An error occurred while parsing %s. The error was %s. "
            "Skipping the file.", full_path, str(error))
        logger.debug("Traceback was:\n%s", traceback.format_exc())
        return None

    try:
        config.domains = [
            util.enforce_domain_sanity(d) for d in renewal_candidate.names()
        ]
    except errors.ConfigurationError as error:
        logger.error(
            "Renewal configuration file %s references a certificate "
            "that contains an invalid domain name. The problem "
            "was: %s. Skipping.", full_path, error)
        return None

    return renewal_candidate
Esempio n. 4
0
def list_certificates():
    """Display information about certs configured with Certbot

    :param config: Configuration.
    :type config: :class:`certbot._internal.configuration.NamespaceConfig`
    """
    
    plugins = plugins_disco.PluginsRegistry.find_all()
    
    args = cli.prepare_and_parse_args(plugins, [
        "certificates", 
        "--config-dir=" + constants.CONFIG_DIR, 
        "--work-dir=" + constants.WORK_DIR, 
        "--logs=" + constants.LOGS_DIR
    ])
    config = configuration.NamespaceConfig(args)
    
    parsed_certs = []
    parse_failures = []
    for renewal_file in storage.renewal_conf_files(config):
        try:
            renewal_candidate = storage.RenewableCert(renewal_file, config)
            crypto_util.verify_renewable_cert(renewal_candidate)
            parsed_certs.append(renewal_candidate)
        except Exception as e:  # pylint: disable=broad-except
            logger.warning("Renewal configuration file %s produced an "
                           "unexpected error: %s. Skipping.", renewal_file, e)
            logger.debug("Traceback was:\n%s", traceback.format_exc())
            parse_failures.append(renewal_file)
    
    return (parsed_certs, parse_failures)
Esempio n. 5
0
    def test_no_renewal_version(self):
        from certbot._internal import storage

        self._write_out_ex_kinds()
        self.assertTrue("version" not in self.config_file)

        with mock.patch("certbot._internal.storage.logger") as mock_logger:
            storage.RenewableCert(self.config_file.filename, self.config)
        self.assertFalse(mock_logger.warning.called)
Esempio n. 6
0
    def test_renewal_newer_version(self):
        from certbot._internal import storage

        self._write_out_ex_kinds()
        self.config_file["version"] = "99.99.99"
        self.config_file.write()

        with mock.patch("certbot._internal.storage.logger") as mock_logger:
            storage.RenewableCert(self.config_file.filename, self.config)
        self.assertTrue(mock_logger.info.called)
        self.assertTrue("version" in mock_logger.info.call_args[0][0])
Esempio n. 7
0
def update_live_symlinks(config: configuration.NamespaceConfig) -> None:
    """Update the certificate file family symlinks to use archive_dir.

    Use the information in the config file to make symlinks point to
    the correct archive directory.

    .. note:: This assumes that the installation is using a Reverter object.

    :param config: Configuration.
    :type config: :class:`certbot._internal.configuration.NamespaceConfig`

    """
    for renewal_file in storage.renewal_conf_files(config):
        storage.RenewableCert(renewal_file, config, update_symlinks=True)
Esempio n. 8
0
 def test_ancient_webroot_renewal_conf(self, mock_set_by_cli):
     mock_set_by_cli.return_value = False
     rc_path = test_util.make_lineage(self.config.config_dir,
                                      'sample-renewal-ancient.conf')
     self.config.account = None
     self.config.email = None
     self.config.webroot_path = None
     config = configuration.NamespaceConfig(self.config)
     lineage = storage.RenewableCert(rc_path, config)
     renewalparams = lineage.configuration['renewalparams']
     # pylint: disable=protected-access
     from certbot._internal import renewal
     renewal._restore_webroot_config(config, renewalparams)
     self.assertEqual(config.webroot_path, ['/var/www/'])
Esempio n. 9
0
 def test_update_symlinks(self):
     from certbot._internal import storage
     archive_dir_path = os.path.join(self.config.config_dir, "archive", "example.org")
     for kind in ALL_FOUR:
         live_path = self.config_file[kind]
         basename = kind + "1.pem"
         archive_path = os.path.join(archive_dir_path, basename)
         open(archive_path, 'a').close()
         os.symlink(os.path.join(self.config.config_dir, basename), live_path)
     self.assertRaises(errors.CertStorageError,
                       storage.RenewableCert, self.config_file.filename,
                       self.config)
     storage.RenewableCert(self.config_file.filename, self.config,
         update_symlinks=True)
Esempio n. 10
0
def lineage_for_certname(cli_config, certname):
    """Find a lineage object with name certname."""
    configs_dir = cli_config.renewal_configs_dir
    # Verify the directory is there
    util.make_or_verify_dir(configs_dir, mode=0o755)
    try:
        renewal_file = storage.renewal_file_for_certname(cli_config, certname)
    except errors.CertStorageError:
        return None
    try:
        return storage.RenewableCert(renewal_file, cli_config)
    except (errors.CertStorageError, IOError):
        logger.debug("Renewal conf file %s is broken.", renewal_file)
        logger.debug("Traceback was:\n%s", traceback.format_exc())
        return None
Esempio n. 11
0
    def setUp(self):
        from certbot._internal import storage

        super().setUp()

        # TODO: maybe provide NamespaceConfig.make_dirs?
        # TODO: main() should create those dirs, c.f. #902
        filesystem.makedirs(
            os.path.join(self.config.config_dir, "live", "example.org"))
        archive_path = os.path.join(self.config.config_dir, "archive",
                                    "example.org")
        filesystem.makedirs(archive_path)
        filesystem.makedirs(os.path.join(self.config.config_dir, "renewal"))

        config_file = configobj.ConfigObj()
        for kind in ALL_FOUR:
            kind_path = os.path.join(self.config.config_dir, "live",
                                     "example.org", kind + ".pem")
            config_file[kind] = kind_path
        with open(
                os.path.join(self.config.config_dir, "live", "example.org",
                             "README"), 'a'):
            pass
        config_file["archive"] = archive_path
        config_file.filename = os.path.join(self.config.config_dir, "renewal",
                                            "example.org.conf")
        config_file.write()
        self.config_file = config_file

        # 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.
        with open(
                os.path.join(self.config.config_dir, "renewal", "IGNORE.THIS"),
                "w") as junk:
            junk.write("This file should be ignored!")

        self.defaults = configobj.ConfigObj()

        with mock.patch(
                "certbot._internal.storage.RenewableCert._check_symlinks"
        ) as check:
            check.return_value = True
            self.test_rc = storage.RenewableCert(config_file.filename,
                                                 self.config)
Esempio n. 12
0
    def test_reuse_key_renewal_params(self):
        self.config.rsa_key_size = 'INVALID_VALUE'
        self.config.reuse_key = True
        self.config.dry_run = True
        config = configuration.NamespaceConfig(self.config)

        rc_path = test_util.make_lineage(self.config.config_dir,
                                         'sample-renewal.conf')
        lineage = storage.RenewableCert(rc_path, config)

        le_client = mock.MagicMock()
        le_client.obtain_certificate.return_value = (None, None, None, None)

        from certbot._internal import renewal

        with mock.patch('certbot._internal.renewal.hooks.renew_hook'):
            renewal.renew_cert(self.config, None, le_client, lineage)

        assert self.config.rsa_key_size == 2048
Esempio n. 13
0
def certificates(config: configuration.NamespaceConfig) -> None:
    """Display information about certs configured with Certbot

    :param config: Configuration.
    :type config: :class:`certbot._internal.configuration.NamespaceConfig`
    """
    parsed_certs = []
    parse_failures = []
    for renewal_file in storage.renewal_conf_files(config):
        try:
            renewal_candidate = storage.RenewableCert(renewal_file, config)
            crypto_util.verify_renewable_cert(renewal_candidate)
            parsed_certs.append(renewal_candidate)
        except Exception as e:  # pylint: disable=broad-except
            logger.warning("Renewal configuration file %s produced an "
                           "unexpected error: %s. Skipping.", renewal_file, e)
            logger.debug("Traceback was:\n%s", traceback.format_exc())
            parse_failures.append(renewal_file)

    # Describe all the certs
    _describe_certs(config, parsed_certs, parse_failures)
Esempio n. 14
0
    def test_reuse_ec_key_renewal_params(self):
        self.config.elliptic_curve = 'INVALID_CURVE'
        self.config.reuse_key = True
        self.config.dry_run = True
        self.config.key_type = 'ecdsa'
        config = configuration.NamespaceConfig(self.config)

        rc_path = test_util.make_lineage(
            self.config.config_dir,
            'sample-renewal-ec.conf',
            ec=True,
        )
        lineage = storage.RenewableCert(rc_path, config)

        le_client = mock.MagicMock()
        le_client.obtain_certificate.return_value = (None, None, None, None)

        from certbot._internal import renewal

        with mock.patch('certbot._internal.renewal.hooks.renew_hook'):
            renewal.renew_cert(self.config, None, le_client, lineage)

        assert self.config.elliptic_curve == 'secp256r1'
Esempio n. 15
0
 def _cert_iter(self):
     """An iterator over all renewable certificates on this machine"""
     for file in storage.renewal_conf_files(self._config()):
         yield storage.RenewableCert(file, self._config())