Может ли Apache/mod_ssl поддерживать двухуровневую работу?
У меня есть веб-сервер, который поддерживает большую часть своего контента в локальной базе данных, но ему необходимо запросить службу справочной службы для получения информации о пользователе. Запрос каталога работает отлично как автономная операция, но когда веб-сервер делает запрос, ssl возвращает ошибку.
Сервер основан на CentOS 7-2.1511/Django 1.9.3/PostgreSQL 9.2.15/Apache 2.4.6-40/mod_ssl 1:2.4.6-40/OpenSSL 1:1.0.1/Python 3.4.3
. Apache использует mod_ssl для обслуживания https: запросы от клиента (браузер), и я предполагаю, что Python ssl.py использует тот же движок, что и https: запросы на сервер каталогов. Python SSL говорит, что реализация основана на OpenSSL. По- видимому, Yum не может перечислять зависимости mod_ssl, но я предполагаю, что он также использует установленную версию openssl.
Следующий код будет использовать различающееся имя пользователя (извлеченное из SSL_CLIENT_CERT) и запросить сервер каталогов для пользовательских атрибутов с использованием интерфейса RESTful:
import requests, urllib
URL = 'https://example.com/rest/user_info/'
def get_user_info(dn)
query = URL + urllib.parse.quote(dn)
return requests.get(query, cert=('server.crt', 'server.key'),
verify='ca_bundle.crt').json()
Когда я запускаю на сервере как пользователь apache в каталоге WSGI сервера, программа правильно возвращает атрибут, содержащий пользовательские атрибуты:
$ python
>>> import auth
>>> dn='cn=Me,o=Company,c=US'
>>> attr = auth.get_user_info(dn)
Но когда Apache вызывает ту же функцию с тем же DN из WSGI-скрипта (views.py
), он вызывает OSError:
OSError(0, 'Error')
Line 810, /lib64/python3.4/ssl.py
803 def do_handshake(self, block=False):
804 """Perform a TLS/SSL handshake."""
805 self._check_connected()
806 timeout = self.gettimeout()
807 try:
808 if timeout == 0.0 and block:
809 self.settimeout(None)
810 self._sslobj.do_handshake()
Я начну исследовать блокировку, как было предложено для OpenSSL (так как я не могу придумать ничего другого, что могло бы вызвать эти ошибки), но трудно поверить, что веб-сервер, использующий SSL для бэкэнд-запросов, уже не является хорошо пройденным путем. Вопросов:
Является ли многопоточность/блокировка/повторное включение лаем по правильному дереву для причины этих ошибок? Уже есть примеры использования SSL для соединений с сервером-сервером? Я сдаюсь. Следующее работает надежно, за счет как красоты, так и эффективности. Сначала он пытается requests
запрос, и если он взорвется, он пьет и вызывает wget
в подпроцессе. Он возвращает $method
meta item $method
который позволяет просмотру страницы узнать, завершился ли запрос inline.
def get_user_info(dn, sub=True, ttl=300):
query = URL + urllib.parse.quote(dn)
try:
info = requests.get(query, cert=(SERVER_CERT, SERVER_KEY),
verify=CA_CERT).json()
info['$method'] = 'requests'
return info
except OSError:
if sub:
args = ['wget', '-O', '-',
'--certificate=' + SERVER_CERT,
'--private-key=' + SERVER_KEY,
query]
bytes = subprocess.check_output(args, timeout=5)
info = json.loads(bytes.decode(encoding='utf-8'))
info['$method'] = 'subprocess'
return info
else:
raise
Было бы неплохо, если бы OpenSSL использовал контексты вместо глобальных переменных.