Source code for ocspd.core.certparser

# -*- coding: utf-8 -*-
"""
This module parses certificate in a queue so the data contained in the
certificate can be used to request OCSP responses. After parsing a new
:class:`ocspd.core.taskcontext.OCSPTaskContext` is created for the
:class:`ocspd.core.oscprenewe.OCSPRenewer` which is then scheduled to be
processed ASAP.
"""

import threading
import datetime
import queue
import ocspd.core.log
from ocspd.core.excepthandler import ocsp_except_handle
from ocspd.core.taskcontext import OCSPTaskContext

LOG = ocspd.core.log.get_logger(__name__)



[docs]class CertParserThread(threading.Thread): """ This object makes sure certificate files are parsed, after which a task context is created for the :class:`ocspd.core.oscprenewer.OCSPRenewer` which is scheduled to be executed ASAP. """
[docs] def __init__(self, *args, **kwargs): """ Initialise the thread with its parent :class:`threading.Thread` and its arguments. :kwarg dict models: A dict to maintain a model cache **(required)**. :kwarg int minimum_validity: The amount of seconds the OCSP staple should be valid for before a renewal is scheduled **(required)**. :kwarg ocspd.scheduling.SchedulerThread scheduler: The scheduler object where we can get parser tasks from and add renew tasks to. **(required)**. :kwarg bool no_recycle: Don't recycle existing staples (default=False) """ self.stop = False self.models = kwargs.pop('models', None) self.minimum_validity = kwargs.pop('minimum_validity', None) self.scheduler = kwargs.pop('scheduler', None) self.no_recycle = kwargs.pop('no_recycle', False) assert self.models is not None, \ "You need to pass a dict to hold the certificate model cache." assert self.minimum_validity is not None, \ "You need to pass the minimum_validity." assert self.scheduler is not None, \ "Please pass a scheduler to get tasks from and add tasks to." super(CertParserThread, self).__init__(*args, **kwargs)
[docs] def run(self): """ Start the certificate parser thread. """ LOG.info("Started a parser thread.") while not self.stop: try: context = self.scheduler.get_task("parse", timeout=0.25) with ocsp_except_handle(context): self.parse_certificate(context.model) # If the parsing action fails, the error handler will # reschedule it if it makes sense, if not a log message will be # emitted that it will be ignored, when the certificate file # is changed the finder will schedule it to be parsed again. self.scheduler.task_done("parse") except queue.Empty: pass LOG.debug("Goodbye cruel world..")
[docs] def parse_certificate(self, model): """ Parse certificate files and check whether an existing OCSP staple that is still valid exists. If so, use it, if not request a new OCSP staple. If the staple is valid but not valid for longer than the ``minimum_validity``, the staple is loaded but a new request is still scheduled. """ LOG.info("Parsing certificate for file \"%s\"..", model) # Parse the certificate model.parse_crt_file() # If there is a valid existing staple, use it.. if not self.no_recycle and model.recycle_staple(self.minimum_validity): # There is a valid staple file, schedule a regular renewal until = model.ocsp_staple.valid_until sched_time = until - datetime.timedelta( seconds=self.minimum_validity) else: # No existing staple file or invalid, renew ASAP. sched_time = None # Schedule a renewal of the OCSP staple context = OCSPTaskContext( task_name="renew", model=model, sched_time=sched_time) self.scheduler.add_task(context)