Saltar al contenido
ecdsa.com
Python ssl module (OpenSSL)cryptography de Python

Mensaje de error

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain

También se muestra como

  • [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain

OpenSSL 3 imprime «self-signed» y OpenSSL 1.1.1, «self signed»; Python añade una ubicación en el código fuente, como «(_ssl.c:1082)». A través de urllib aparece dentro de «<urlopen error …>», y a través de requests, dentro de «Max retries exceeded … (Caused by SSLError(…))».

Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN (19)

Qué significa

La cadena que presentó el servidor termina en un certificado raíz autofirmado que no está entre las CA en las que confía este proceso de Python. La cadena en sí está completa; simplemente, la raíz es desconocida. Cuando ocurre con sitios públicos como pypi.org o api.github.com, la raíz pertenece a un proxy que inspecciona TLS o a un antivirus de tu red o de tu equipo.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Averiguar de quién es la raíz

    Imprime la cadena de un host público. Una raíz con el nombre de tu empresa o de un producto de seguridad es aquella en la que debes confiar; un nombre desconocido en una red que no es de confianza es motivo para detenerse, no para confiar en ella.

    bash
    openssl s_client -connect pypi.org:443 -servername pypi.org -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
    # A top certificate named after your company or a security vendor = interception proxy
  2. 2.

    Verificar con el almacén de confianza del sistema operativo

    truststore.inject_into_ssl() hace que el TLS de Python use el almacén de confianza del sistema operativo, que ya contiene las raíces desplegadas por tu organización. Es la solución más limpia en equipos Windows y macOS gestionados.

    python
    # pip install truststore==0.10.5
    import truststore
    truststore.inject_into_ssl()   # the proxy root deployed in the OS store is now trusted
    
    import requests
    requests.get("https://api.example.com/")
  3. 3.

    Crear un bundle con las raíces públicas más tu raíz

    REQUESTS_CA_BUNDLE (requests) y SSL_CERT_FILE (ssl, urllib, httpx) sustituyen el bundle predeterminado, así que concatena las raíces de certifi con la raíz de la empresa en lugar de apuntar solo a la raíz de la empresa.

    bash
    # Keep the public roots and add the company/proxy root
    cat "$(python3 -m certifi)" corp-root-ca.pem > ~/.config/corp-ca-bundle.pem
    export REQUESTS_CA_BUNDLE=~/.config/corp-ca-bundle.pem   # requests
    export SSL_CERT_FILE=~/.config/corp-ca-bundle.pem        # ssl, urllib, httpx
  4. 4.

    conda: configurar su propio ajuste

    conda lee ssl_verify de .condarc; asígnale el bundle combinado para que conda install y conda update funcionen detrás del proxy.

    bash
    # conda keeps its own OpenSSL and CA bundle
    conda config --set ssl_verify /path/to/corp-ca-bundle.pem

Errores relacionados

Explorar toda la base de datos de errores de firma