diff --git a/lemur/certificates/cli.py b/lemur/certificates/cli.py index 88cfa134..b883dee0 100644 --- a/lemur/certificates/cli.py +++ b/lemur/certificates/cli.py @@ -23,7 +23,7 @@ from lemur.certificates.service import ( get_certificate_primitives, get_all_pending_reissue, get_by_name, - get_all_certs, + get_all_valid_certs, get, get_all_certs_attached_to_endpoint_without_autorotate, ) @@ -657,7 +657,14 @@ def check_revoked(): encounters an issue with verification it marks the certificate status as `unknown`. """ - for cert in get_all_certs(): + + log_data = { + "function": f"{__name__}.{sys._getframe().f_code.co_name}", + "message": "Checking for revoked Certificates" + } + + certs = get_all_valid_certs(current_app.config.get("SUPPORTED_REVOCATION_AUTHORITY_PLUGINS", [])) + for cert in certs: try: if cert.chain: status = verify_string(cert.body, cert.chain) @@ -666,6 +673,20 @@ def check_revoked(): cert.status = "valid" if status else "revoked" + if cert.status == "revoked": + log_data["valid"] = cert.status + log_data["certificate_name"] = cert.name + log_data["certificate_id"] = cert.id + metrics.send( + "certificate_revoked", + "counter", + 1, + metric_tags={"status": log_data["valid"], + "certificate_name": log_data["certificate_name"], + "certificate_id": log_data["certificate_id"]}, + ) + current_app.logger.info(log_data) + except Exception as e: sentry.captureException() current_app.logger.exception(e) diff --git a/lemur/certificates/service.py b/lemur/certificates/service.py index 5d1e6e63..f711bbd9 100644 --- a/lemur/certificates/service.py +++ b/lemur/certificates/service.py @@ -102,6 +102,27 @@ def get_all_certs(): return Certificate.query.all() +def get_all_valid_certs(authority_plugin_name): + """ + Retrieves all valid (not expired) certificates within Lemur, for the given authority plugin names + ignored if no authority_plugin_name provided. + + Note that depending on the DB size retrieving all certificates might an expensive operation + + :return: + """ + if authority_plugin_name: + return ( + Certificate.query.outerjoin(Authority, Authority.id == Certificate.authority_id).filter( + Certificate.not_after > arrow.now().format("YYYY-MM-DD")).filter( + Authority.plugin_name.in_(authority_plugin_name)).all() + ) + else: + return ( + Certificate.query.filter(Certificate.not_after > arrow.now().format("YYYY-MM-DD")).all() + ) + + def get_all_pending_cleaning_expired(source): """ Retrieves all certificates that are available for cleaning. These are certificates which are expired and are not diff --git a/lemur/certificates/verify.py b/lemur/certificates/verify.py index 76c6b521..989a2317 100644 --- a/lemur/certificates/verify.py +++ b/lemur/certificates/verify.py @@ -8,6 +8,7 @@ import requests import subprocess from flask import current_app +from lemur.extensions import sentry from requests.exceptions import ConnectionError, InvalidSchema from cryptography import x509 from cryptography.hazmat.backends import default_backend @@ -152,10 +153,18 @@ def verify(cert_path, issuer_chain_path): # OCSP is our main source of truth, in a lot of cases CRLs # have been deprecated and are no longer updated - verify_result = ocsp_verify(cert, cert_path, issuer_chain_path) + try: + verify_result = ocsp_verify(cert, cert_path, issuer_chain_path) + except Exception as e: + sentry.captureException() + current_app.logger.exception(e) if verify_result is None: - verify_result = crl_verify(cert, cert_path) + try: + verify_result = crl_verify(cert, cert_path) + except Exception as e: + sentry.captureException() + current_app.logger.exception(e) if verify_result is None: current_app.logger.debug("Failed to verify {}".format(cert.serial_number))