web-dev-qa-db-fra.com

Python Requests - Comment utiliser les certificats de système (debian / ubuntu) du système?

J'ai installé un certificat de racine ca auto-signé dans /usr/share/ca-certificates/local De debian et les ai installés avec Sudo dpkg-reconfigure ca-certificates. À ce stade, true | gnutls-cli mysite.local Est heureux et true | openssl s_client -connect mysite.local:443 Est heureux, mais le module de requêtes python2 et python3 insiste sur le fait qu'il n'est pas satisfait du certificat.

python2:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

python3

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

Pourquoi python ignore-t-il le paquet de certificats de certification de système, et comment puis-je l'intégrer?

23
ThorSummoner

De https://stackoverflow.com/a/33717517/169568

Pour que les requêtes python utilisent le paquet système ca-certificats, il faut lui indiquer de l'utiliser sur son propre paquet incorporé

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

Demandes incorpore ses paquets ici, pour référence:

/usr/local/lib/python2.7/site-packages/requests/cacert.pem
/usr/lib/python3/dist-packages/requests/cacert.pem
46
ThorSummoner

J'ai eu du mal avec cela pendant une semaine ou deux récemment. J'ai enfin trouvé le moyen de vérifier un certificat auto-signé ou privé signé en Python. Vous devez créer votre propre fichier d'ensembles de certificats. Il n'est pas nécessaire de mettre à jour des ensembles de certificats obscurs à chaque mise à jour d'une bibliothèque ou d'ajouter quoi que ce soit au magasin de certificats du système.

Commencez par exécuter la commande openssl que vous avez exécutée auparavant, mais ajoutez -showcerts. openssl s_client -connect mysite.local:443 -showcerts Cela vous donnera une longue sortie et en haut, vous verrez toute la chaîne de certificats. Cela signifie généralement trois certificats, le certificat du site Web, le certificat intermédiaire et le certificat racine dans cet ordre. Nous devons placer uniquement les certificats racine et intermédiaires dans un fichier suivant dans l'ordre inverse.

Copiez le dernier certificat, le certificat racine, dans un nouveau fichier texte. Prenez juste le truc entre, et incluant:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Copiez le certificat intermédiaire (le certificat intermédiaire) dans le nouveau fichier texte sous le certificat racine. Encore une fois, prenez les lignes de certificat de début et de fin et tout le reste.

Enregistrez ce fichier texte dans le répertoire où se trouve votre script Python. Je vous recommande de l’appeler CertBundle.pem. (Si vous lui attribuez un nom différent ou le placez ailleurs dans la structure de votre dossier, assurez-vous que la ligne de vérification le reflète.) Mettez à jour votre script pour faire référence au nouvel ensemble de certificats:

response = requests.post("https://www.example.com/", headers=headerContents, json=bodyContents, verify="CertBundle.pem")

Et c'est tout. Si vous ne possédez que le certificat racine ou intermédiaire, alors Python ne peut pas valider la totalité de la chaîne de certificats. Toutefois, si vous incluez les deux certificats dans le lot de certificats que vous avez créé, Python peut valider que l'intermédiaire a été signé par la racine, puis lorsqu'il accède au site Web, il peut valider que le certificat du site Web a été signé par le certificat intermédiaire.

edit: Correction de l’extension du fichier pour l’ensemble de certificats. En outre, corrigé quelques erreurs grammaticales.

6
fryad