From cd9c11221808af63d4d5eb6a8ef598283ee4761c Mon Sep 17 00:00:00 2001 From: Charles Hendrie Date: Sat, 22 Oct 2016 02:52:18 -0500 Subject: [PATCH] Implement a CFSSL issuer plugin (#452) * Implement CFSSL issuer plugin Implement a Lemur plugin for generating certificates from the open source certificate authority CFSSL (https://github.com/cloudflare/cfssl). The plugin interacts with CFSSL through the CFSSL REST API. The CFSSL configuration is defined in the lemur.conf.py property file using property names prefixed with "CFSSL_". * Update documentation to include CFSSL plugin --- docs/administration.rst | 32 +++++++++- .../internals/lemur.plugins.lemur_cfssl.rst | 20 ++++++ docs/developer/internals/lemur.plugins.rst | 1 + lemur/plugins/lemur_cfssl/__init__.py | 5 ++ lemur/plugins/lemur_cfssl/plugin.py | 64 +++++++++++++++++++ lemur/plugins/lemur_cfssl/tests/conftest.py | 1 + lemur/plugins/lemur_cfssl/tests/test_cfssl.py | 6 ++ setup.py | 1 + 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 docs/developer/internals/lemur.plugins.lemur_cfssl.rst create mode 100644 lemur/plugins/lemur_cfssl/__init__.py create mode 100644 lemur/plugins/lemur_cfssl/plugin.py create mode 100644 lemur/plugins/lemur_cfssl/tests/conftest.py create mode 100644 lemur/plugins/lemur_cfssl/tests/test_cfssl.py diff --git a/docs/administration.rst b/docs/administration.rst index 60952152..ff066c2d 100644 --- a/docs/administration.rst +++ b/docs/administration.rst @@ -361,6 +361,26 @@ for those plugins. This is the root to be used for your CA chain +CFSSL Issuer Plugin +^^^^^^^^^^^^^^^^^^^ + +The following configuration properties are required to use the the CFSSL issuer plugin. + +.. data:: CFSSL_URL + :noindex: + + This is the URL for the CFSSL API + +.. data:: CFSSL_ROOT + :noindex: + + This is the root to be used for your CA chain + +.. data:: CFSSL_INTERMEDIATE + :noindex: + + This is the intermediate to be used for your CA chain + AWS Source/Destination Plugin ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -836,6 +856,17 @@ Openssl Leverages Openssl to support additional export formats (pkcs12) +CFSSL +----- + +:Authors: + Charles Hendrie +:Type: + Issuer +:Description: + Basic support for generating certificates from the private certificate authority CFSSL + + 3rd Party Plugins ================= @@ -886,4 +917,3 @@ These permissions are applied to the user upon login and refreshed on every requ .. seealso:: `Flask-Principal `_ - diff --git a/docs/developer/internals/lemur.plugins.lemur_cfssl.rst b/docs/developer/internals/lemur.plugins.lemur_cfssl.rst new file mode 100644 index 00000000..6ea2875e --- /dev/null +++ b/docs/developer/internals/lemur.plugins.lemur_cfssl.rst @@ -0,0 +1,20 @@ +lemur_cfssl Package +=================== + +:mod:`lemur_cfssl` Package +-------------------------- + +.. automodule:: lemur.plugins.lemur_cfssl + :noindex: + :members: + :undoc-members: + :show-inheritance: + +:mod:`plugin` Module +-------------------- + +.. automodule:: lemur.plugins.lemur_cfssl.plugin + :noindex: + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/developer/internals/lemur.plugins.rst b/docs/developer/internals/lemur.plugins.rst index 4b021c5c..bd440e8e 100644 --- a/docs/developer/internals/lemur.plugins.rst +++ b/docs/developer/internals/lemur.plugins.rst @@ -27,5 +27,6 @@ Subpackages lemur.plugins.base lemur.plugins.bases lemur.plugins.lemur_aws + lemur.plugins.lemur_cfssl lemur.plugins.lemur_email lemur.plugins.lemur_verisign diff --git a/lemur/plugins/lemur_cfssl/__init__.py b/lemur/plugins/lemur_cfssl/__init__.py new file mode 100644 index 00000000..8ce5a7f3 --- /dev/null +++ b/lemur/plugins/lemur_cfssl/__init__.py @@ -0,0 +1,5 @@ +try: + VERSION = __import__('pkg_resources') \ + .get_distribution(__name__).version +except Exception as e: + VERSION = 'unknown' diff --git a/lemur/plugins/lemur_cfssl/plugin.py b/lemur/plugins/lemur_cfssl/plugin.py new file mode 100644 index 00000000..76cc4b24 --- /dev/null +++ b/lemur/plugins/lemur_cfssl/plugin.py @@ -0,0 +1,64 @@ +""" +.. module: lemur.plugins.lemur_cfssl.plugin + :platform: Unix + :synopsis: This module is responsible for communicating with the CFSSL private CA. + :copyright: (c) 2016 by Thomson Reuters + :license: Apache, see LICENSE for more details. + +.. moduleauthor:: Charles Hendrie +""" + +import json +import requests + +from flask import current_app + +from lemur.plugins.bases import IssuerPlugin +from lemur.plugins import lemur_cfssl as cfssl + + +class CfsslIssuerPlugin(IssuerPlugin): + title = 'CFSSL' + slug = 'cfssl-issuer' + description = 'Enables the creation of certificates by CFSSL private CA' + version = cfssl.VERSION + + author = 'Charles Hendrie' + author_url = 'https://github.com/netflix/lemur.git' + + def __init__(self, *args, **kwargs): + self.session = requests.Session() + super(CfsslIssuerPlugin, self).__init__(*args, **kwargs) + + def create_certificate(self, csr, issuer_options): + """ + Creates a CFSSL certificate. + + :param csr: + :param issuer_options: + :return: + """ + current_app.logger.info("Requesting a new cfssl certificate with csr: {0}".format(csr)) + + url = "{0}{1}".format(current_app.config.get('CFSSL_URL'), '/api/v1/cfssl/sign') + + data = {'certificate_request': csr.decode('utf_8')} + data = json.dumps(data) + + response = self.session.post(url, data=data.encode(encoding='utf_8', errors='strict')) + response_json = json.loads(response.content.decode('utf_8')) + cert = response_json['result']['certificate'] + + return cert, current_app.config.get('CFSSL_INTERMEDIATE'), + + @staticmethod + def create_authority(options): + """ + Creates an authority, this authority is then used by Lemur to allow a user + to specify which Certificate Authority they want to sign their certificate. + + :param options: + :return: + """ + role = {'username': '', 'password': '', 'name': 'cfssl'} + return current_app.config.get('CFSSL_ROOT'), "", [role] diff --git a/lemur/plugins/lemur_cfssl/tests/conftest.py b/lemur/plugins/lemur_cfssl/tests/conftest.py new file mode 100644 index 00000000..0e1cd89f --- /dev/null +++ b/lemur/plugins/lemur_cfssl/tests/conftest.py @@ -0,0 +1 @@ +from lemur.tests.conftest import * # noqa diff --git a/lemur/plugins/lemur_cfssl/tests/test_cfssl.py b/lemur/plugins/lemur_cfssl/tests/test_cfssl.py new file mode 100644 index 00000000..ea8f0856 --- /dev/null +++ b/lemur/plugins/lemur_cfssl/tests/test_cfssl.py @@ -0,0 +1,6 @@ + +def test_get_certificates(app): + from lemur.plugins.base import plugins + + p = plugins.get('cfssl-issuer') + assert p diff --git a/setup.py b/setup.py index 865531be..52d4afcd 100644 --- a/setup.py +++ b/setup.py @@ -184,6 +184,7 @@ setup( 'atlas_metric = lemur.plugins.lemur_atlas.plugin:AtlasMetricPlugin', 'kubernetes_destination = lemur.plugins.lemur_kubernetes.plugin:KubernetesDestinationPlugin', 'cryptography_issuer = lemur.plugins.lemur_cryptography.plugin:CryptographyIssuerPlugin', + 'cfssl_issuer = lemur.plugins.lemur_cfssl.plugin:CfsslIssuerPlugin', ], }, classifiers=[