Create a PKCS#12 browser certificate for a particular Certificate (CN)

    ca_name
        name of the CA
    CN
        common name matching the certificate signing request
    passphrase
        used to unlock the PKCS#12 certificate when loaded into the browser
    cacert_path
        absolute path to ca certificates root directory
    replace
        Replace this certificate even if it exists

        .. versionadded:: 2015.5.1

    If the following values were set::

        ca.cert_base_path='/etc/pki'
        ca_name='koji'
        CN='test.egavas.org'

    the resulting signed certificate would be written in the
    following location::

        /etc/pki/koji/certs/test.egavas.org.p12

    CLI Example:

    .. code-block:: bash

        salt '*' tls.create_pkcs12 test localhost

def create_pkcs12(ca_name, CN, passphrase='', cacert_path=None, replace=False):
    '''
    Create a PKCS#12 browser certificate for a particular Certificate (CN)

    ca_name
        name of the CA
    CN
        common name matching the certificate signing request
    passphrase
        used to unlock the PKCS#12 certificate when loaded into the browser
    cacert_path
        absolute path to ca certificates root directory
    replace
        Replace this certificate even if it exists

        .. versionadded:: 2015.5.1

    If the following values were set::

        ca.cert_base_path='/etc/pki'
        ca_name='koji'
        CN='test.egavas.org'

    the resulting signed certificate would be written in the
    following location::

        /etc/pki/koji/certs/test.egavas.org.p12

    CLI Example:

    .. code-block:: bash

        salt '*' tls.create_pkcs12 test localhost
    '''
    set_ca_path(cacert_path)
    if not replace and os.path.exists(
            '{0}/{1}/certs/{2}.p12'.format(
                cert_base_path(),
                ca_name,
                CN)
    ):
        return 'Certificate "{0}" already exists'.format(CN)

    try:
        with salt.utils.files.fopen(
                '{0}/{1}/{1}_ca_cert.crt'.format(cert_base_path(), ca_name)) as fhr:
            ca_cert = OpenSSL.crypto.load_certificate(
                OpenSSL.crypto.FILETYPE_PEM,
                fhr.read()
            )
    except IOError:
        return 'There is no CA named "{0}"'.format(ca_name)

    try:
        with salt.utils.files.fopen('{0}/{1}/certs/{2}.crt'.format(cert_base_path(),
                                                             ca_name,
                                                             CN)) as fhr:
            cert = OpenSSL.crypto.load_certificate(
                OpenSSL.crypto.FILETYPE_PEM,
                fhr.read()
            )
        with salt.utils.files.fopen('{0}/{1}/certs/{2}.key'.format(cert_base_path(),
                                                             ca_name,
                                                             CN)) as fhr:
            key = OpenSSL.crypto.load_privatekey(
                OpenSSL.crypto.FILETYPE_PEM,
                fhr.read()
            )
    except IOError:
        return 'There is no certificate that matches the CN "{0}"'.format(CN)

    pkcs12 = OpenSSL.crypto.PKCS12()

    pkcs12.set_certificate(cert)
    pkcs12.set_ca_certificates([ca_cert])
    pkcs12.set_privatekey(key)

    with salt.utils.files.fopen('{0}/{1}/certs/{2}.p12'.format(cert_base_path(),
                                                         ca_name,
                                                         CN), 'wb') as ofile:
        ofile.write(
            pkcs12.export(
                passphrase=salt.utils.stringutils.to_bytes(passphrase)
            )
        )

    return ('Created PKCS#12 Certificate for "{0}": '
            '"{1}/{2}/certs/{0}.p12"').format(
        CN,
        cert_base_path(),
        ca_name,
    )