Если я запустил следующую команду из моего окна разработки:
$ openssl s_client -connect github.com:443
Я получаю следующую последнюю строку вывода:
Verify return code: 20 (unable to get local issuer certificate)
Если я попытаюсь сделать это с запросами, я получаю еще один неудачный запрос:
>>> import requests
>>> r = requests.get('https://github.com/', verify=True)
С исключением:
SSLError: [Errno 1] _ssl.c:507: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Я также могу запустить первую команду с флажком проверки и получить аналогичный вывод:
$ openssl s_client -connect github.com:443 -verify 9
...
Verify return code: 27 (certificate not trusted)
В основном это говорит мне о наличии проблем с сертификатами. Я могу указать конкретный сертификат с обоими методами, и он будет работать:
$ openssl s_client -connect github.com:443 -CAfile /etc/ssl/certs/DigiCert_High_Assurance_EV_Root_CA.pem -verify 9
...
Verify return code: 0 (ok)
и
>>> r = requests.get('https://github.com/', verify='/etc/ssl/certs/DigiCert...pem')
<Response [200]>
Итак, на мой вопрос, , что здесь точно не так? Не должны ли запросы /openssl уже знать, где найти действительные сертификаты?
Дополнительная информация:
- Python == 2.7.6
- запрашивает == 2.2.1
- openssl 0.9.8h
Кроме того, я знаю, что передача verify=False
в метод requests.get
тоже будет работать, но я хочу проверить.
ИЗМЕНИТЬ
Я подтвердил, что, как указал @Heikki Toivonen в ответе, указывается флаг -CAfile для версии openssl, которую я запускаю, работает.
$ openssl s_client -connect github.com:443 -CAfile `python -c 'import requests; print(requests.certs.where())'`
...
Verify return code: 0 (ok)
Итак, нет ничего плохого в версии openssl, которую я запускаю, и нет ничего плохого в файле cacert.pem по умолчанию, который предоставляет запрос.
Теперь, когда я знаю, что openssl предназначен для работы таким образом, что CA файл или место для поиска сертификатов должны быть указаны, я больше беспокоюсь о получении запросов на работу.
Если я запустил:
>>> r = requests.get('https://github.com/', verify='path to cacert.pem file')
Я все еще получаю ту же ошибку, что и раньше. Я даже попробовал загрузить файл cacert.pem из http://curl.haxx.se/ca, и он все равно не работает. запросы только работают (на этой конкретной машине), если я укажу конкретный файл сертификата поставщика.
Замечание: на моей локальной машине все работает так, как ожидалось. Однако есть несколько отличий между этими двумя машинами. Я до сих пор не смог определить, какова конкретная разница, которая вызывает эту проблему.