Вопрос или проблема
У меня есть пакет Python, который использует Requests. Я создаю объект Session
с verify=[файл CA]
. Похоже, что Requests будет использовать это, плюс любые системные сертификаты, чтобы проверить подключение. Есть ли способ отключить это поведение?
У одного из моих клиентов нет того же хранилища доверия, что и у меня, и на их системе подключение завершается неудачей. Я уже знаю, что это связано с тем, что сертификат, который я использую, неправильный, но, поскольку этот факт был скрыт в моей программе из-за того, что правильный сертификат был в моем хранилище доверия, я не знал. Я хотел бы иметь возможность правильно протестировать в следующий раз.
Я заглянул в исходный код requests и нашел этот комментарий:
Если вы упаковываете Requests, например, для дистрибутива Linux или управляемой среды, вы можете изменить определение функции where() таким образом, чтобы она возвращала отдельно упакованный CA bundle
Эта возможность поддерживается также в документации:
https://requests.readthedocs.io/en/stable/user/advanced/#ca-certificates
где говорится, что requests просто полагается на пакет certifi.
Итак, вы можете взглянуть на исходный код certifi и разобраться, как сделать monkey patch функции where.
https://github.com/certifi/python-certifi/blob/master/certifi/core.py
Я не вижу ничего в исходном коде certifi, что читает из места, отличного от файла pem, упакованного с ним.
Возможно, у вас и у вашего клиента установлены разные версии python/certifi на ваших системах, и их выравнивание поможет?
Спасибо,
Марк
Ответ или решение
Чтобы удостовериться, что ваш Python-код использует только указанный вами CA файл для проверки SSL-соединений, а не системные сертификаты, вы можете выполнить ряд шагов. При использовании библиотеки Requests
, которая в свою очередь полагается на пакет certifi
, существует важная особенность: по умолчанию Requests
использует системный хранилище сертификатов для валидации соединений. Однако, этой базе можно управлять, исключив другие сертификаты и гарантируя, что проверка осуществляется только на основе вашего CA файла.
Шаги для проверки SSL только с указанным CA файлом
-
Создание собственного объекта сессии:
Начните с создания объектаSession
, передав путь к вашему CA файлу в параметреverify
. Это гарантирует, что библиотекаRequests
будет использовать только указанный файл.import requests session = requests.Session() session.verify = '/path/to/your/cafile.pem'
-
Отключение системной проверки сертификатов:
Чтобы полностью отключить системную проверку сертификатов, можно создать кастомный адаптер или использовать специальный флаг, который указывает на использование только вашего CA файла. -
Используйте
http.client
для более глубокой настройки:
Вы можете переопределить поведение проверки, использовав стандартные библиотеки Python, такие какhttp.client
. Ниже приведен пример, как это можно сделать:import http.client import ssl import requests class CustomHTTPAdapter(requests.adapters.HTTPAdapter): def init_poolmanager(self, *args, **kwargs): context = ssl.create_default_context(cafile='/path/to/your/cafile.pem') kwargs['ssl_context'] = context return super().init_poolmanager(*args, **kwargs) session = requests.Session() session.mount('https://', CustomHTTPAdapter()) response = session.get('https://example.com')
-
Проверка версий библиотек:
Убедитесь, что у вас и вашего клиента установлены одинаковые версии Python и библиотек, таких какrequests
иcertifi
. Различия в версиях могут вызывать inconsistency в процессе проверки. -
Мониторинг и тестирование:
Проверьте, что ваш код корректно работает на всех целевых системах без зависимости от их системного хранилища сертификатов. Это можно сделать, запустив несколько тестов на соответствующих серверах с убедительным указанием на то, что используется именно ваш CA файл.
Заключение
Используя указанные методы, вы сможете точно контролировать процесс проверки SSL-соединений и избегать проблем с несовпадением сертификатов явно. Следуйте предложенным шагам и обеспечьте надежную и безопасную работу вашего программного обеспечения, независимо от системных своячков, установленных на каждом из серверов.