def check_revoked(): """ Function attempts to update Lemur's internal cache with revoked certificates. This is called periodically by Lemur. It checks both CRLs and OCSP to see if a certificate is revoked. If Lemur is unable encounters an issue with verification it marks the certificate status as `unknown`. """ 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) elif cert.issuer == '<selfsigned>': status = True else: status = verify_string(cert.body, "") 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) cert.status = "unknown" database.update(cert)
def create_certificate_check_destination_tasks(): """ This celery task fetches all (certificate, destination) pairs from Lemur and creates subtasks to verify that the certificate has been uploaded. :return: """ function = f"{__name__}.{sys._getframe().f_code.co_name}" logger = logging.getLogger(function) task_id = None if celery.current_task: task_id = celery.current_task.request.id log_data = { "task_id": task_id, } if task_id and is_task_active(function, task_id, None): logger.debug("Skipping task: Task is already active", extra=log_data) return log_data certs = certificate_service.get_all_valid_certs([]) num_subtasks_created = 0 for cert in certs: if cert.replaced or len(cert.destinations) == 0: continue for dest in cert.destinations: logger.debug( "creating sub task to check certificate/destination pair", extra={ "certificate": cert.name, "destination": str(dest), }, ) certificate_check_destination.delay(cert.id, dest.id) num_subtasks_created += 1 logger.debug( "task creation completed", extra={ **log_data, "num_subtasks_created": num_subtasks_created }, ) return log_data
def deactivate_entrust_certificates(): """ Attempt to deactivate test certificates issued by Entrust """ log_data = { "function": f"{__name__}.{sys._getframe().f_code.co_name}", "message": "Deactivating Entrust certificates" } certificates = get_all_valid_certs(['entrust-issuer']) entrust_plugin = plugins.get('entrust-issuer') for index, cert in enumerate(certificates): if (index % 10) == 0: # Entrust enforces a 10 request per 30s rate limit sleep(30) try: response = entrust_plugin.deactivate_certificate(cert) if response == 200: cert.status = "revoked" else: cert.status = "unknown" log_data["valid"] = cert.status log_data["certificate_name"] = cert.name log_data["certificate_id"] = cert.id metrics.send( "certificate_deactivate", "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) database.update(cert) except Exception as e: current_app.logger.info(log_data) sentry.captureException() current_app.logger.exception(e)
def check_revoked(): """ Function attempts to update Lemur's internal cache with revoked certificates. This is called periodically by Lemur. It checks both CRLs and OCSP to see if a certificate is revoked. If Lemur is unable encounters an issue with verification it marks the certificate status as `unknown`. """ log_data = { "function": f"{__name__}.{sys._getframe().f_code.co_name}", "message": "Checking for revoked Certificates" } there_are_still_certs = True page = 1 count = 1000 ocsp_err_count = 0 crl_err_count = 0 while there_are_still_certs: # get all valid certs issued until day before. This is to avoid OCSP not knowing about a newly created cert. certs = get_all_valid_certs( current_app.config.get("SUPPORTED_REVOCATION_AUTHORITY_PLUGINS", []), paginate=True, page=page, count=count, created_on_or_before=arrow.now().shift(days=-1)) if len(certs) < count: # this must be tha last page there_are_still_certs = False else: metrics.send("certificate_revoked_progress", "counter", 1, metric_tags={"page": page}) page += 1 for cert in certs: try: if cert.chain: status, ocsp_err, crl_err = verify_string( cert.body, cert.chain) else: status, ocsp_err, crl_err = verify_string(cert.body, "") ocsp_err_count += ocsp_err crl_err_count += crl_err if status is None: cert.status = "unknown" else: 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: capture_exception() current_app.logger.warning(e) cert.status = "unknown" try: database.update(cert) except Exception as e: capture_exception() current_app.logger.warning(e) metrics.send( "certificate_revoked_ocsp_error", "gauge", ocsp_err_count, ) metrics.send( "certificate_revoked_crl_error", "gauge", crl_err_count, ) metrics.send( "certificate_revoked_checked", "gauge", (page - 1) * count + len(certs), )