Запросы Python - Как использовать системные ca-сертификаты (debian/ubuntu)?

Я установил самозаверяющий root ca cert в debian /usr/share/ca-certificates/local и установил их с помощью sudo dpkg-reconfigure ca-certificates. На данный момент true | gnutls-cli mysite.local счастлив, а true | openssl s_client -connect mysite.local:443 счастлив, но модуль запросов python2 и python3 настаивает, что он не доволен сертификатом.

python2:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

python3

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/bin/python3.5/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)

Почему python игнорирует пакет ca-сертификатов системы и как его интегрировать?

Ответ 1

Из fooobar.com/questions/97505/...

Чтобы сделать запросы python использовать пакет ca-сертификатов системы, нужно сказать, чтобы использовать его по своему встроенному пакету

export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt

Запросы вставляют свои связки здесь, для справки:

/usr/local/lib/python2.7/site-packages/requests/cacert.pem
/usr/lib/python3/dist-packages/requests/cacert.pem

Ответ 2

Я боролся с этим в течение недели или около того недавно. Наконец-то я нашел способ проверить самоподписанный или подписанный лично сертификат в Python. Вам нужно создать свой собственный файл пакета сертификатов. Нет необходимости обновлять неизвестные пакеты сертификатов при каждом обновлении библиотеки или добавлении чего-либо в системное хранилище сертификатов.

Начните с запуска команды openssl, которую вы запускали ранее, но добавьте -showcerts. openssl s_client -connect mysite.local:443 -showcerts Это даст вам длинный вывод, а вверху вы увидите всю цепочку сертификатов. Обычно это три сертификата, сертификат веб-сайта, промежуточный сертификат и корневой сертификат в указанном порядке. Нам нужно поместить только корневой и промежуточный сертификаты в следующий файл в обратном порядке.

Скопируйте последний сертификат, корневой сертификат, в новый текстовый файл. Возьмите только то, что между, и в том числе:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Скопируйте средний сертификат (он же промежуточный сертификат) в новый текстовый файл под корневым сертификатом. Снова, возьмите строки Начального и Конечного сертификата и все, что между ними.

Сохраните этот текстовый файл в каталог, где находится ваш скрипт Python. Я рекомендую называть его CertBundle.pem. (Если вы дадите ему другое имя или поместите его где-нибудь еще в структуре вашей папки, убедитесь, что строка проверки отражает это.) Обновите ваш скрипт, чтобы он ссылался на новый пакет сертификатов:

response = requests.post("https://www.example.com/", headers=headerContents, json=bodyContents, verify="CertBundle.pem")

И это оно. Если у вас есть только корневой или только промежуточный сертификат, то Python не сможет проверить всю цепочку сертификатов. Но если вы включите оба сертификата в созданный вами комплект сертификатов, то Python может проверить, что промежуточное звено было подписано корнем, а затем при доступе к веб-сайту он может проверить, что сертификат веб-сайта был подписан промежуточным сертификатом.,

редактировать: исправлено расширение файла для комплекта сертификатов. Также исправлена пара грамматических ошибок.

Ответ 3

Передача сертификатных кортежей должна работать:

certificate_path = os.path.join(CERT_PATH, 'cacert.pem')
certificate_key_path = os.path.join(CERT_PATH, 'cacert.key')
re = requests.get(next_url, cert=(certificate_path, certificate_key_path))

Я использую этот подход;)