Сообщение об ошибке
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain
Также выводится как
- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain
OpenSSL 3 пишет «self-signed», OpenSSL 1.1.1 — «self signed»; Python добавляет место в исходном коде, например «(_ssl.c:1082)». При вызове через urllib сообщение оказывается внутри «<urlopen error …>», через requests — внутри «Max retries exceeded … (Caused by SSLError(…))».
Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN (19)
Что это означает
Цепочка, которую предъявил сервер, заканчивается самоподписанным корневым сертификатом, который не входит в число CA, доверенных для этого процесса Python. Сама цепочка полная, просто корневой сертификат неизвестен. Если это происходит с публичными сайтами вроде pypi.org или api.github.com, корневой сертификат принадлежит прокси или антивирусу с инспекцией TLS в вашей сети или на вашей машине.
Почему это происходит
Корпоративный прокси или антивирус перехватывает HTTPS
частоИТ-отдел устанавливает корневой сертификат для перехвата в хранилище Windows или macOS, поэтому браузеры работают. OpenSSL в составе Python и библиотеки, которые используют пакет сертификатов certifi, эти хранилища не читают.
requests, pip или httpx проверяют сертификаты по certifi
частоcertifi содержит только публичные корневые сертификаты Mozilla. Если добавить корневой сертификат компании в системное хранилище, файл certifi не изменится, а обновление certifi через pip затирает правки, сделанные вручную.
Внутренний сервис отправляет свой частный корневой сертификат
иногдаЕсли внутренние API, чьи сертификаты подписаны корпоративным CA, отдают корневой сертификат в цепочке, этот корневой сертификат всё равно нужно настроить на клиенте.
conda, pyenv или виртуальное окружение со своим пакетом сертификатов
иногдаconda поставляет собственные OpenSSL и пакет сертификатов CA; исправление, внесённое в системный Python, до conda не доходит.
Как исправить
- 1.
Выясните, чей это корневой сертификат
Выведите цепочку для публичного хоста. Если корневой сертификат назван по имени вашей компании или средства защиты, доверять нужно именно ему; незнакомое имя в недоверенной сети — повод остановиться, а не доверять.
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.
Используйте для проверки хранилище доверенных сертификатов операционной системы
truststore.inject_into_ssl() переключает TLS в Python на хранилище доверенных сертификатов ОС, где уже есть корневые сертификаты, развёрнутые вашей организацией. Это самое чистое решение на управляемых машинах с Windows и macOS.
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.
Соберите пакет с публичными корневыми сертификатами и вашим корневым сертификатом
REQUESTS_CA_BUNDLE (requests) и SSL_CERT_FILE (ssl, urllib, httpx) заменяют пакет сертификатов по умолчанию, поэтому объедините корневые сертификаты certifi с корневым сертификатом компании, а не указывайте в переменной только корневой сертификат компании.
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: настройте собственный параметр conda
conda читает ssl_verify из .condarc; укажите в этом параметре объединённый пакет сертификатов, чтобы conda install и conda update работали за прокси.
bash # conda keeps its own OpenSSL and CA bundle conda config --set ssl_verify /path/to/corp-ca-bundle.pem
Связанные ошибки
[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)