web-dev-qa-db-fra.com

Requêtes Python renvoyant SSLError

Je travaille sur un script simple qui implique CAS, une vérification de sécurité de jspring, une redirection, etc. J'aimerais utiliser les requêtes Python de Kenneth Reitz, car c'est un excellent travail! Cependant, CAS nécessite d'être validé via SSL, je dois donc passer cette étape en premier. Je ne sais pas ce que Python demande Où ce certificat SSL est-il censé résider?

Traceback (most recent call last):
  File "./test.py", line 24, in <module>
  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
252
TedBurrows

Le problème que vous rencontrez est dû à un certificat SSL non approuvé.

Comme @dirk mentionné dans un commentaire précédent, le correctif le plus rapide définit verify=False:

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

Veuillez noter que cela fera que le certificat ne sera pas vérifié. Ceci exposera votre application à des risques de sécurité, tels que des attaques par interception. 

Bien sûr, appliquer son jugement. Comme mentionné dans les commentaires, ceci peut être acceptable pour les applications/scripts rapides/jetables, mais ne devrait en aucun cas aller au logiciel de production

Si ignorer simplement la vérification du certificat n'est pas acceptable dans votre contexte particulier, envisagez les options suivantes. La meilleure option consiste à définir le paramètre verify sur une chaîne correspondant au chemin du fichier .pem du certificat (que vous devriez obtenir des moyens sécurisés).

Ainsi, à partir de la version 2.0, le paramètre verify accepte les valeurs suivantes, avec leur sémantique respective:

  • True: le certificat est validé par rapport aux autorités de certification approuvées de la bibliothèque (Remarque: vous pouvez voir quelles requêtes de certificats racine utilisent via la bibliothèque Certifi, une base de données de confiance des contrôleurs de domaine extraite de Requests: Certifi - Base de données de confiance pour les humains ) .
  • False: contourne la validation du certificat complètement.
  • Chemin d'accès à un fichier CA_BUNDLE pour les demandes à utiliser pour valider les certificats.

Source: Demandes - Vérification du certificat SSL

Jetez également un coup d'œil au paramètre cert sur le même lien.

322
Rafael Almeida

A partir de requêtes documentation sur la vérification SSL :

Les demandes peuvent vérifier les certificats SSL pour les demandes HTTPS, tout comme un navigateur Web. Pour vérifier le certificat SSL d'un hôte, vous pouvez utiliser l'argument de vérification:

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

Si vous ne voulez pas vérifier votre certificat SSL, indiquez verify=False 

96
Boud

Le nom du fichier d’autorité de certification que vous souhaitez utiliser peut être transmis via verify:

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

Si vous utilisez verify=True, requests utilise son propre ensemble d'autorités de certification qui peut ne pas contenir d'autorité de certification ayant signé votre certificat de serveur.

44
jfs

$ pip install -U requests[security]

  • Testé sur Python 2.7.6 @ Ubuntu 14.04.4 LTS
  • Testé sur Python 2.7.5 @ MacOSX 10.9.5 (Mavericks)

Lorsque cette question a été ouverte (2012-05), la version de Requests était 0.13.1. Sur la version 2.4.1 (2014-09) les suppléments "sécurité" ont été introduits, en utilisant le paquetage certifi si disponible. 

Pour le moment (2016-09), la version principale est la 2.11.1, cela fonctionne bien sansverify=False. Pas besoin d'utiliser requests.get(url, verify=False), si installé avec des extras requests[security].

30
alanjds

J'ai rencontré le même problème et le certificat ssl a échoué lors de l'utilisation de aws boto3. En passant en revue le code boto3, j'ai constaté que le REQUESTS_CA_BUNDLE n'est pas défini. J'ai donc résolu le problème à la fois en le réglant manuellement:

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')

Pour aws-cli, je suppose que définir REQUESTS_CA_BUNDLE dans ~/.bashrc résoudra ce problème (non testé car mon aws-cli fonctionne sans lui).

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

Si vous avez une bibliothèque qui s'appuie sur requests et que vous ne pouvez pas modifier le chemin de vérification (comme avec pyvmomi), vous devez rechercher le cacert.pem fourni avec les demandes et y ajouter votre autorité de certification. Voici une approche générique pour trouver l'emplacement cacert.pem:

les fenêtres

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

btw. @ request-devs, associer vos propres cacerts à request est vraiment très ennuyant ... surtout le fait que vous ne semblez pas utiliser le système ca stocke d’abord et que cela n’est documenté nulle part.

mettre à jour

dans les cas où vous utilisez une bibliothèque et n'avez aucun contrôle sur l'emplacement du paquetage, vous pouvez également définir explicitement l'emplacement de ce dernier comme étant votre paquetage hôte:

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

Je rencontre le même problème avec gspread et ces commandes fonctionnent pour moi:

Sudo pip uninstall -y certifi
Sudo pip install certifi==2015.04.28
13
user941581

Si vous souhaitez supprimer les avertissements, utilisez le code ci-dessous.

import urllib3

urllib3.disable_warnings()

et verify=False avec la méthode request.get ou post

10
AniketGole

J'ai trouvé une approche spécifique pour résoudre un problème similaire. L'idée est de pointer le fichier cacert stocké sur le system et utilisé par une autre application basée sur ssl.

Dans Debian (je ne suis pas sûr que ce soit la même chose dans d'autres distributions), les fichiers de certificat (.pem) sont stockés dans /etc/ssl/certs/ C'est donc le code qui fonctionne pour moi:

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

Pour deviner quel fichier pem choisir, je dois parcourir l'URL et vérifier quelle autorité de certification (CA) a généré le certificat.

ÉDITER: si vous ne pouvez pas éditer le code (car vous utilisez une troisième application), vous pouvez essayer d’ajouter le certificat pem directement dans /usr/local/lib/python2.7/dist-packages/requests/cacert.pem (par exemple, en le copiant à la fin du fichier).

10
chk

Si vous ne vous souciez pas du certificat, utilisez simplement verify=False.

import requests

url = "Write your url here"

returnResponse = requests.get(url, verify=False)
9
yogesh prasad

Après des heures de débogage, je ne pouvais le faire fonctionner qu'avec les packages suivants:

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

en utilisant OpenSSL 1.0.2g 1 Mar 2016

Sans ces paquets, verify=False ne fonctionnait pas.

J'espère que ça aidera quelqu'un.

7
michael

J'ai rencontré le même problème. Il s'avère que je n'ai pas installé le certificat intermédiaire sur mon serveur (il suffit de l'ajouter au bas de votre certificat, comme indiqué ci-dessous).

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

Assurez-vous que le package ca-certificates est installé:

Sudo apt-get install ca-certificates

La mise à jour de l'heure peut également résoudre ce problème:

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

Si vous utilisez un certificat auto-signé, vous devrez probablement l'ajouter manuellement à votre système.

5
Marius Craciunoiu

Je me suis battu ce problème pendant des heures. 

J'ai essayé de mettre à jour les demandes. Puis j'ai mis à jour certifi. J'ai fait vérifier à certifi.where () (le code le fait par défaut de toute façon). Rien n'a fonctionné.

Enfin, j'ai mis à jour ma version de python vers python 2.7.11. J'étais sur Python 2.7.5 qui avait quelques incompatibilités avec la façon dont les certificats sont vérifiés. Une fois que j'ai mis à jour Python (et quelques autres dépendances), tout a commencé à fonctionner.

3
ajon

Il y a actuellement un problème dans le module de requêtes à l'origine de cette erreur, présent dans les versions 2.6.2 à 2.12 (ATOW): https://github.com/kennethreitz/requests/issues/2573

La solution de contournement pour ce problème consiste à ajouter la ligne suivante: 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'

2
Peter

Trop tard pour la fête je suppose mais je voulais coller le correctif pour les autres vagabonds comme moi! Donc ce qui suit a fonctionné pour moi sur Python 3.7.x

Tapez ce qui suit dans votre terminal 

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

Essayez de relancer votre script/vos requêtes et voyez si cela fonctionne (je suis sûr qu'il ne sera pas encore résolu!). Si cela ne fonctionne pas, essayez d’exécuter la commande suivante directement dans le terminal

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

Comme mentionné par @Rafael Almeida, le problème que vous rencontrez est dû à un certificat SSL non approuvé. Dans mon cas, le certificat SSL n'a pas été approuvé par mon serveur. Pour résoudre ce problème sans compromettre la sécurité, j'ai téléchargé le certificat et je l'ai installé sur le serveur (en double-cliquant simplement sur le fichier .crt, puis sur Installer le certificat ...).

1
Michael

Si les appels de requête sont enterrés profondément dans le code et que vous ne souhaitez pas installer le certificat de serveur, alors, juste pour pour le débogage uniquement , il est possible d'effectuer un monkeypatch avec des requêtes:

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!')

Ne jamais utiliser dans la production!

1
xmedeko

Dans mon cas, la raison était assez triviale.

Je savais que la vérification SSL avait fonctionné jusqu'à quelques jours auparavant et travaillait en fait sur une autre machine.

Mon étape suivante consistait à comparer le contenu et la taille du certificat entre la machine sur laquelle la vérification fonctionnait et celle sur laquelle elle ne fonctionnait pas.

Cela m'a rapidement conduit à constater que le certificat de la machine «fonctionnant incorrectement» n'était pas bon et, une fois remplacé par le «bon» certificat, tout allait bien.

0
mastDrinkNimbuPani

Il n'est pas possible d'ajouter des options si des demandes sont appelées à partir d'un autre package. Dans ce cas, l'ajout de certificats au paquet cacert constitue le chemin direct, par ex. J'ai dû ajouter "CA de serveur intermédiaire intermédiaire StartCom classe 1", pour lequel j'ai téléchargé le certificat racine dans StartComClass1.pem. étant donné que mon virtualenv s'appelle caldav, j'ai ajouté le certificat avec:

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

un de ceux pourrait être assez, je n'ai pas vérifié

0
rhoerbe

J'avais un problème similaire ou identique à celui de la validation de la certification. J'ai lu que les versions OpenSSL inférieures à 1.0.2, dont les requêtes dépendent parfois de la difficulté à valider des certificats forts (voir ici ). CentOS 7 semble utiliser 1.0.1e qui semble avoir le problème. 

Je ne savais pas trop comment résoudre ce problème sous CentOS. J'ai donc décidé d'autoriser des certificats d'autorité de certification 1024 bits plus faibles. 

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

Je devais passer de Python 3.4.0 à 3.4.6

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