Solicitudes de Python lanzando SSLError

Estoy trabajando en un script simple que involucra CAS, control de seguridad jspring, redirección, etc. Me gustaría usar las solicitudes de python de Kenneth Reitz porque es un gran trabajo. Sin embargo, CAS requiere ser validado a través de SSL, así que primero debo pasar ese paso. No sé lo que está pidiendo Python peticiones? ¿Dónde se supone que reside este certificado SSL?

Traceback (most recent call last): File "./test.py", line 24, in  response = requests.get(url1, headers=headers) File "build/bdist.linux-x86_64/egg/requests/api.py", line 52, in get File "build/bdist.linux-x86_64/egg/requests/api.py", line 40, in request File "build/bdist.linux-x86_64/egg/requests/sessions.py", line 209, in request File "build/bdist.linux-x86_64/egg/requests/models.py", line 624, in send File "build/bdist.linux-x86_64/egg/requests/models.py", line 300, in _build_response File "build/bdist.linux-x86_64/egg/requests/models.py", line 611, in send requests.exceptions.SSLError: [Errno 1] _ssl.c:503: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed 

El problema que tiene es causado por un certificado SSL no confiable.

Al igual que @dirk mencionado en un comentario anterior, la solución más rápida es la configuración de verify=False :

 requests.get('https://example.com', verify=False) 

Tenga en cuenta que esto hará que el certificado no sea verificado. Esto expondrá su aplicación a riesgos de seguridad, como los ataques de intermediarios.

Por supuesto, aplicar el juicio. Como se mencionó en los comentarios, esto puede ser aceptable para aplicaciones / scripts rápidos / desechables, pero en realidad no debería ir al software de producción .

Si simplemente omitir la verificación del certificado no es aceptable en su contexto particular, considere las siguientes opciones, su mejor opción es establecer el parámetro de verify en una cadena que sea la ruta del archivo .pem del certificado (que debe obtener de alguna manera). tipo de medios seguros).

Entonces, a partir de la versión 2.0, el parámetro de verify acepta los siguientes valores, con sus respectivas semánticas:

  • True : hace que el certificado se valide frente a las propias autoridades de certificación de confianza de la biblioteca (Nota: puede ver qué solicitudes de certificados raíz utiliza a través de la biblioteca Certifi, una base de datos de RC extraída de Solicitudes: Certifi – Trust Database for Humans ).
  • False : pasa por alto la validación de certificados por completo .
  • Ruta a un archivo CA_BUNDLE para que las solicitudes se utilicen para validar los certificados.

Fuente: Solicitudes – SSL Cert Verification

También eche un vistazo al parámetro cert en el mismo enlace.

De solicitudes de documentación sobre verificación SSL :

Las solicitudes pueden verificar los certificados SSL para las solicitudes HTTPS, al igual que un navegador web. Para verificar el certificado SSL de un host, puede usar el argumento de verificación:

 >>> requests.get('https://kennethreitz.com', verify=True) 

Si no desea verificar su certificado SSL, haga que verify=False

El nombre del archivo CA a utilizar que podría pasar a través de verify :

 cafile = 'cacert.pem' # http://curl.haxx.se/ca/cacert.pem r = requests.get(url, verify=cafile) 

Si usa verify=True entonces las requests utilizan su propio conjunto de CA que podría no tener CA que firmó su certificado de servidor.

$ pip install -U requests[security]

  • Probado en Python 2.7.6 @ Ubuntu 14.04.4 LTS
  • Probado en Python 2.7.5 @ MacOSX 10.9.5 (Mavericks)

Cuando se abrió esta pregunta (2012-05), la versión de Solicitudes era 0.13.1. En la versión 2.4.1 (2014-09) se introdujeron los extras de “seguridad”, utilizando el paquete certifi si está disponible.

En este momento (2016-09) la versión principal es 2.11.1, que funciona bien sin verify=False . No es necesario utilizar requests.get(url, verify=False) , si se instala con requests[security] extras de requests[security] .

Encontré el mismo problema y el certificado ssl falló al fallar el problema al usar aws boto3, al revisar el código de boto3, encontré que el REQUESTS_CA_BUNDLE no está configurado, así que solucioné el problema al configurarlo manualmente:

 from boto3.session import Session import os # debian os.environ['REQUESTS_CA_BUNDLE'] = os.path.join( '/etc/ssl/certs/', 'ca-certificates.crt') # centos # 'ca-bundle.crt') 

Para aws-cli, supongo que si configura REQUESTS_CA_BUNDLE en ~/.bashrc solucionará este problema (no se ha probado porque mi aws-cli funciona sin él).

 REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt # ca-bundle.crt export REQUESTS_CA_BUNDLE 

En caso de que tenga una biblioteca que dependa de las requests y no pueda modificar la ruta de verificación (como con pyvmomi ), entonces tendrá que encontrar el cacert.pem incluido en las solicitudes y adjuntar su CA allí. Aquí hay un enfoque genérico para encontrar la ubicación cacert.pem :

ventanas

 C:\>python -c "import requests; print requests.certs.where()" c:\Python27\lib\site-packages\requests-2.8.1-py2.7.egg\requests\cacert.pem 

linux

 # (py2.7.5,requests 2.7.0, verify not enforced) root@host:~/# python -c "import requests; print requests.certs.where()" /usr/lib/python2.7/dist-packages/certifi/cacert.pem # (py2.7.10, verify enforced) root@host:~/# python -c "import requests; print requests.certs.where()" /usr/local/lib/python2.7/dist-packages/requests/cacert.pem 

por cierto @ request-devs, agrupar sus propios cacerts con solicitud es realmente molesto … especialmente el hecho de que no parece utilizar el almacén de ca del sistema primero y esto no está documentado en ninguna parte.

actualizar

En situaciones en las que está utilizando una biblioteca y no tiene control sobre la ubicación del paquete ca, también puede establecer explícitamente que la ubicación del paquete ca sea el paquete ca de todo el host:

 REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt python -c "import requests; requests.get('https://somesite.com';)" 

Me enfrento al mismo problema con gspread y estos comandos funcionan para mí:

 sudo pip uninstall -y certifi sudo pip install certifi==2015.04.28 

He encontrado un enfoque específico para resolver un problema similar. La idea es apuntar el archivo cacert almacenado en el sistema y utilizado por otras aplicaciones basadas en ssl.

En Debian (no estoy seguro si es igual en otras distribuciones) los archivos de certificado (.pem) se almacenan en /etc/ssl/certs/ Entonces, este es el código que me funciona:

 import requests verify='/etc/ssl/certs/cacert.org.pem' response = requests.get('https://lists.cacert.org', verify=verify) 

Para adivinar qué archivo pem elegí, he pem en la url y compruebo la Autoridad de certificación (CA) que ha generado el certificado.

EDITAR: si no puede editar el código (porque está ejecutando una tercera aplicación) puede intentar agregar el certificado pem directamente a /usr/local/lib/python2.7/dist-packages/requests/cacert.pem (por ejemplo, copiar hasta el final del archivo).

Si desea eliminar las advertencias, utilice el siguiente código.

 import urllib3 urllib3.disable_warnings() 

y verify=False con request.get o método post

Si no se preocupa por el certificado, simplemente use verify=False .

 import requests url = "Write your url here" returnResponse = requests.get(url, verify=False) 

Después de horas de depuración, solo conseguí que esto funcionara con los siguientes paquetes:

 requests[security]==2.7.0 # not 2.18.1 cryptography==1.9 # not 2.0 

utilizando OpenSSL 1.0.2g 1 Mar 2016

Sin estos paquetes, verify=False no funcionaba.

Espero que esto ayude a alguien.

Me encontré con el mismo problema. Resulta que no había instalado el certificado intermedio en mi servidor (solo agréguelo al final de su certificado como se ve a continuación).

https://www.digicert.com/ssl-support/pem-ssl-creation.htm

Asegúrese de tener instalado el paquete de certificados de ca:

 sudo apt-get install ca-certificates 

Actualizar el tiempo también puede resolver esto:

 sudo apt-get install ntpdate sudo ntpdate -u ntp.ubuntu.com 

Si está utilizando un certificado autofirmado, probablemente tendrá que agregarlo a su sistema manualmente.

Luché contra este problema por HORAS.

Traté de actualizar las solicitudes. Luego actualicé certifi. Señalé verificar a certifi.where () (el código hace esto de manera predeterminada de todos modos). Nada funcionó.

Finalmente, actualicé mi versión de python a python 2.7.11. Estaba en Python 2.7.5, que tenía algunas incompatibilidades con la forma en que se verifican los certificados. Una vez que actualicé Python (y un puñado de otras dependencias) comenzó a funcionar.

Actualmente hay un problema en el módulo de solicitudes que causa este error, presente en v2.6.2 a v2.12.4 (ATOW): https://github.com/kennethreitz/requests/issues/2573

La solución para este problema es agregar la siguiente línea: requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'

Como lo mencionó @Rafael Almeida, el problema que tiene es causado por un certificado SSL no confiable. En mi caso, el servidor no confió en el certificado SSL. Para solucionar esto sin comprometer la seguridad, descargué el certificado y lo instalé en el servidor (simplemente haciendo doble clic en el archivo .crt y luego Instalar certificado …).

Si las llamadas de solicitud están enterradas en algún lugar del código y no desea instalar el certificado del servidor, entonces, solo con fines de depuración , es posible realizar solicitudes mono parche:

 import requests.api import warnings def requestspatch(method, url, **kwargs): kwargs['verify'] = False return _origcall(method, url, **kwargs) _origcall = requests.api.request requests.api.request = requestspatch warnings.warn('Patched requests: SSL verification disabled!') 

¡Nunca usar en producción!

¡Demasiado tarde para la fiesta, supongo, pero quería pegar la solución para compañeros vagabundos como yo! Así que lo siguiente funcionó para mí en Python 3.7.x

Escriba lo siguiente en su terminal

 pip install --upgrade certifi # hold your breath.. 

Intente ejecutar su script / solicitudes de nuevo y ver si funciona (¡estoy seguro de que no se solucionará todavía!). Si no funcionó, intente ejecutar el siguiente comando en el terminal directamente

 open /Applications/Python\ 3.6/Install\ Certificates.command # please replace 3.6 here with your suitable python version 

No es posible agregar opciones si se están llamando solicitudes desde otro paquete. En ese caso, agregar certificados al paquete cacert es la ruta directa, por ejemplo, tuve que agregar “CA de Servidor Intermedio Primario StartCom Clase 1”, para lo cual descargué el certificado raíz en StartComClass1.pem. dado que mi virtualenv se llama caldav, agregué el certificado con:

 cat StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/pip/_vendor/requests/cacert.pem cat temp/StartComClass1.pem >> .virtualenvs/caldav/lib/python2.7/site-packages/requests/cacert.pem 

Uno de esos podría ser suficiente, no lo comprobé.

Estaba teniendo un problema de validación de certificación similar o similar. Leí que las versiones de OpenSSL inferiores a 1.0.2, de las que depende la solicitud, a veces tienen problemas para validar certificados sólidos (consulte aquí ). CentOS 7 parece usar 1.0.1e que parece tener el problema.

No estaba seguro de cómo solucionar este problema en CentOS, así que decidí permitir certificados de CA de 1024 bits más débiles.

 import certifi # This should be already installed as a dependency of 'requests' requests.get("https://example.com", verify=certifi.old_where()) 

Tuve que actualizar de Python 3.4.0 a 3.4.6

 pyenv virtualenv 3.4.6 myvenv pyenv activate myvenv pip install -r requirements.txt