Python HTTPS против API управления службами Azure не работает в Windows

Недавно я расширил API Python для API хранилища Windows Azure (PyAzure), включив поддержку API управления службами. См. https://github.com/bmb/pyazure .

Я использую HTTPSClientAuthHandler, подобный предложенному в , используя pyOpenSSL для создания настраиваемого средства открытия urllib . В Linux с различными версиями Python 2.6 и 2.7 это хорошо работает. Однако Windows - это совсем другое дело. Все запросы к адресу хоста управления Azure завершаются ошибкой:

[Errno 10054] Существующее соединение было принудительно закрыто удаленным хостом

Я думаю, это сокет errno 10054 "Connection reset by peer", перетаскиваемый.

Похоже, это не проблема в моем коде API (если только используемый мной метод аутентификации сертификата клиента каким-то образом не является фиктивным), это что-то низкоуровневое. Я могу воспроизвести проблему без urllib2 или httplib, просто настроив сокет SSL и отправив тот же HTTP-запрос по каналу, что и urllib2, например чтобы перечислить допустимые местоположения центров обработки данных Azure:

>>> import socket, ssl, sys
>>> sys.version
'2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)]'

>>> s = ssl.wrap_socket(socket.socket(), certfile='c:\\users\\blair\\research\\clouds\\azure\\BlairBethwaiteAzure1.pfx.pem')
>>> s.connect(('management.core.windows.net',443))
>>> s.send("GET /SUBSCRIPTION_ID/locations HTTP/1.1\r\nAccept-Encoding: identity\r\nX-Ms-Version: 2011-10-01\r\nHost: management.core.windows.net\r\nConnection: close\r\nUser-Agent: Python-urllib/2.6\r\n\r\n")
202

>>> s.read()
Traceback (most recent call last):
c:\Users\blair\research\clouds\azure\pyazure\
in ()
----> 1 s.read()

C:\Python27\lib\ssl.pyc in read(self, len)
   136
   137         try:
--> 138             return self._sslobj.read(len)
   139         except SSLError, x:
   140             if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:


error: [Errno 10054] An existing connection was forcibly closed by the remote host

Замените SUBSCRIPTION_ID выше на свой идентификатор подписки Azure. Исключение возникает через ~ 45 секунд после вызова SSLSocket.read. Сертификат представляет собой правильно отформатированный файл PEM, включающий как закрытый ключ, так и сертификат, он был преобразован из файла pfx (в Ubuntu 10.04) используя:

openssl pkcs12 -in pfxfile -out pemfile -nodes

Я не думаю, что здесь это имеет значение, но я также пробовал использовать unix2dos-файл PEM, но безрезультатно. У меня такое же поведение, даже когда я не предоставляю сертификат, но выполнение этого в Linux приводит к правильной ошибке API с сервера:

'HTTP / 1.1 403 Forbidden \ r \ nContent-Length: 0 \ r \ nСервер: Microsoft-HTTPAPI / 2.0 \ r \ nДата: 1 декабря 2011 г., 13:59:29 GMT \ r \ nСоединение: закрыть \ r \ n \ r \ n '

Это было независимо проверено другим человеком, использующим Windows 7 (такая же, как у меня). Это не проблема брандмауэра на стороне клиента - тот же код работает в виртуальной машине Linux с NAT, работающей на том же хосте.

Я в тупике. Был бы очень признателен за любую помощь, которую могли бы оказать здесь люди ...

Обновление: Похоже, это связано с базовой реализацией SSL в Python. В CPython 2.7.1 возникает ошибка, как показано выше, но с тех пор я успешно протестировал ActiveState Python (как 2.7, так и 2.6), например:

>>> import sys, socket, ssl
>>> sys.version
'2.7.1 (r271:86832, Feb  7 2011, 11:30:38) [MSC v.1500 32 bit (Intel)]'
>>> s = ssl.wrap_socket(socket.socket(), certfile='\\\\VBOXSVR\\azure\\BlairBethwaiteAzure1.pfx.pem')
>>> s.connect(('management.core.windows.net',443))
>>> s.send('GET /SUBSCRIPTION_ID/locations HTTP/1.1\r\nAccept-Encoding: identity\r\nX-Ms-Version: 2011-10-01\r\nHost: management.core.windows.net\r\nUser-Agent: Python-urllib/2.6\r\n\r\n')
183

>>> s.read(4096)
'HTTP/1.1 200 OK\r\nContent-Length: 908\r\nContent-Type: application/xml; charset=utf-8\r\nServer: Microsoft-HTTPAPI/2.0\r\nx-ms-request-id: 08ca048cda6b445da6b3a8f3e4890197\r\nDate: Fri, 02 Dec 2011 03:02:14 GMT\r\n\r\nAnywhere USAnywhere USSouth Central USSouth Central USNorth Central USNorth Central USAnywhere EuropeAnywhere EuropeNorth EuropeNorth EuropeWest EuropeWest EuropeAnywhere AsiaAnywhere AsiaSoutheast AsiaSoutheast AsiaEast AsiaEast Asia'

И, как и ожидалось, мой API тоже работает:

ActivePython 2.6.7.20 (ActiveState Software Inc.) based on
Python 2.6.7 (r267:88850, Jun 27 2011, 13:20:48) [MSC v.1500 64 bit (AMD64)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyazure import pyazure
>>> pa = pyazure.PyAzure(subscription_id=SUBSCRIPTION_ID, management_cert_path='c:\\users\\blair\\research\\clouds\\azure\\BlairBethwaiteAzure1.pfx.pem')
>>> list(pa.wasm.list_locations())
['Anywhere US', 'South Central US', 'North Central US', 'Anywhere Europe', 'North Europe', 'West Europe', 'Anywhere Asia', 'Southeast Asia', 'East Asia']

The Lib \ Файлы ssl.py в CPython2.7 и ActivePython2.7 идентичны, поэтому я предполагаю, что это должно быть связано с некоторой разницей в базовых библиотеках C, возможно, с ошибкой в ​​CPython. Есть какие-нибудь гуру?

15
задан Community 23 May 2017 в 11:53
поделиться