Saltar al contenido
ecdsa.com
requests / urllib3 (Python)cryptography de Python

Mensaje de error

Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

También se muestra como

  • requests.exceptions.SSLError: HTTPSConnectionPool(host='api.example.com', port=8443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate

El host, el puerto y la ruta de la URL se toman de tu solicitud. El motivo más interno varía («self-signed certificate in certificate chain», «Hostname mismatch…», «certificate has expired»), y la línea termina con una ubicación en el código fuente como «(_ssl.c:1082)')))».

requests / urllib3 (Python) — requests.exceptions.SSLError wrapping urllib3 MaxRetryError

Qué significa

requests pidió una conexión a urllib3, la verificación del certificado falló durante el handshake TLS y urllib3 se rindió (con el valor predeterminado de requests, sin reintentos, después del primer intento). La parte útil está entre paréntesis: aquí OpenSSL no encontró el emisor en el bundle de CA que usa requests, que de forma predeterminada es la copia de certifi de las raíces de Mozilla, no el almacén del sistema operativo.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Pasar el bundle correcto con verify=

    verify acepta la ruta de un archivo de bundle de CA o de un directorio de CA indexado por hash; mantiene activadas las comprobaciones del nombre de host y de las fechas.

    python
    import requests
    
    # A CA file (or a directory prepared with c_rehash) for this call
    requests.get("https://api.example.com/", verify="/etc/ssl/certs/ca-certificates.crt")
  2. 2.

    Establecer REQUESTS_CA_BUNDLE para el proceso

    Si haces que apunte al bundle del sistema (después de instalar allí tu CA), todas las llamadas de requests de ese proceso confiarán en las mismas raíces que curl y las herramientas del sistema operativo.

    bash
    # For every requests call in the process (also honoured: CURL_CA_BUNDLE)
    export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt   # Debian/Ubuntu system bundle
    python3 app.py
  3. 3.

    Usar el almacén de confianza del sistema operativo

    Llamar a truststore.inject_into_ssl() al arrancar permite que requests verifique a través del sistema operativo, de modo que las raíces que despliega el departamento de TI funcionan sin tener que mantener bundles.

    python
    # pip install truststore==0.10.5 — requests then verifies with the OS trust store
    import truststore
    truststore.inject_into_ssl()
    
    import requests
    requests.get("https://api.example.com/")
  4. 4.

    Configurar una sesión (Session) una sola vez

    En las aplicaciones, establece Session.verify en un bundle que contenga las raíces públicas más la raíz de la empresa, y reutiliza la sesión.

    python
    import requests
    
    session = requests.Session()
    session.verify = "/etc/ssl/private-ca/corp-ca-bundle.pem"   # public roots + company root
    session.get("https://api.example.com/")

Errores relacionados

Explorar toda la base de datos de errores de firma