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
Un proxy corporativo o un antivirus intercepta HTTPS
frecuenteEl departamento de TI instala la raíz de interceptación en el almacén de Windows o de macOS, así que los navegadores funcionan. El OpenSSL de Python y las bibliotecas que usan el bundle de certifi no leen esos almacenes.
requests, pip o httpx verifican con certifi
frecuentecertifi solo contiene las raíces públicas de Mozilla. Añadir la raíz de la empresa al almacén del sistema no cambia el archivo de certifi, y una actualización de certifi con pip sobrescribe las ediciones manuales.
Un servicio interno envía su raíz privada
ocasionalLas API internas firmadas por una CA de la empresa siguen necesitando que esa raíz esté configurada en el cliente, aunque sirvan la raíz en la cadena.
conda, pyenv o un entorno virtual con su propio bundle
ocasionalconda incluye su propio OpenSSL y su propio bundle de CA; una corrección aplicada al Python del sistema no le llega.
Cómo solucionarlo
- 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.
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.
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.
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
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local…Python ssl module (OpenSSL)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certifi…Python ssl module (OpenSSL)There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FA…pipcurl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)