lemur/lemur/plugins/lemur_openssl/plugin.py
2019-05-16 07:57:02 -07:00

151 lines
4.3 KiB
Python

"""
.. module: lemur.plugins.lemur_openssl.plugin
:platform: Unix
:copyright: (c) 2018 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
"""
from io import open
import subprocess
from flask import current_app
from lemur.utils import mktempfile, mktemppath
from lemur.plugins.bases import ExportPlugin
from lemur.plugins import lemur_openssl as openssl
from lemur.common.utils import get_psuedo_random_string, parse_certificate
from lemur.common.defaults import common_name
def run_process(command):
"""
Runs a given command with pOpen and wraps some
error handling around it.
:param command:
:return:
"""
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
current_app.logger.debug(command)
stdout, stderr = p.communicate()
if p.returncode != 0:
current_app.logger.debug(" ".join(command))
current_app.logger.error(stderr)
raise Exception(stderr)
def create_pkcs12(cert, chain, p12_tmp, key, alias, passphrase):
"""
Creates a pkcs12 formated file.
:param cert:
:param chain:
:param p12_tmp:
:param key:
:param alias:
:param passphrase:
"""
assert isinstance(cert, str)
assert isinstance(chain, str)
assert isinstance(key, str)
with mktempfile() as key_tmp:
with open(key_tmp, "w") as f:
f.write(key)
# Create PKCS12 keystore from private key and public certificate
with mktempfile() as cert_tmp:
with open(cert_tmp, "w") as f:
if chain:
f.writelines([cert.strip() + "\n", chain.strip() + "\n"])
else:
f.writelines([cert.strip() + "\n"])
run_process(
[
"openssl",
"pkcs12",
"-export",
"-name",
alias,
"-in",
cert_tmp,
"-inkey",
key_tmp,
"-out",
p12_tmp,
"-password",
"pass:{}".format(passphrase),
]
)
class OpenSSLExportPlugin(ExportPlugin):
title = "OpenSSL"
slug = "openssl-export"
description = "Is a loose interface to openssl and support various formats"
version = openssl.VERSION
author = "Kevin Glisson"
author_url = "https://github.com/netflix/lemur"
options = [
{
"name": "type",
"type": "select",
"required": True,
"available": ["PKCS12 (.p12)"],
"helpMessage": "Choose the format you wish to export",
},
{
"name": "passphrase",
"type": "str",
"required": False,
"helpMessage": "If no passphrase is given one will be generated for you, we highly recommend this.",
"validation": "",
},
{
"name": "alias",
"type": "str",
"required": False,
"helpMessage": "Enter the alias you wish to use for the keystore.",
},
]
def export(self, body, chain, key, options, **kwargs):
"""
Generates a PKCS#12 archive.
:param key:
:param chain:
:param body:
:param options:
:param kwargs:
"""
if self.get_option("passphrase", options):
passphrase = self.get_option("passphrase", options)
else:
passphrase = get_psuedo_random_string()
if self.get_option("alias", options):
alias = self.get_option("alias", options)
else:
alias = common_name(parse_certificate(body))
type = self.get_option("type", options)
with mktemppath() as output_tmp:
if type == "PKCS12 (.p12)":
if not key:
raise Exception("Private Key required by {0}".format(type))
create_pkcs12(body, chain, output_tmp, key, alias, passphrase)
extension = "p12"
else:
raise Exception("Unable to export, unsupported type: {0}".format(type))
with open(output_tmp, "rb") as f:
raw = f.read()
return extension, passphrase, raw