Merge branch 'lemur_vault_plugin' of github.com:/alwaysjolley/lemur into lemur_vault_plugin

This commit is contained in:
alwaysjolley
2019-03-05 07:22:18 -05:00
28 changed files with 591 additions and 110 deletions

View File

@ -0,0 +1,6 @@
"""Set the version information."""
try:
VERSION = __import__('pkg_resources') \
.get_distribution(__name__).version
except Exception as e:
VERSION = 'unknown'

View File

@ -0,0 +1,116 @@
from lemur.plugins.bases import IssuerPlugin, SourcePlugin
import requests
from lemur.plugins import lemur_adcs as ADCS
from certsrv import Certsrv
from OpenSSL import crypto
from flask import current_app
class ADCSIssuerPlugin(IssuerPlugin):
title = 'ADCS'
slug = 'adcs-issuer'
description = 'Enables the creation of certificates by ADCS (Active Directory Certificate Services)'
version = ADCS.VERSION
author = 'sirferl'
author_url = 'https://github.com/sirferl/lemur'
def __init__(self, *args, **kwargs):
"""Initialize the issuer with the appropriate details."""
self.session = requests.Session()
super(ADCSIssuerPlugin, self).__init__(*args, **kwargs)
@staticmethod
def create_authority(options):
"""Create an authority.
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:
"""
adcs_root = current_app.config.get('ADCS_ROOT')
adcs_issuing = current_app.config.get('ADCS_ISSUING')
role = {'username': '', 'password': '', 'name': 'adcs'}
return adcs_root, adcs_issuing, [role]
def create_certificate(self, csr, issuer_options):
adcs_server = current_app.config.get('ADCS_SERVER')
adcs_user = current_app.config.get('ADCS_USER')
adcs_pwd = current_app.config.get('ADCS_PWD')
adcs_auth_method = current_app.config.get('ADCS_AUTH_METHOD')
adcs_template = current_app.config.get('ADCS_TEMPLATE')
ca_server = Certsrv(adcs_server, adcs_user, adcs_pwd, auth_method=adcs_auth_method)
current_app.logger.info("Requesting CSR: {0}".format(csr))
current_app.logger.info("Issuer options: {0}".format(issuer_options))
cert, req_id = ca_server.get_cert(csr, adcs_template, encoding='b64').decode('utf-8').replace('\r\n', '\n')
chain = ca_server.get_ca_cert(encoding='b64').decode('utf-8').replace('\r\n', '\n')
return cert, chain, req_id
def revoke_certificate(self, certificate, comments):
raise NotImplementedError('Not implemented\n', self, certificate, comments)
def get_ordered_certificate(self, order_id):
raise NotImplementedError('Not implemented\n', self, order_id)
def canceled_ordered_certificate(self, pending_cert, **kwargs):
raise NotImplementedError('Not implemented\n', self, pending_cert, **kwargs)
class ADCSSourcePlugin(SourcePlugin):
title = 'ADCS'
slug = 'adcs-source'
description = 'Enables the collecion of certificates'
version = ADCS.VERSION
author = 'sirferl'
author_url = 'https://github.com/sirferl/lemur'
options = [
{
'name': 'dummy',
'type': 'str',
'required': False,
'validation': '/^[0-9]{12,12}$/',
'helpMessage': 'Just to prevent error'
}
]
def get_certificates(self, options, **kwargs):
adcs_server = current_app.config.get('ADCS_SERVER')
adcs_user = current_app.config.get('ADCS_USER')
adcs_pwd = current_app.config.get('ADCS_PWD')
adcs_auth_method = current_app.config.get('ADCS_AUTH_METHOD')
adcs_start = current_app.config.get('ADCS_START')
adcs_stop = current_app.config.get('ADCS_STOP')
ca_server = Certsrv(adcs_server, adcs_user, adcs_pwd, auth_method=adcs_auth_method)
out_certlist = []
for id in range(adcs_start, adcs_stop):
try:
cert = ca_server.get_existing_cert(id, encoding='b64').decode('utf-8').replace('\r\n', '\n')
except Exception as err:
if '{0}'.format(err).find("CERTSRV_E_PROPERTY_EMPTY"):
# this error indicates end of certificate list(?), so we stop
break
else:
# We do nothing in case there is no certificate returned for other reasons
current_app.logger.info("Error with id {0}: {1}".format(id, err))
else:
# we have a certificate
pubkey = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
# loop through extensions to see if we find "TLS Web Server Authentication"
for e_id in range(0, pubkey.get_extension_count() - 1):
try:
extension = '{0}'.format(pubkey.get_extension(e_id))
except Exception:
extensionn = ''
if extension.find("TLS Web Server Authentication") != -1:
out_certlist.append({
'name': format(pubkey.get_subject().CN),
'body': cert})
break
return out_certlist
def get_endpoints(self, options, **kwargs):
# There are no endpoints in the ADCS
raise NotImplementedError('Not implemented\n', self, options, **kwargs)

View File

@ -64,6 +64,7 @@ def upload_cert(name, body, private_key, path, cert_chain=None, **kwargs):
:param path:
:return:
"""
assert isinstance(private_key, str)
client = kwargs.pop('client')
if not path or path == '/':
@ -72,8 +73,6 @@ def upload_cert(name, body, private_key, path, cert_chain=None, **kwargs):
name = name + '-' + path.strip('/')
try:
if isinstance(private_key, bytes):
private_key = private_key.decode("utf-8")
if cert_chain:
return client.upload_server_certificate(
Path=path,

View File

@ -14,6 +14,7 @@ from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from lemur.common.utils import parse_private_key
from lemur.plugins.bases import IssuerPlugin
from lemur.plugins import lemur_cryptography as cryptography_issuer
@ -40,7 +41,8 @@ def issue_certificate(csr, options, private_key=None):
if options.get("authority"):
# Issue certificate signed by an existing lemur_certificates authority
issuer_subject = options['authority'].authority_certificate.subject
issuer_private_key = options['authority'].authority_certificate.private_key
assert private_key is None, "Private would be ignored, authority key used instead"
private_key = options['authority'].authority_certificate.private_key
chain_cert_pem = options['authority'].authority_certificate.body
authority_key_identifier_public = options['authority'].authority_certificate.public_key
authority_key_identifier_subject = x509.SubjectKeyIdentifier.from_public_key(authority_key_identifier_public)
@ -52,7 +54,6 @@ def issue_certificate(csr, options, private_key=None):
else:
# Issue certificate that is self-signed (new lemur_certificates root authority)
issuer_subject = csr.subject
issuer_private_key = private_key
chain_cert_pem = ""
authority_key_identifier_public = csr.public_key()
authority_key_identifier_subject = None
@ -112,11 +113,7 @@ def issue_certificate(csr, options, private_key=None):
# FIXME: Not implemented in lemur/schemas.py yet https://github.com/Netflix/lemur/issues/662
pass
private_key = serialization.load_pem_private_key(
bytes(str(issuer_private_key).encode('utf-8')),
password=None,
backend=default_backend()
)
private_key = parse_private_key(private_key)
cert = builder.sign(private_key, hashes.SHA256(), default_backend())
cert_pem = cert.public_bytes(

View File

@ -38,14 +38,9 @@ def create_csr(cert, chain, csr_tmp, key):
:param csr_tmp:
:param key:
"""
if isinstance(cert, bytes):
cert = cert.decode('utf-8')
if isinstance(chain, bytes):
chain = chain.decode('utf-8')
if isinstance(key, bytes):
key = key.decode('utf-8')
assert isinstance(cert, str)
assert isinstance(chain, str)
assert isinstance(key, str)
with mktempfile() as key_tmp:
with open(key_tmp, 'w') as f:

View File

@ -15,6 +15,8 @@ from cryptography.fernet import Fernet
from lemur.utils import mktempfile, mktemppath
from lemur.plugins.bases import ExportPlugin
from lemur.plugins import lemur_java as java
from lemur.common.utils import parse_certificate
from lemur.common.defaults import common_name
def run_process(command):
@ -59,11 +61,8 @@ def split_chain(chain):
def create_truststore(cert, chain, jks_tmp, alias, passphrase):
if isinstance(cert, bytes):
cert = cert.decode('utf-8')
if isinstance(chain, bytes):
chain = chain.decode('utf-8')
assert isinstance(cert, str)
assert isinstance(chain, str)
with mktempfile() as cert_tmp:
with open(cert_tmp, 'w') as f:
@ -98,14 +97,9 @@ def create_truststore(cert, chain, jks_tmp, alias, passphrase):
def create_keystore(cert, chain, jks_tmp, key, alias, passphrase):
if isinstance(cert, bytes):
cert = cert.decode('utf-8')
if isinstance(chain, bytes):
chain = chain.decode('utf-8')
if isinstance(key, bytes):
key = key.decode('utf-8')
assert isinstance(cert, str)
assert isinstance(chain, str)
assert isinstance(key, str)
# Create PKCS12 keystore from private key and public certificate
with mktempfile() as cert_tmp:
@ -241,7 +235,7 @@ class JavaKeystoreExportPlugin(ExportPlugin):
if self.get_option('alias', options):
alias = self.get_option('alias', options)
else:
alias = "blah"
alias = common_name(parse_certificate(body))
with mktemppath() as jks_tmp:
create_keystore(body, chain, jks_tmp, key, alias, passphrase)

View File

@ -14,7 +14,8 @@ 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
from lemur.common.utils import get_psuedo_random_string, parse_certificate
from lemur.common.defaults import common_name
def run_process(command):
@ -44,14 +45,9 @@ def create_pkcs12(cert, chain, p12_tmp, key, alias, passphrase):
:param alias:
:param passphrase:
"""
if isinstance(cert, bytes):
cert = cert.decode('utf-8')
if isinstance(chain, bytes):
chain = chain.decode('utf-8')
if isinstance(key, bytes):
key = key.decode('utf-8')
assert isinstance(cert, str)
assert isinstance(chain, str)
assert isinstance(key, str)
with mktempfile() as key_tmp:
with open(key_tmp, 'w') as f:
@ -127,7 +123,7 @@ class OpenSSLExportPlugin(ExportPlugin):
if self.get_option('alias', options):
alias = self.get_option('alias', options)
else:
alias = "blah"
alias = common_name(parse_certificate(body))
type = self.get_option('type', options)