def _report_new_cert(config, cert_path, fullchain_path): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain """ expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) if fullchain_path: # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. and_chain = "and chain have" path = fullchain_path else: # Unless we're in .csr mode and there really isn't one and_chain = "has " path = cert_path verbswitch = ' with the "certonly" option' if config.verb == "run" else "" # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ('Congratulations! Your certificate {0} been saved at {1}.' ' Your cert will expire on {2}. To obtain a new or tweaked version of this ' 'certificate in the future, simply run {3} again{4}. ' 'To non-interactively renew *all* of your ceriticates, run "{3} renew"' .format(and_chain, path, expiry, cli.cli_command, verbswitch)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def _report_new_cert(cert_path, fullchain_path): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain """ expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) if fullchain_path: # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. and_chain = "and chain have" path = fullchain_path else: # Unless we're in .csr mode and there really isn't one and_chain = "has " path = cert_path # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ("Congratulations! Your certificate {0} been saved at {1}." " Your cert will expire on {2}. To obtain a new version of the " "certificate in the future, simply run Certbot again." .format(and_chain, path, expiry)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def target_expiry(self): """The current target certificate's expiration datetime :returns: Expiration datetime of the current target certificate :rtype: :class:`datetime.datetime` """ return crypto_util.notAfter(self.current_target("cert"))
def ocsp_revoked_by_paths(self, cert_path: str, chain_path: str, timeout: int = 10) -> bool: """Performs the OCSP revocation check :param str cert_path: Certificate filepath :param str chain_path: Certificate chain :param int timeout: Timeout (in seconds) for the OCSP query :returns: True if revoked; False if valid or the check failed or cert is expired. :rtype: bool """ if self.broken: return False # Let's Encrypt doesn't update OCSP for expired certificates, # so don't check OCSP if the cert is expired. # https://github.com/certbot/certbot/issues/7152 now = pytz.UTC.fromutc(datetime.utcnow()) if crypto_util.notAfter(cert_path) <= now: return False url, host = _determine_ocsp_server(cert_path) if not host or not url: return False if self.use_openssl_binary: return self._check_ocsp_openssl_bin(cert_path, chain_path, host, url, timeout) return _check_ocsp_cryptography(cert_path, chain_path, url, timeout)
def _report_new_cert(config, cert_path, fullchain_path): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain """ expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) if fullchain_path: # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. and_chain = "and chain have" path = fullchain_path else: # Unless we're in .csr mode and there really isn't one and_chain = "has " path = cert_path verbswitch = ' with the "certonly" option' if config.verb == "run" else "" # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ('Congratulations! Your certificate {0} been saved at {1}.' ' Your cert will expire on {2}. To obtain a new or tweaked version of this ' 'certificate in the future, simply run {3} again{4}. ' 'To non-interactively renew *all* of your certificates, run "{3} renew"' .format(and_chain, path, expiry, cli.cli_command, verbswitch)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def _report_new_cert(cert_path, fullchain_path): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain """ expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) if fullchain_path: # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. and_chain = "and chain have" path = fullchain_path else: # Unless we're in .csr mode and there really isn't one and_chain = "has " path = cert_path # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ( "Congratulations! Your certificate {0} been saved at {1}." " Your cert will expire on {2}. To obtain a new version of the " "certificate in the future, simply run Certbot again.".format(and_chain, path, expiry) ) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def _report_new_cert(config, cert_path, fullchain_path): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain """ if config.dry_run: _report_successful_dry_run(config) return assert cert_path and fullchain_path, "No certificates saved to report." expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. verbswitch = ' with the "certonly" option' if config.verb == "run" else "" # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ( 'Congratulations! Your certificate and chain have been saved at {0}.' ' Your cert will expire on {1}. To obtain a new or tweaked version of this ' 'certificate in the future, simply run {2} again{3}. ' 'To non-interactively renew *all* of your certificates, run "{2} renew"' .format(fullchain_path, expiry, cli.cli_command, verbswitch)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY) print("Voy a copiar") copyfile(fullchain_path, "../../ObtainedCERT.pem")
def ocsp_revoked(self, cert): # type: (RenewableCert) -> bool """Get revoked status for a particular cert version. .. todo:: Make this a non-blocking call :param `.interfaces.RenewableCert` cert: Certificate object :returns: True if revoked; False if valid or the check failed or cert is expired. :rtype: bool """ cert_path, chain_path = cert.cert_path, cert.chain_path if self.broken: return False # Let's Encrypt doesn't update OCSP for expired certificates, # so don't check OCSP if the cert is expired. # https://github.com/certbot/certbot/issues/7152 now = pytz.UTC.fromutc(datetime.utcnow()) if crypto_util.notAfter(cert_path) <= now: return False url, host = _determine_ocsp_server(cert_path) if not host or not url: return False if self.use_openssl_binary: return self._check_ocsp_openssl_bin(cert_path, chain_path, host, url) return _check_ocsp_cryptography(cert_path, chain_path, url)
def should_autodeploy(self, interactive=False): """Should this lineage now automatically deploy a newer version? This is a policy question and does not only depend on whether there is a newer version of the cert. (This considers whether autodeployment is enabled, whether a relevant newer version exists, and whether the time interval for autodeployment has been reached.) :param bool interactive: set to True to examine the question regardless of whether the renewal configuration allows automated deployment (for interactive use). Default False. :returns: whether the lineage now ought to autodeploy an existing newer cert version :rtype: bool """ if interactive or self.autodeployment_is_enabled(): if self.has_pending_deployment(): interval = self.configuration.get("deploy_before_expiry", "5 days") expiry = crypto_util.notAfter(self.current_target("cert")) now = pytz.UTC.fromutc(datetime.datetime.utcnow()) if expiry < add_time_interval(now, interval): return True return False
def _report_new_cert(config, cert_path, fullchain_path, key_path=None): """Reports the creation of a new certificate to the user. :param str cert_path: path to cert :param str fullchain_path: path to full chain :param str key_path: path to private key, if available """ if config.dry_run: _report_successful_dry_run(config) return assert cert_path and fullchain_path, "No certificates saved to report." expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. verbswitch = ' with the "certonly" option' if config.verb == "run" else "" privkey_statement = 'Your key file has been saved at:{br}{0}{br}'.format( key_path, br=os.linesep) if key_path else "" # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ('Congratulations! Your certificate and chain have been saved at:{br}' '{0}{br}{1}' 'Your cert will expire on {2}. To obtain a new or tweaked version of this ' 'certificate in the future, simply run {3} again{4}. ' 'To non-interactively renew *all* of your certificates, run "{3} renew"' .format(fullchain_path, privkey_statement, expiry, cli.cli_command, verbswitch, br=os.linesep)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def _report_new_cert(config, cert_path, fullchain_path, key_path=None): """Reports the creation of a new certificate to the user. :param cert_path: path to certificate :type cert_path: str :param fullchain_path: path to full chain :type fullchain_path: str :param key_path: path to private key, if available :type key_path: str :returns: `None` :rtype: None """ if config.dry_run: _report_successful_dry_run(config) return assert cert_path and fullchain_path, "No certificates saved to report." expiry = crypto_util.notAfter(cert_path).date() reporter_util = zope.component.getUtility(interfaces.IReporter) # Print the path to fullchain.pem because that's what modern webservers # (Nginx and Apache2.4) will want. verbswitch = ' with the "certonly" option' if config.verb == "run" else "" privkey_statement = 'Your key file has been saved at:{br}{0}{br}'.format( key_path, br=os.linesep) if key_path else "" # XXX Perhaps one day we could detect the presence of known old webservers # and say something more informative here. msg = ( 'Congratulations! Your certificate and chain have been saved at:{br}' '{0}{br}{1}' 'Your cert will expire on {2}. To obtain a new or tweaked version of this ' 'certificate in the future, simply run {3} again{4}. ' 'To non-interactively renew *all* of your certificates, run "{3} renew"' .format(fullchain_path, privkey_statement, expiry, cli.cli_command, verbswitch, br=os.linesep)) reporter_util.add_message(msg, reporter_util.MEDIUM_PRIORITY)
def should_autorenew(self, interactive=False): """Should we now try to autorenew the most recent cert version? This is a policy question and does not only depend on whether the cert is expired. (This considers whether autorenewal is enabled, whether the cert is revoked, and whether the time interval for autorenewal has been reached.) Note that this examines the numerically most recent cert version, not the currently deployed version. :param bool interactive: set to True to examine the question regardless of whether the renewal configuration allows automated renewal (for interactive use). Default False. :returns: whether an attempt should now be made to autorenew the most current cert version in this lineage :rtype: bool """ if interactive or self.autorenewal_is_enabled(): # Consider whether to attempt to autorenew this cert now # Renewals on the basis of revocation if self.ocsp_revoked(self.latest_common_version()): logger.debug("Should renew, certificate is revoked.") return True # Renews some period before expiry time default_interval = constants.RENEWER_DEFAULTS[ "renew_before_expiry"] interval = self.configuration.get("renew_before_expiry", default_interval) expiry = crypto_util.notAfter( self.version("cert", self.latest_common_version())) now = pytz.UTC.fromutc(datetime.datetime.utcnow()) if expiry < add_time_interval(now, interval): logger.debug( "Should renew, less than %s before certificate " "expiry %s.", interval, expiry.strftime("%Y-%m-%d %H:%M:%S %Z")) return True return False
def should_autorenew(self, interactive=False): """Should we now try to autorenew the most recent cert version? This is a policy question and does not only depend on whether the cert is expired. (This considers whether autorenewal is enabled, whether the cert is revoked, and whether the time interval for autorenewal has been reached.) Note that this examines the numerically most recent cert version, not the currently deployed version. :param bool interactive: set to True to examine the question regardless of whether the renewal configuration allows automated renewal (for interactive use). Default False. :returns: whether an attempt should now be made to autorenew the most current cert version in this lineage :rtype: bool """ if interactive or self.autorenewal_is_enabled(): # Consider whether to attempt to autorenew this cert now # Renewals on the basis of revocation if self.ocsp_revoked(self.latest_common_version()): logger.debug("Should renew, certificate is revoked.") return True # Renews some period before expiry time default_interval = constants.RENEWER_DEFAULTS["renew_before_expiry"] interval = self.configuration.get("renew_before_expiry", default_interval) expiry = crypto_util.notAfter(self.version( "cert", self.latest_common_version())) now = pytz.UTC.fromutc(datetime.datetime.utcnow()) if expiry < add_time_interval(now, interval): logger.debug("Should renew, less than %s before certificate " "expiry %s.", interval, expiry.strftime("%Y-%m-%d %H:%M:%S %Z")) return True return False
def test_notAfter(self): from certbot.crypto_util import notAfter self.assertEqual( notAfter(CERT_PATH).isoformat(), '2014-12-18T22:34:45+00:00')
def test_notAfter(self): from certbot.crypto_util import notAfter self.assertEqual(notAfter(CERT_PATH).isoformat(), '2014-12-18T22:34:45+00:00')
def handle_renewal_request(config): """Examine each lineage; renew if due and report results""" # This is trivially False if config.domains is empty if any(domain not in config.webroot_map for domain in config.domains): # If more plugins start using cli.add_domains, # we may want to only log a warning here raise errors.Error( "Currently, the renew verb is capable of either " "renewing all installed certificates that are due " "to be renewed or renewing a single certificate specified " "by its name. If you would like to renew specific " "certificates by their domains, use the certonly command " "instead. The renew verb may provide other options " "for selecting certificates to renew in the future.") if config.certname: conf_files = [ storage.renewal_file_for_certname(config, config.certname) ] else: conf_files = storage.renewal_conf_files(config) renew_successes = [] renew_failures = [] renew_skipped = [] parse_failures = [] # Noninteractive renewals include a random delay in order to spread # out the load on the certificate authority servers, even if many # users all pick the same time for renewals. This delay precedes # running any hooks, so that side effects of the hooks (such as # shutting down a web service) aren't prolonged unnecessarily. apply_random_sleep = not sys.stdin.isatty( ) and config.random_sleep_on_renew for renewal_file in conf_files: display_util.notification("Processing " + renewal_file, pause=False) lineage_config = copy.deepcopy(config) lineagename = storage.lineagename_for_filename(renewal_file) # Note that this modifies config (to add back the configuration # elements from within the renewal configuration file). try: renewal_candidate = _reconstitute(lineage_config, renewal_file) except Exception as e: # pylint: disable=broad-except logger.error( "Renewal configuration file %s (cert: %s) " "produced an unexpected error: %s. Skipping.", renewal_file, lineagename, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) parse_failures.append(renewal_file) continue try: if renewal_candidate is None: parse_failures.append(renewal_file) else: # This call is done only for retro-compatibility purposes. # TODO: Remove this call once zope dependencies are removed from Certbot. zope.component.provideUtility(lineage_config, interfaces.IConfig) renewal_candidate.ensure_deployed() from certbot._internal import main plugins = plugins_disco.PluginsRegistry.find_all() if should_renew(lineage_config, renewal_candidate): # Apply random sleep upon first renewal if needed if apply_random_sleep: sleep_time = random.uniform(1, 60 * 8) logger.info( "Non-interactive renewal: random delay of %s seconds", sleep_time) time.sleep(sleep_time) # We will sleep only once this day, folks. apply_random_sleep = False # domains have been restored into lineage_config by reconstitute # but they're unnecessary anyway because renew_cert here # will just grab them from the certificate # we already know it's time to renew based on should_renew # and we have a lineage in renewal_candidate main.renew_cert(lineage_config, plugins, renewal_candidate) renew_successes.append(renewal_candidate.fullchain) else: expiry = crypto_util.notAfter( renewal_candidate.version( "cert", renewal_candidate.latest_common_version())) renew_skipped.append("%s expires on %s" % (renewal_candidate.fullchain, expiry.strftime("%Y-%m-%d"))) # Run updater interface methods updater.run_generic_updaters(lineage_config, renewal_candidate, plugins) except Exception as e: # pylint: disable=broad-except # obtain_cert (presumably) encountered an unanticipated problem. logger.error("Failed to renew certificate %s with error: %s", lineagename, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) renew_failures.append(renewal_candidate.fullchain) # Describe all the results _renew_describe_results(config, renew_successes, renew_failures, renew_skipped, parse_failures) if renew_failures or parse_failures: raise errors.Error("{0} renew failure(s), {1} parse failure(s)".format( len(renew_failures), len(parse_failures))) # Windows installer integration tests rely on handle_renewal_request behavior here. # If the text below changes, these tests will need to be updated accordingly. logger.debug("no renewal failures")
def handle_renewal_request(config): """Examine each lineage; renew if due and report results""" # This is trivially False if config.domains is empty if any(domain not in config.webroot_map for domain in config.domains): # If more plugins start using cli.add_domains, # we may want to only log a warning here raise errors.Error( "Currently, the renew verb is capable of either " "renewing all installed certificates that are due " "to be renewed or renewing a single certificate specified " "by its name. If you would like to renew specific " "certificates by their domains, use the certonly command " "instead. The renew verb may provide other options " "for selecting certificates to renew in the future.") if config.certname: conf_files = [ storage.renewal_file_for_certname(config, config.certname) ] else: conf_files = storage.renewal_conf_files(config) renew_successes = [] renew_failures = [] renew_skipped = [] parse_failures = [] for renewal_file in conf_files: disp = zope.component.getUtility(interfaces.IDisplay) disp.notification("Processing " + renewal_file, pause=False) lineage_config = copy.deepcopy(config) lineagename = storage.lineagename_for_filename(renewal_file) # Note that this modifies config (to add back the configuration # elements from within the renewal configuration file). try: renewal_candidate = _reconstitute(lineage_config, renewal_file) except Exception as e: # pylint: disable=broad-except logger.warning( "Renewal configuration file %s (cert: %s) " "produced an unexpected error: %s. Skipping.", renewal_file, lineagename, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) parse_failures.append(renewal_file) continue try: if renewal_candidate is None: parse_failures.append(renewal_file) else: # XXX: ensure that each call here replaces the previous one zope.component.provideUtility(lineage_config) renewal_candidate.ensure_deployed() from certbot import main plugins = plugins_disco.PluginsRegistry.find_all() if should_renew(lineage_config, renewal_candidate): # domains have been restored into lineage_config by reconstitute # but they're unnecessary anyway because renew_cert here # will just grab them from the certificate # we already know it's time to renew based on should_renew # and we have a lineage in renewal_candidate main.renew_cert(lineage_config, plugins, renewal_candidate) renew_successes.append(renewal_candidate.fullchain) else: expiry = crypto_util.notAfter( renewal_candidate.version( "cert", renewal_candidate.latest_common_version())) renew_skipped.append("%s expires on %s" % (renewal_candidate.fullchain, expiry.strftime("%Y-%m-%d"))) # Run updater interface methods updater.run_generic_updaters(lineage_config, renewal_candidate, plugins) except Exception as e: # pylint: disable=broad-except # obtain_cert (presumably) encountered an unanticipated problem. logger.warning( "Attempting to renew cert (%s) from %s produced an " "unexpected error: %s. Skipping.", lineagename, renewal_file, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) renew_failures.append(renewal_candidate.fullchain) # Describe all the results _renew_describe_results(config, renew_successes, renew_failures, renew_skipped, parse_failures) if renew_failures or parse_failures: raise errors.Error("{0} renew failure(s), {1} parse failure(s)".format( len(renew_failures), len(parse_failures))) else: logger.debug("no renewal failures")
def handle_renewal_request(config): """Examine each lineage; renew if due and report results""" # This is trivially False if config.domains is empty if any(domain not in config.webroot_map for domain in config.domains): # If more plugins start using cli.add_domains, # we may want to only log a warning here raise errors.Error("Currently, the renew verb is capable of either " "renewing all installed certificates that are due " "to be renewed or renewing a single certificate specified " "by its name. If you would like to renew specific " "certificates by their domains, use the certonly command " "instead. The renew verb may provide other options " "for selecting certificates to renew in the future.") if config.certname: conf_files = [storage.renewal_file_for_certname(config, config.certname)] else: conf_files = storage.renewal_conf_files(config) renew_successes = [] renew_failures = [] renew_skipped = [] parse_failures = [] for renewal_file in conf_files: disp = zope.component.getUtility(interfaces.IDisplay) disp.notification("Processing " + renewal_file, pause=False) lineage_config = copy.deepcopy(config) lineagename = storage.lineagename_for_filename(renewal_file) # Note that this modifies config (to add back the configuration # elements from within the renewal configuration file). try: renewal_candidate = _reconstitute(lineage_config, renewal_file) except Exception as e: # pylint: disable=broad-except logger.warning("Renewal configuration file %s (cert: %s) " "produced an unexpected error: %s. Skipping.", renewal_file, lineagename, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) parse_failures.append(renewal_file) continue try: if renewal_candidate is None: parse_failures.append(renewal_file) else: # XXX: ensure that each call here replaces the previous one zope.component.provideUtility(lineage_config) renewal_candidate.ensure_deployed() from certbot import main plugins = plugins_disco.PluginsRegistry.find_all() if should_renew(lineage_config, renewal_candidate): # domains have been restored into lineage_config by reconstitute # but they're unnecessary anyway because renew_cert here # will just grab them from the certificate # we already know it's time to renew based on should_renew # and we have a lineage in renewal_candidate main.renew_cert(lineage_config, plugins, renewal_candidate) renew_successes.append(renewal_candidate.fullchain) else: expiry = crypto_util.notAfter(renewal_candidate.version( "cert", renewal_candidate.latest_common_version())) renew_skipped.append("%s expires on %s" % (renewal_candidate.fullchain, expiry.strftime("%Y-%m-%d"))) # Run updater interface methods updater.run_generic_updaters(lineage_config, renewal_candidate, plugins) except Exception as e: # pylint: disable=broad-except # obtain_cert (presumably) encountered an unanticipated problem. logger.warning("Attempting to renew cert (%s) from %s produced an " "unexpected error: %s. Skipping.", lineagename, renewal_file, e) logger.debug("Traceback was:\n%s", traceback.format_exc()) renew_failures.append(renewal_candidate.fullchain) # Describe all the results _renew_describe_results(config, renew_successes, renew_failures, renew_skipped, parse_failures) if renew_failures or parse_failures: raise errors.Error("{0} renew failure(s), {1} parse failure(s)".format( len(renew_failures), len(parse_failures))) else: logger.debug("no renewal failures")