# Buggy code
def create_csr(path=None, text=False, **kwargs):
    """
    Create a certificate signing request.

    path:
        Path to write the certificate to.

    text:
        If ``True``, return the PEM text without writing to a file. Default ``False``.

    kwargs:
        The subject, extension and version arguments from
        :mod:`x509.create_certificate <salt.modules.x509.create_certificate>` can be used.

    CLI Example:

    .. code-block:: bash

        salt '*' x509.create_csr path=/etc/pki/myca.csr public_key='/etc/pki/myca.key' CN='My Cert
    """

    if not path and not text:
        raise salt.exceptions.SaltInvocationError(
            "Either path or text must be specified."
        )
    if path and text:
        raise salt.exceptions.SaltInvocationError(
            "Either path or text must be specified, not both."
        )

    csr = M2Crypto.X509.Request()
    subject = csr.get_subject()
    csr.set_version(kwargs["version"] - 1)

    if "public_key" not in kwargs:
        raise salt.exceptions.SaltInvocationError("public_key is required")
    csr.set_pubkey(get_public_key(kwargs["public_key"], asObj=True))

    for entry, num in six.iteritems(subject.nid):  # pylint: disable=unused-variable
        if entry in kwargs:
            setattr(subject, entry, kwargs[entry])

    extstack = M2Crypto.X509.X509_Extension_Stack()
    for extname, extlongname in six.iteritems(EXT_NAME_MAPPINGS):
        if extname not in kwargs or extlongname not in kwargs:
            continue

        extval = kwargs[extname] or kwargs[extlongname]

        critical = False
        if extval.startswith("critical "):
            critical = True
            extval = extval[9:]

        issuer = None
        ext = _new_extension(
            name=extname, value=extval, critical=critical, issuer=issuer
        )
        if not ext.x509_ext:
            log.info("Invalid X509v3 Extension. {0}: {1}".format(extname, extval))
            continue

        extstack.push(ext)

    csr.add_extensions(extstack)

    if path:
        return write_pem(text=csr.as_pem(), path=path, pem_type="CERTIFICATE REQUEST")
    else:
        return csr.as_pem()


# Traceback (X509Error)
[WARNING ] /usr/lib/python2.7/dist-packages/salt/grains/core.py:1493: DeprecationWarning: The "osmajorrelease" will be a type of an integer.

[ERROR   ] An un-handled exception was caught by salt's global exception handler:
X509Error: 140503767979776:error:0D0C40D8:asn1 encoding routines:c2i_ASN1_OBJECT:invalid object encoding:a_object.c:283:
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=algorithm, Type=X509_ALGOR
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=sig_alg, Type=X509_REQ
140503767979776:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:83:

Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/python2.7/dist-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/usr/lib/python2.7/dist-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/salt/modules/x509.py", line 500, in read_csr
csr = _get_request_obj(csr)
File "/usr/lib/python2.7/dist-packages/salt/modules/x509.py", line 321, in _get_request_obj
return M2Crypto.X509.load_request_string(text)
File "/usr/lib/python2.7/dist-packages/M2Crypto/X509.py", line 1040, in load_request_string
return load_request_bio(bio, format)
File "/usr/lib/python2.7/dist-packages/M2Crypto/X509.py", line 1024, in load_request_bio
raise X509Error(Err.get_error())
X509Error: 140503767979776:error:0D0C40D8:asn1 encoding routines:c2i_ASN1_OBJECT:invalid object encoding:a_object.c:283:
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=algorithm, Type=X509_ALGOR
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=sig_alg, Type=X509_REQ
140503767979776:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:83:
Traceback (most recent call last):
File "/usr/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/python2.7/dist-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python2.7/dist-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/usr/lib/python2.7/dist-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/salt/modules/x509.py", line 500, in read_csr
csr = _get_request_obj(csr)
File "/usr/lib/python2.7/dist-packages/salt/modules/x509.py", line 321, in _get_request_obj
return M2Crypto.X509.load_request_string(text)
File "/usr/lib/python2.7/dist-packages/M2Crypto/X509.py", line 1040, in load_request_string
return load_request_bio(bio, format)
File "/usr/lib/python2.7/dist-packages/M2Crypto/X509.py", line 1024, in load_request_bio
raise X509Error(Err.get_error())
M2Crypto.X509.X509Error: 140503767979776:error:0D0C40D8:asn1 encoding routines:c2i_ASN1_OBJECT:invalid object encoding:a_object.c:283:
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=algorithm, Type=X509_ALGOR
140503767979776:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=sig_alg, Type=X509_REQ
140503767979776:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:pem_oth.c:83:

# Fixed code
def create_csr(path=None, text=False, **kwargs):
    """
    Create a certificate signing request.

    path:
        Path to write the certificate to.

    text:
        If ``True``, return the PEM text without writing to a file. Default ``False``.

    algorithm:
        The hashing algorithm to be used for signing this request. Defaults to sha256.

    kwargs:
        The subject, extension and version arguments from
        :mod:`x509.create_certificate <salt.modules.x509.create_certificate>` can be used.

    CLI Example:

    .. code-block:: bash

        salt '*' x509.create_csr path=/etc/pki/myca.csr public_key='/etc/pki/myca.key' CN='My Cert
    """

    if not path and not text:
        raise salt.exceptions.SaltInvocationError(
            "Either path or text must be specified."
        )
    if path and text:
        raise salt.exceptions.SaltInvocationError(
            "Either path or text must be specified, not both."
        )

    csr = M2Crypto.X509.Request()
    subject = csr.get_subject()

    for prop, default in six.iteritems(CERT_DEFAULTS):
        if prop not in kwargs:
            kwargs[prop] = default

    csr.set_version(kwargs["version"] - 1)

    if "private_key" not in kwargs and "public_key" in kwargs:
        kwargs["private_key"] = kwargs["public_key"]
        log.warning(
            "OpenSSL no longer allows working with non-signed CSRs. A private_key must be specified. Attempting to use public_key as private_key"
        )

    if "private_key" not in kwargs not in kwargs:
        raise salt.exceptions.SaltInvocationError("private_key is required")

    if "public_key" not in kwargs:
        kwargs["public_key"] = kwargs["private_key"]

    csr.set_pubkey(get_public_key(kwargs["public_key"], asObj=True))

    for entry, num in six.iteritems(subject.nid):  # pylint: disable=unused-variable
        if entry in kwargs:
            setattr(subject, entry, kwargs[entry])

    extstack = M2Crypto.X509.X509_Extension_Stack()
    for extname, extlongname in six.iteritems(EXT_NAME_MAPPINGS):
        if extname not in kwargs and extlongname not in kwargs:
            continue

        extval = kwargs[extname] or kwargs[extlongname]

        critical = False
        if extval.startswith("critical "):
            critical = True
            extval = extval[9:]

        issuer = None
        ext = _new_extension(
            name=extname, value=extval, critical=critical, issuer=issuer
        )
        if not ext.x509_ext:
            log.info("Invalid X509v3 Extension. {0}: {1}".format(extname, extval))
            continue

        extstack.push(ext)

    csr.add_extensions(extstack)

    csr.sign(_get_private_key_obj(kwargs["private_key"]), kwargs["algorithm"])

    if path:
        return write_pem(text=csr.as_pem(), path=path, pem_type="CERTIFICATE REQUEST")
    else:
        return csr.as_pem()