docs: 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.
  
      ext_mapping:
          Provide additional X509v3 extension mappings.  This argument should be
          in the form of a dictionary and should include both the OID and the
          friendly name for the extension.
  
          .. versionadded:: Neon
  
      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:
          raise salt.exceptions.SaltInvocationError('private_key is required')
  
      if 'public_key' not in kwargs:
          kwargs['public_key'] = kwargs['private_key']
  
      if 'private_key_passphrase' not in kwargs:
          kwargs['private_key_passphrase'] = None
      if 'public_key_passphrase' not in kwargs:
          kwargs['public_key_passphrase'] = None
      if kwargs['public_key_passphrase'] and not kwargs['private_key_passphrase']:
          kwargs['private_key_passphrase'] = kwargs['public_key_passphrase']
      if kwargs['private_key_passphrase'] and not kwargs['public_key_passphrase']:
          kwargs['public_key_passphrase'] = kwargs['private_key_passphrase']
  
      csr.set_pubkey(get_public_key(kwargs['public_key'],
                                    passphrase=kwargs['public_key_passphrase'], asObj=True))
  
      # pylint: disable=unused-variable
      for entry, num in six.iteritems(subject.nid):
          if entry in kwargs:
              setattr(subject, entry, kwargs[entry])
      # pylint: enable=unused-variable
  
      if 'ext_mapping' in kwargs:
          EXT_NAME_MAPPINGS.update(kwargs['ext_mapping'])
  
      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.get(extname, None) or kwargs.get(extlongname, None)
  
          critical = False
          if extval.startswith('critical '):
              critical = True
              extval = extval[9:]
  
          if extname == 'subjectKeyIdentifier' and 'hash' in extval:
              extval = extval.replace('hash', _get_pubkey_hash(csr))
  
          if extname == 'subjectAltName':
              extval = extval.replace('IP Address', 'IP')
  
          if extname == 'authorityKeyIdentifier':
              continue
  
          issuer = None
          ext = _new_extension(
              name=extname, value=extval, critical=critical, issuer=issuer)
          if not ext.x509_ext:
              log.info('Invalid X509v3 Extension. %s: %s', extname, extval)
              continue
  
          extstack.push(ext)
  
      csr.add_extensions(extstack)
      csr.sign(_get_private_key_obj(kwargs['private_key'],
                                    passphrase=kwargs['private_key_passphrase']), kwargs['algorithm'])
  
      return write_pem(text=csr.as_pem(), path=path, pem_type='CERTIFICATE REQUEST') if path else csr.as_pem()