From 82b43b5a9d29ad8e21affe995fcc48916b2d8721 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Tue, 29 Aug 2017 03:35:56 +0300 Subject: [PATCH] Create signal hooks and handler for dumping CSR and certificate details (#882) --- docs/administration.rst | 6 ++++++ lemur/certificates/hooks.py | 38 +++++++++++++++++++++++++++++++++++ lemur/certificates/service.py | 17 ++++++++++++++-- lemur/extensions.py | 3 +++ lemur/factory.py | 5 +++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 lemur/certificates/hooks.py diff --git a/docs/administration.rst b/docs/administration.rst index c69f2586..42682424 100644 --- a/docs/administration.rst +++ b/docs/administration.rst @@ -120,6 +120,12 @@ Basic Configuration LEMUR_ENCRYPTION_KEYS = ['1YeftooSbxCiX2zo8m1lXtpvQjy27smZcUUaGmffhMY=', 'LAfQt6yrkLqOK5lwpvQcT4jf2zdeTQJV1uYeh9coT5s='] +.. data:: DEBUG_DUMP + :noindex: + + Dump all imported or generated CSR and certificate details to stdout using OpenSSL. (default: `False`) + + Certificate Default Options --------------------------- diff --git a/lemur/certificates/hooks.py b/lemur/certificates/hooks.py new file mode 100644 index 00000000..e352a4d5 --- /dev/null +++ b/lemur/certificates/hooks.py @@ -0,0 +1,38 @@ +""" +Debugging hooks for dumping imported or generated CSR and certificate details to stdout via OpenSSL. + +.. module: lemur.certificates.hooks + :platform: Unix + :copyright: (c) 2016-2017 by Marti Raudsepp, see AUTHORS for more + :license: Apache, see LICENSE for more details. + +.. moduleauthor:: Marti Raudsepp +""" +import subprocess + +from flask import current_app + +from lemur.certificates.service import csr_created, csr_imported, certificate_issued, certificate_imported + + +def csr_dump_handler(sender, csr, **kwargs): + try: + subprocess.run(['openssl', 'req', '-text', '-noout', '-reqopt', 'no_sigdump,no_pubkey'], + input=csr.encode('utf8')) + except Exception as err: + current_app.logger.warning("Error inspecting CSR: %s", err) + + +def cert_dump_handler(sender, certificate, **kwargs): + try: + subprocess.run(['openssl', 'x509', '-text', '-noout', '-certopt', 'no_sigdump,no_pubkey'], + input=certificate.body.encode('utf8')) + except Exception as err: + current_app.logger.warning("Error inspecting certificate: %s", err) + + +def activate_debug_dump(): + csr_created.connect(csr_dump_handler) + csr_imported.connect(csr_dump_handler) + certificate_issued.connect(cert_dump_handler) + certificate_imported.connect(cert_dump_handler) diff --git a/lemur/certificates/service.py b/lemur/certificates/service.py index da613516..4ad7c219 100644 --- a/lemur/certificates/service.py +++ b/lemur/certificates/service.py @@ -15,7 +15,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from lemur import database -from lemur.extensions import metrics +from lemur.extensions import metrics, signals from lemur.plugins.base import plugins from lemur.common.utils import generate_private_key @@ -31,6 +31,12 @@ from lemur.certificates.schemas import CertificateOutputSchema, CertificateInput from lemur.roles import service as role_service +csr_created = signals.signal('csr_created', "CSR generated") +csr_imported = signals.signal('csr_imported', "CSR imported from external source") +certificate_issued = signals.signal('certificate_issued', "Authority issued a certificate") +certificate_imported = signals.signal('certificate_imported', "Certificate imported from external source") + + def get(cert_id): """ Retrieves certificate by its ID. @@ -168,9 +174,11 @@ def mint(**kwargs): # allow the CSR to be specified by the user if not kwargs.get('csr'): csr, private_key = create_csr(**kwargs) + csr_created.send(authority=authority, csr=csr) else: csr = str(kwargs.get('csr')) private_key = None + csr_imported.send(authority=authority, csr=csr) cert_body, cert_chain = issuer.create_certificate(csr, kwargs) return cert_body, private_key, cert_chain, @@ -216,7 +224,10 @@ def upload(**kwargs): cert = database.create(cert) kwargs['creator'].certificates.append(cert) - return database.update(cert) + + cert = database.update(cert) + certificate_imported.send(certificate=cert, authority=cert.authority) + return cert def create(**kwargs): @@ -239,6 +250,8 @@ def create(**kwargs): kwargs['creator'].certificates.append(cert) cert.authority = kwargs['authority'] + certificate_issued.send(certificate=cert, authority=cert.authority) + database.commit() metrics.send('certificate_issued', 'counter', 1, metric_tags=dict(owner=cert.owner, issuer=cert.issuer)) diff --git a/lemur/extensions.py b/lemur/extensions.py index 2e631fe4..b5a18569 100644 --- a/lemur/extensions.py +++ b/lemur/extensions.py @@ -23,3 +23,6 @@ metrics = Metrics() from raven.contrib.flask import Sentry sentry = Sentry() + +from blinker import Namespace +signals = Namespace() diff --git a/lemur/factory.py b/lemur/factory.py index 52e0db9e..bc96c27e 100644 --- a/lemur/factory.py +++ b/lemur/factory.py @@ -18,6 +18,8 @@ from logging import Formatter, StreamHandler from logging.handlers import RotatingFileHandler from flask import Flask + +from lemur.certificates.hooks import activate_debug_dump from lemur.common.health import mod as health from lemur.extensions import db, migrate, principal, smtp_mail, metrics, sentry @@ -157,6 +159,9 @@ def configure_logging(app): stream_handler.setLevel(app.config.get('LOG_LEVEL', 'DEBUG')) app.logger.addHandler(stream_handler) + if app.config.get('DEBUG_DUMP', False): + activate_debug_dump() + def install_plugins(app): """