Wie bekomme ich Python-Anfragen, um einem selbstsignierten SSL-Zertifikat zu vertrauen?

82
import requests
data = {'foo':'bar'}
url = 'https://foo.com/bar'
r = requests.post(url, data=data)

Wenn die URL ein selbstsigniertes Zertifikat verwendet, schlägt dies mit fehl

requests.exceptions.SSLError: [Errno 1] _ssl.c:507: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Ich weiß, dass ich Falseden verifyParameter wie folgt übergeben kann:

r = requests.post(url, data=data, verify=False)

Ich möchte jedoch Anfragen auf eine Kopie des öffentlichen Schlüssels auf der Festplatte verweisen und ihm mitteilen, dass er diesem Zertifikat vertrauen soll.

Matthew Moisen
quelle

Antworten:

60

Versuchen:

r = requests.post(url, data=data, verify='/path/to/public_key.pem')
Krock
quelle
1
Können Sie dasselbe tun und gleichzeitig Client-Zertifikate verwenden? Ich bekomme Probleme damit.
user1156544
9
Beachten Sie, dass die übergebene PEM-Datei das Serverzertifikat und alle Zwischenzertifikate enthalten muss . Ich habe ein paar Stunden verloren, um herauszufinden, warum es nach dem Hinzufügen des Serverzertifikats nicht funktioniert hat.
ChrisBob
Ich habe selbst signiertes Zertifikat.pem hinzugefügt und es hat funktioniert.
HS Rathore
4
Diese Technik hat bei mir nicht funktioniert. Ich habe ssl.get_server_certificateein Zertifikat für heruntergeladen (self-signed.badssl.com, 443), dieses Zertifikat gespeichert cert.pemund dann ausgeführt, requests.get('https://self-signed.badssl.com/', verify='cert.pem')und es ist immer noch mit einem SSL-Fehler fehlgeschlagen (dieses Zertifikat ist selbst signiert).
Jason R. Coombs
41

Mit dem verifyParameter können Sie ein benutzerdefiniertes Zertifikatberechtigungspaket bereitstellen

requests.get(url, verify=path_to_bundle_file)

Aus den Dokumenten :

Sie können verifyden Pfad zu einer CA_BUNDLE-Datei mit Zertifikaten vertrauenswürdiger Zertifizierungsstellen übergeben. Diese Liste vertrauenswürdiger Zertifizierungsstellen kann auch über die Umgebungsvariable REQUESTS_CA_BUNDLE angegeben werden.

Dr. Jan-Philip Gehrcke
quelle
2
Um es ganz klar zu machen, der Boden mit Variante cert=(...)ist nur für Client - SSL , auch bekannt als MTLS. Es ist zwar interessant, aber viel seltener und nicht wirklich das, worum es bei der Frage ging.
Nick T
@ nick-t Danke für den Kommentar. Sie haben Recht, ich habe den unteren Teil der Antwort entfernt, um sie weniger ausführlich zu machen.
Dr. Jan-Philip Gehrcke
22

Am einfachsten ist es, die Variable zu exportieren, die REQUESTS_CA_BUNDLEauf Ihre private Zertifizierungsstelle oder ein bestimmtes Zertifikatspaket verweist. In der Befehlszeile können Sie dies wie folgt tun:

export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem
python script.py

Wenn Sie über Ihre Zertifizierungsstelle verfügen und diese nicht exportjedes Mal eingeben möchten, können REQUESTS_CA_BUNDLESie sie ~/.bash_profilewie folgt zu Ihrer hinzufügen :

echo "export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem" >> ~/.bash_profile ; source ~/.bash_profile
Mike N.
quelle
Die Umgebungsvariable war das, was ich brauchte, damit PyCharm mit den in der OpenSSL-Zertifikatdatei gespeicherten Zertifikaten funktioniert.
Brady
Ich habe ein selbstsigniertes Zertifikat in der Kette. Diese Lösung löste mein Problem mit der Boto3-Bibliothek.
Ilkin
6

Der Fall, dass mehrere Zertifikate benötigt werden, wurde wie folgt gelöst: Verketten Sie die mehreren Root-PEM-Dateien myCert-A-Root.pem und myCert-B-Root.pem zu einer Datei. Setzen Sie dann die Anforderungen REQUESTS_CA_BUNDLE var auf diese Datei in meinem ./.bash_profile.

$ cp myCert-A-Root.pem ca_roots.pem
$ cat myCert-B-Root.pem >> ca_roots.pem
$ echo "export REQUESTS_CA_BUNDLE=~/PATH_TO/CA_CHAIN/ca_roots.pem" >> ~/.bash_profile ; source ~/.bash_profile
Halbert Stone
quelle
Das war mein "ahhh" Moment des Tages ... Vielen Dank ... Mit diesem Hinweis habe ich mein selbstsigniertes Jira-Zertifikat zum Laufen gebracht ... ;-) Ich weiß, dass es vielleicht Hunderte von Websites und Antworten gibt, die dies beschreiben , aber ich habe deins gefunden, also bekommst du meine Anerkennung dafür, dass du mir geholfen hast, mein Problem zu lösen ... d
alexrjs
4

Einstellung export SSL_CERT_FILE=/path/file.crtsollte den Job machen.

Gizzmole
quelle
Vielen Dank. Funktioniert für mich (während REQUESTS_CA_BUNDLEVariable in meinem Fall keine Auswirkung hat).
Pascal H.
0

Wenn jemand hier landet (wie ich), der eine Zertifizierungsstelle (in meinem Fall Charles Proxy) für httplib2 hinzufügen möchte, können Sie diese anscheinend an die cacerts.txtDatei anhängen, die im Python-Paket enthalten ist.

Zum Beispiel:

cat ~/Desktop/charles-ssl-proxying-certificate.pem >> /usr/local/google-cloud-sdk/lib/third_party/httplib2/cacerts.txt

Die Umgebungsvariablen, auf die in anderen Lösungen verwiesen wird, scheinen anforderungsspezifisch zu sein und wurden in meinen Tests nicht von httplib2 erfasst.

Mat Schaffer
quelle