¿Cómo hacer que las solicitudes de Python confíen en un certificado SSL autofirmado?

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

Si la URL usa un certificado autofirmado, esto falla con

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

Sé que puedo pasar Falseal verifyparámetro, así:

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

Sin embargo, lo que me gustaría hacer es señalar las solicitudes a una copia de la clave pública en el disco y decirle que confíe en ese certificado.

Matthew Moisen
fuente

Respuestas:

60

tratar:

r = requests.post(url, data=data, verify='/path/to/public_key.pem')
krock
fuente
1
¿Puede hacer lo mismo y utilizar certificados de cliente al mismo tiempo? Tengo problemas con esto.
user1156544
9
Tenga en cuenta que el archivo .pem que pase debe incluir el certificado del servidor y cualquier certificado intermedio . Perdí algunas horas tratando de averiguar por qué no funcionó después de agregar el certificado del servidor.
ChrisBob
Agregué certificate.pem autofirmado y funcionó.
HS Rathore
4
Esta técnica no funcionó para mí. Solía ssl.get_server_certificatedescargar un certificado (self-signed.badssl.com, 443), guardé ese certificado en cert.pem, y luego lo ejecuté requests.get('https://self-signed.badssl.com/', verify='cert.pem')y todavía falló con un error de SSL (ese certificado está autofirmado).
Jason R. Coombs
41

Con el verifyparámetro puede proporcionar un paquete de autoridad certificadora personalizado

requests.get(url, verify=path_to_bundle_file)

De los documentos :

Puede pasar verifyla ruta a un archivo CA_BUNDLE con certificados de CA confiables. Esta lista de CA de confianza también se puede especificar mediante la variable de entorno REQUESTS_CA_BUNDLE.

Dr. Jan-Philip Gehrcke
fuente
2
Para que quede muy claro, la variante inferior con cert=(...)es SOLO para SSL de cliente , también conocido como TLS mutuo. Si bien es interesante, es mucho más raro y realmente no se trata de la pregunta.
Nick T
@ nick-t Gracias por el comentario. Tiene razón, he eliminado la parte inferior de la respuesta para que sea menos detallada.
Dr. Jan-Philip Gehrcke
23

Lo más fácil es exportar la variable REQUESTS_CA_BUNDLEque apunta a su autoridad de certificación privada o un paquete de certificados específico. En la línea de comando puede hacerlo de la siguiente manera:

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

Si tiene su autoridad de certificación y no desea escribir el exportcada vez, puede agregar el REQUESTS_CA_BUNDLEa su de la ~/.bash_profilesiguiente manera:

echo "export REQUESTS_CA_BUNDLE=/path/to/your/certificate.pem" >> ~/.bash_profile ; source ~/.bash_profile
Mike N
fuente
La variable de entorno era lo que necesitaba para que PyCharm funcionara con los certificados almacenados en el archivo cert de OpenSSL.
Brady
Tengo un certificado autofirmado en la cadena. Esta solución resolvió mi problema con la biblioteca boto3.
Ilkin
6

El caso en el que se necesitan varios certificados se resolvió de la siguiente manera: Concatenar los archivos pem raíz múltiples, myCert-A-Root.pem y myCert-B-Root.pem, en un archivo. Luego, configure las solicitudes REQUESTS_CA_BUNDLE var en ese archivo en mi ./.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
fuente
Ese fue mi momento "ahhh" del día ... Muchas gracias ... Con esta pista obtuve mi certificado jira autofirmado para que funcionara ... ;-) Sé que tal vez hay cientos de sitios y respuestas que describen esto , pero encontré el tuyo, así que obtienes mi crédito por ayudarme a resolver mi problema ... d
alexrjs
4

La configuración export SSL_CERT_FILE=/path/file.crtdebería hacer el trabajo.

gizzmole
fuente
Gracias. Funciona para mí (mientras que la REQUESTS_CA_BUNDLEvariable no tiene ningún efecto en mi caso).
Pascal H.
0

En caso de que alguien aterrice aquí (como lo hice yo) y busque agregar una CA (en mi caso Charles Proxy) para httplib2, parece que puede agregarlo al cacerts.txtarchivo incluido con el paquete de python.

Por ejemplo:

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

Las variables de entorno a las que se hace referencia en otras soluciones parecen ser específicas de las solicitudes y no fueron recogidas por http:

Mat Schaffer
fuente