Merge branch 'lemur_vault_plugin' of github.com:/alwaysjolley/lemur into lemur_vault_plugin
This commit is contained in:
6
lemur/plugins/lemur_adcs/__init__.py
Normal file
6
lemur/plugins/lemur_adcs/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""Set the version information."""
|
||||
try:
|
||||
VERSION = __import__('pkg_resources') \
|
||||
.get_distribution(__name__).version
|
||||
except Exception as e:
|
||||
VERSION = 'unknown'
|
116
lemur/plugins/lemur_adcs/plugin.py
Normal file
116
lemur/plugins/lemur_adcs/plugin.py
Normal 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)
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user