a function to generate a keystore and cert files for self-signed ssl authentication

def generate_keystore(key_alias, key_folder='./', root_cert='', truststore='', password='', organization='', organization_unit='', locality='', country='', key_size=2048, verbose=True, overwrite=False):

    ''' a function to generate a keystore and cert files for self-signed ssl authentication '''

    title = 'generate_keystore'
    
# import dependencies
    import os
    from subprocess import call, STDOUT, Popen, PIPE
    DEVNULL = open(os.devnull, 'w')

# define system call
    def _call(sys_command, ignore='', prompt_input='', title=''):
        if title and verbose:
            print('%s ... ' % title, end='', flush=True)
        p = Popen(sys_command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
        if prompt_input:
            stdout, stderr = p.communicate(str('%s\n' % prompt_input).encode('utf-8'))
        if p.returncode != 0:
            cmd_err = p.stdout.read().decode()
            if not cmd_err:
                pass
            elif ignore:
                if not cmd_err.find(ignore) > -1:
                    raise Exception(cmd_err)
            else:
                if title and verbose:
                    print('ERROR.')
                raise Exception(cmd_err)
        if title and verbose:
            print('done.')

# verify libraries
    try:
        call('openssl version', shell=True, stdout=DEVNULL)
    except:
        raise Exception('%s requires openssl library. try: sudo apt-get install openssl' % title)
    try:
        _call('keytool -help', ignore='Key and Certificate Management Tool')
    except:
        raise Exception('%s requires keytool library. try: sudo apt-get install openjdk-8-jre' % title)

# validate input
    if not isinstance(key_alias, str):
        raise ValueError('%s(key_alias="...") must be a string datatype.' % title)
    if not key_size in (2048, 4096):
        raise ValueError('%s(key_size=%s must be either 2048 or 4096' % (title, key_size))
    import re
    input_fields = {
        'organization': organization,
        'organization_unit': organization_unit,
        'locality': locality,
        'country': country
    }
    for key, value in input_fields.items():
        if re.findall('[^\w_\-\s]', value):
            raise ValueError('%s(%s="%s") must contain only alphanumeric characters, _, - and spaces.' % (title, key, value))

# construct key folder
    from os import path, makedirs, remove
    if not path.exists(key_folder):
        makedirs(key_folder)
    elif not path.isdir(key_folder):
        raise ValueError('%s(key_folder="%s") must be a directory.' % (title, key_folder))

# validate cert path
    cert_path = path.join(key_folder, '%s.crt' % key_alias)
    if path.exists(cert_path) and not overwrite:
        raise ValueError('%s.crt already exists in %s. to overwrite, set overwrite=true' % (key_alias, key_folder))

# validate root path
    from copy import deepcopy
    root_cert_copy = deepcopy(root_cert)
    if root_cert_copy:
        if not path.exists(root_cert_copy):
            root_cert_copy = path.join(key_folder, root_cert_copy)
            if not path.exists(root_cert_copy):
                raise ValueError('%s(root_cert="%s") is not a valid path.' % (title, root_cert_copy))
        root_node, root_ext = path.splitext(root_cert_copy)
        root_key = root_node + '.key'
        if not root_ext in ('.crt', '.pem'):
            raise ValueError('%s(root_cert="%s") must be a .crt or .pem file type.' % (title, root_cert_copy))
        elif not path.exists(root_key):
            key_path, key_name = path.split(root_key)
            raise ValueError('%s(root_cert="%s") requires a matching private key %s' % (title, root_cert_copy, key_name))
        root_path = root_cert_copy
        key_path = root_path.replace('.crt', '.key')
    else:
        key_path = path.join(key_folder, 'root.key')
        root_path = path.join(key_folder, 'root.crt')
        if path.exists(root_path) and not overwrite:
            raise ValueError('root.crt already exists in %s. to overwrite, set overwrite=true' % key_folder)

# validate truststore path
    truststore_copy = deepcopy(truststore)
    if truststore_copy:
        if not path.exists(truststore_copy):
            truststore_copy = path.join(key_folder, truststore_copy)
            if not path.exists(truststore_copy):
                raise ValueError('%s(truststore="%s") is not a valid path.' % (title, truststore_copy))
        trust_node, trust_ext = path.splitext(truststore_copy)
        if not trust_ext in ('.jks'):
            raise ValueError('%s(truststore="%s") must be a .jks file type.' % (title, truststore_copy))
        truststore_path = truststore_copy
        trust_root, trust_node = path.split(truststore_path)
        trust_alias, trust_ext = path.splitext(trust_node)
    else:
        truststore_path = path.join(key_folder, 'truststore.jks')
        trust_alias = 'truststore'
        if path.exists(truststore_path) and not overwrite:
            raise ValueError('%s.jks already exists in %s. to overwrite, set overwrite=true' % (trust_alias, key_folder))

# format DNAME fields
    if not organization:
        organization = 'None'
    if not organization_unit:
        organization_unit = 'None'
    if not locality:
        locality = 'None'
    if not country:
        country = 'None'

# create root certificate
    if not root_cert_copy:
        subject_args = '/CN=root/OU=%s/O=%s/L=%s/C=%s' % (
            organization_unit,
            organization,
            locality,
            country
        )
        root_subject = '-subj %s' % subject_args.replace(' ', '\ ')
        password_text = '-passout pass:%s' % password
        sys_command = 'openssl req -newkey rsa:%s -x509 -nodes -keyout %s -out %s -days 36500 %s %s' % (key_size, key_path, root_path, root_subject, password_text)
        _call(sys_command, ignore='writing new private key', title='Generating root certificate')

# generate server cert
    server_dname = '-dname "CN=%s, OU=%s, O=%s, L=%s, C=%s"' % (
        key_alias, organization_unit, organization, locality, country
    )
    keystore_path = path.join(key_folder, '%s.jks' % key_alias)
    if path.exists(keystore_path) and not overwrite:
        raise ValueError('%s.jks already exists in %s. to overwrite, set overwrite=true' % (key_alias, key_folder))
    elif path.exists(keystore_path):
        remove(keystore_path)
    sys_command = 'keytool -genkey -keyalg RSA -alias %s -validity 36500 -keystore %s -storepass %s -keypass %s -keysize %s %s' % (key_alias, keystore_path, password, password, key_size, server_dname)
    _call(sys_command, ignore='JKS keystore uses a proprietary format', title='Generating keystore for %s' % key_alias)

# convert cert to pkcs12
    sys_command = 'keytool -importkeystore -srckeystore %s -destkeystore %s -deststoretype pkcs12 -storepass %s -keypass %s' % (keystore_path, keystore_path, password, password)
    _call(sys_command, prompt_input=password, title='Converting keystore to pkcs12 standard')
    remove('%s.old' % keystore_path)

# generate certificate request
    request_path = path.join(key_folder, '%s.csr' % key_alias)
    sys_command = 'keytool -certreq -alias %s -file %s -keystore %s -storepass %s -keypass %s %s' % (
        key_alias, request_path, keystore_path, password, password, server_dname
    )
    _call(sys_command, title='Generating certificate signing request for %s'% key_alias)

# sign server cert with root cert
    cert_path = path.join(key_folder, '%s.crt' % key_alias)
    sys_command = 'openssl x509 -req -CA %s -CAkey %s -in %s -out %s -days 36500 -CAcreateserial -passin pass:%s' % (root_path, key_path, request_path, cert_path, password)
    _call(sys_command, ignore='Getting CA Private Key', title='Signing certificate for %s with root certificate' % key_alias)

# add root cert to server keystore
    root_root, root_node = path.split(root_path)
    root_alias, root_ext = path.splitext(root_node)
    sys_command = 'keytool -importcert -keystore %s -alias %s -file %s -noprompt -keypass %s -storepass %s' % (keystore_path, root_alias, root_path, password, password)
    _call(sys_command, ignore='Certificate was added to keystore', title='Adding root certificate to keystore for %s' % key_alias)

# add server cert to server keystore
    sys_command = 'keytool -importcert -keystore %s -alias %s -file %s -noprompt -keypass %s -storepass %s' % (keystore_path, key_alias, cert_path, password, password)
    _call(sys_command, ignore='Certificate reply was installed in keystore', title='Adding certificate for %s to keystore for %s' % (key_alias, key_alias))

# add root certificate to truststore
    if not truststore_copy:
        if path.exists(truststore_path):
            remove(truststore_path)
        sys_command = 'keytool -importcert -keystore %s -alias %s -file %s -noprompt -keypass %s -storepass %s' % (truststore_path, root_alias, root_path, password, password)
        _call(sys_command, ignore='Certificate was added to keystore', title='Generating truststore for root certificate')

# add server cert to truststore
    sys_command = 'keytool -importcert -keystore %s -alias %s -file %s -noprompt -keypass %s -storepass %s' % (truststore_path, key_alias, cert_path, password, password)
    _call(sys_command, ignore='Certificate was added to keystore', title='Adding certificate for %s to truststore' % key_alias)

# remove .srl files
    from os import listdir
    for file_name in listdir('./'):
        if file_name == '.srl':
            remove(file_name)
    for file_name in listdir(key_folder):
        file_alias, file_ext = path.splitext(file_name)
        if file_ext == '.srl':
            remove(path.join(key_folder, file_name))

    return True