
Решение ужасных проблем с сертификатами в модуле Python Requests
23 ноября 2022 г.Недавно я работал с модулем запросов Python для защиты вызова API с использованием сертификата сервера.
n Я застрял на одном месте, и узнать, что я сделал, чтобы исправить эту проблему, было здорово, и это побудило меня создать сообщение на глубокий анализ SSL-сертификатов.
Проблема
Я использовал модуль запросов, и вот вызов API.
response = requests.post(url, files=files, headers=headers)
Это ошибка, которую я получил в ответ:
/ (Caused by SSLError(SSLCertVerification(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1108)'))
Попытки
Выполнение незащищенных вызовов с verify=false
Моей первой попыткой было использовать флаг подтверждения как False
и попробовать.
response = requests.post(url, files=files, headers=headers, verify=False)
Хотя я получил 200, я получил неприятное предупреждение, подтверждающее, что я делаю ужасную работу, не предоставляя сертификат. Поэтому мне нужно было найти правильный способ сделать это.
Предоставить сертификат сервера
Сначала я подумал, что если я смогу указать сертификат сервера в ключе проверки, это поможет. Так я и сделал,
response = requests.post(url, files=files, headers=headers, verify='server.cer')
Это сертификат с кодировкой DER
Я получил еще одну ошибку:
/ (Caused by SSLError(SSLError(136, '[X509] no certificate or crl found (_ssl.c:4232)'))
Переопределить CA_REQUESTS_BUNDLE
Модуль запрашивает использование certifi для доступа к пакету ЦС и проверки безопасных соединений SSL, и мы можем использовать переменную среды CA_REQUESTS_BUNDLE для переопределения расположение пакета ЦС. Поэтому я подумал, что если я смогу вручную указать server.cer в этой переменной, я достигну просветления. Но, к моему отчаянию, и это не удалось.
Преобразовать в другую кодировку сертификата
Затем я подумал, что модуль requests не должен принимать сертификат в кодировке DER. Поэтому я преобразовал в PEM, который является открытым текстом, но закодирован в Base 64.
openssl x509 -in server.cer -inform DER -outform PEM -out server.pem
и снова позвонил
response = requests.post(url, files=files, headers=headers, verify='server.pem')
Еще одна ошибка.
/ (Caused by SSLError(SSLCertVerification(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1108)'))
Да, это то же самое, что и Ошибка 1. Итак, мы вернулись к исходной точке. Я пытался поискать в Интернете, но ни у кого не было толкового решения. Кто-то
Тогда я подумал, что это не выход, я решу этот вопрос. Так что я много учился, чтобы получить сертификаты, и, наконец, я их получил. Я написал статью «Глубокое погружение» и поместил туда все.
Назад к основам
Эта проблема и все подобные проблемы, связанные с сертификатами (на любом языке, не только на python) в Интернете, требуют четкого и ясного понимания цепочки сертификатов. Я очень четко объяснил все в своем посте с глубоким погружением.
Обычно цепочка сертификатов состоит из трех сторон.
- Корневой центр сертификации
- Один или несколько промежуточных центров сертификации
- Сертификат сервера запрашивает подпись сертификата.
Делегирование ответственности:
<цитата>Знаки корневого ЦС → промежуточный ЦС
Промежуточные знаки ЦС → сертификат сервера
Корневые сертификаты от корневых ЦС обычно имеют очень долгий срок действия (более 20 лет) и поставляются в виде пакетов ЦС на всех компьютерах и серверах и хранятся очень и очень надежно в соответствии со строгими правилами, чтобы никто не мог изменить их на любой машине. .
Поскольку корневой ЦС очень и очень священн, им нужны промежуточные ЦС, чтобы делегировать ответственность за подписание сертификата сервера, когда кто-либо запрашивает его, предоставляя CSR. Эти посредники называются промежуточными ЦС. В цепочке сертификатов может быть несколько промежуточных ЦС.
Решение
В нашем случае, когда мы конвертировали файл сертификата в формат PEM, мы делаем ошибку,
unable to get local issuer certificate (_ssl.c:1108)
Это происходит по 2 причинам:
- Сертификат промежуточного ЦС недоступен в файле server.pem
- Поскольку мы вручную указываем, какой файл сертификата использовать, указав verify=server.pem*,*, модуль запроса python не будет использовать уже существующий пакет ЦС, скорее будет использовать сервер . pem и ожидает, что он содержит все сертификаты в цепочке, server.cer, промежуточный сертификат и корневой сертификат
Поэтому я вручную удалил сертификат сервера следующим образом:
Это делается в Windows, но то же самое можно сделать и в Mac или Linux.
После удаления всех сертификатов из server.cer у нас будут разные файлы .cer для всех ЦС. Таким образом, для приведенного выше случая у нас будет 4 файла .cer.
- Корневой центр сертификации (Zeescalar root ca)
- Промежуточный ЦС 1 (Zscalar промежуточный корневой ЦС)
- Промежуточный ЦС 2 (Zscalar промежуточный корневой ЦС)
- файл .cer сервера Google
Теперь все, что нам нужно сделать, это преобразовать все эти файлы .cer в файлы .pem и объединить их вместе, чтобы создать объединенный файл pem файл и передайте его запросам Python.
Таким образом, для всех файлов cer выполните следующую команду 4 раза.
openssl x509 -in server.cer -inform DER -outform PEM >> consolidate.pem
Всё, что мы здесь делаем, — это создаём полноценный пакет ЦС со всеми сертификатами, и в любом случае мы можем это сделать, это нормально.
Вот и все, мы передаем наш новый файл CA pem запросам python, и он счастлив.
response = requests.post(url, files=files, headers=headers, verify='consolidate.pem')<Response [200]>
:::информация Также опубликовано здесь.
:::
Оригинал