def human_readable_cert_info( config: configuration.NamespaceConfig, cert: storage.RenewableCert, skip_filter_checks: bool = False) -> Optional[str]: """ Returns a human readable description of info about a RenewableCert object""" certinfo = [] checker = ocsp.RevocationChecker() if config.certname and cert.lineagename != config.certname and not skip_filter_checks: return None if config.domains and not set(config.domains).issubset(cert.names()): return None now = pytz.UTC.fromutc(datetime.datetime.utcnow()) reasons = [] if cert.is_test_cert: reasons.append('TEST_CERT') if cert.target_expiry <= now: reasons.append('EXPIRED') elif checker.ocsp_revoked(cert): reasons.append('REVOKED') if reasons: status = "INVALID: " + ", ".join(reasons) else: diff = cert.target_expiry - now if diff.days == 1: status = "VALID: 1 day" elif diff.days < 1: status = "VALID: {0} hour(s)".format(diff.seconds // 3600) else: status = "VALID: {0} days".format(diff.days) valid_string = "{0} ({1})".format(cert.target_expiry, status) serial = format(crypto_util.get_serial_from_cert(cert.cert_path), 'x') certinfo.append(" Certificate Name: {}\n" " Serial Number: {}\n" " Key Type: {}\n" " Domains: {}\n" " Expiry Date: {}\n" " Certificate Path: {}\n" " Private Key Path: {}".format(cert.lineagename, serial, cert.private_key_type, " ".join(cert.names()), valid_string, cert.fullchain, cert.privkey)) return "".join(certinfo)
def renew_cert(config: configuration.NamespaceConfig, domains: Optional[List[str]], le_client: client.Client, lineage: storage.RenewableCert) -> None: """Renew a certificate lineage.""" renewal_params = lineage.configuration["renewalparams"] original_server = renewal_params.get("server", cli.flag_default("server")) _avoid_invalidating_lineage(config, lineage, original_server) if not domains: domains = lineage.names() # The private key is the existing lineage private key if reuse_key is set. # Otherwise, generate a fresh private key by passing None. if config.reuse_key: new_key = os.path.normpath(lineage.privkey) _update_renewal_params_from_key(new_key, config) else: new_key = None new_cert, new_chain, new_key, _ = le_client.obtain_certificate( domains, new_key) if config.dry_run: logger.debug("Dry run: skipping updating lineage at %s", os.path.dirname(lineage.cert)) else: prior_version = lineage.latest_common_version() # TODO: Check return value of save_successor lineage.save_successor(prior_version, new_cert, new_key.pem, new_chain, config) lineage.update_all_links_to(lineage.latest_common_version()) hooks.renew_hook(config, domains, lineage.live_dir)
def _avoid_invalidating_lineage(config: configuration.NamespaceConfig, lineage: storage.RenewableCert, original_server: str) -> None: """Do not renew a valid cert with one from a staging server!""" if util.is_staging(config.server): if not util.is_staging(original_server): if not config.break_my_certs: names = ", ".join(lineage.names()) raise errors.Error( "You've asked to renew/replace a seemingly valid certificate with " f"a test certificate (domains: {names}). We will not do that " "unless you use the --break-my-certs flag!")
def should_renew(config: configuration.NamespaceConfig, lineage: storage.RenewableCert) -> bool: """Return true if any of the circumstances for automatic renewal apply.""" if config.renew_by_default: logger.debug("Auto-renewal forced with --force-renewal...") return True if lineage.should_autorenew(): logger.info("Certificate is due for renewal, auto-renewing...") return True if config.dry_run: logger.info( "Certificate not due for renewal, but simulating renewal for dry run" ) return True display_util.notify("Certificate not yet due for renewal") return False
def update_certs_for_domain_matches(candidate_lineage: storage.RenewableCert, rv: Tuple[Optional[storage.RenewableCert], Optional[storage.RenewableCert]] ) -> Tuple[Optional[storage.RenewableCert], Optional[storage.RenewableCert]]: """Return cert as identical_names_cert if it matches, or subset_names_cert if it matches as subset """ # TODO: Handle these differently depending on whether they are # expired or still valid? identical_names_cert, subset_names_cert = rv 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)