繁体   English   中英

Windows上针对Azure服务管理API的Python HTTPS失败

[英]Python HTTPS against Azure service management API fails on Windows

我最近为Windows Azure存储API(PyAzure)扩展了一个Python API,以包含对服务管理API的支持。 请参阅https://github.com/bmb/pyazure

我正在使用HTTPSClientAuthHandler,就像使用pyOpenSSL建议创建urllib自定义开启器一样 在Linux上,使用各种版本的Python 2.6和2.7,效果很好。 但是,Windows是另一个故事。 针对Azure管理主机地址的所有请求都失败:

[Errno 10054]远程主机强行关闭现有连接

我认为,是套接字errno 10054“连接由同行重置”,在拖动。

这在我的API代码中似乎不是问题(除非我使用的客户端证书身份验证方法是虚假的),但是更低级别的东西。 我可以在没有urllib2或httplib的情况下重现问题,只需设置一个SSL套接字,然后像urllib2一样向管道发送相同的HTTP请求,例如列出有效的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\<ipython-input-63-3306c981d8a7>
in <module>()
----> 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

使用Azure订阅ID替换上面的SUBSCRIPTION_ID。 调用SSLSocket.read后,异常会提高~45秒。 证书是一个格式正确的PEM文件,包括私钥和证书,它是从pfx(在Ubuntu 10.04中)转换而来的,使用:

openssl pkcs12 -in pfxfile -out pemfile -nodes

我认为这不重要,但我也试过unix2dos-ing PEM文件,但无济于事。 即使我没有提供任何证书,我也会得到相同的行为,但在Linux上执行此操作会导致服务器出现正确的API错误:

'HTTP / 1.1 403禁止\\ r \\ n内容长度:0 \\ r \\ n服务器:Microsoft-HTTPAPI / 2.0 \\ r \\ n日期:2011年12月1日星期四13:59:29 GMT \\ r \\ n连接:关闭\\ r \\ n \\ r \\ N”

这已由使用Windows 7的其他人(与我相同)独立验证。 这不是客户端防火墙问题 - 相同的代码适用于在同一主机上运行的NAT-ed Linux VM。

我很难过。 真的很感激这里的帮助人们可以提供......

更新:这似乎与Python中的基础SSL实现有关。 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\n<Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Location><Name>Anywhere US</Name><DisplayName>Anywhere US</DisplayName></Location><Location><Name>South Central US</Name><DisplayName>South Central US</DisplayName></Location><Location><Name>North Central US</Name><DisplayName>North Central US</DisplayName></Location><Location><Name>Anywhere Europe</Name><DisplayName>Anywhere Europe</DisplayName></Location><Location><Name>North Europe</Name><DisplayName>North Europe</DisplayName></Location><Location><Name>West Europe</Name><DisplayName>West Europe</DisplayName></Location><Location><Name>Anywhere Asia</Name><DisplayName>Anywhere Asia</DisplayName></Location><Location><Name>Southeast Asia</Name><DisplayName>Southeast Asia</DisplayName></Location><Location><Name>East Asia</Name><DisplayName>East Asia</DisplayName></Location></Locations>'

正如预期的那样,我的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']

CPython2.7和ActivePython2.7中的Lib \\ ssl.py文件是相同的,所以我想这一定是由于底层C库中的一些差异,也许是CPython中的一个错误。 那里有专家吗?

我无法确定这方面的明确解释,但经过一些试验和错误后,我对这个问题的位置充满信心......

简短回答:这是http://www.python.org/Windows软件包中的ssl实现。 请改用ActiveState Python。

长答案:Windows CPython发行版可从http://www.python.org/download/捆绑得到相当旧版本的OpenSSL(0.9.8l),与基于CPython的ActiveState Python发行版相比,但(除其他外) )定期更新第三方内容,如OpenSSL(目前为0.9.8r)。

我下载了OpenSSL的Windows二进制文件,并通过openssl s_client接口进行了测试,例如:

openssl s_client -connect management.core.windows.net:443 -cert /home/blair/nimrod-dev/BlairBethwaiteAzure1.pfx.pem

正如预期的那样,当前版本有效。 不幸的是,似乎很难掌握用于Windows的旧OpenSSL二进制文件,也许这并不奇怪,因为它是一个安全库......但无论如何,我在Ubuntu 10.04下从源代码构建了0.9.8l并发现它在发送HTTP请求后挂起管道下方,可能服务器由于某种原因无声地丢弃了连接:

blair@venus-vm:~/Downloads/openssl-0.9.8l/apps$ ./openssl s_client -connect management.core.windows.net:443 -cert ./BlairAzure.pem 
CONNECTED(00000003)
depth=2 /CN=Microsoft Internet Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/CN=management.core.windows.net
   i:/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure Server Authority
 1 s:/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure Server Authority
   i:/CN=Microsoft Internet Authority
 2 s:/CN=Microsoft Internet Authority
   i:/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGhDCCBWygAwIBAgIKFnL3ogAIAAIjlDANBgkqhkiG9w0BAQUFADCBizETMBEG
CgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEUMBIG
CgmSJomT8ixkARkWBGNvcnAxFzAVBgoJkiaJk/IsZAEZFgdyZWRtb25kMSowKAYD
VQQDEyFNaWNyb3NvZnQgU2VjdXJlIFNlcnZlciBBdXRob3JpdHkwHhcNMTEwNjE2
MDg0MjI3WhcNMTMwNjE1MDg0MjI3WjAmMSQwIgYDVQQDExttYW5hZ2VtZW50LmNv
cmUud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCS
Z9PTUqQLh5keX/IRJ6JxaQkVBIy/iyoCIx2Y0zy5F5tll8CRydGzFDjXMLWEG425
EuuRDQrBgQnmVtlZ2t42QfIRBSvfJheZVh8k27g/tH5wpchZ47gxxatUKsVJ84P8
Me2S0RP9xtk3P14dVqTDJIhUC3k8JYdBiTTtk64EB5Dbq8sxEtjVb/68XDgTZKek
te/vqWSW/KcduKEjsfjOwNSM9UbYrFOTbelac+mf/L+CluAJpYAlIhOMUP2afy5e
tYIg6zK04pDNjPjizpfN3xrGX7NRY16kaafrdqJQixfmEVlMDN8FsXLWDweXWfMM
XRh4vuAVb6tA9wBkPDhZAgMBAAGjggNMMIIDSDALBgNVHQ8EBAMCBLAwHQYDVR0l
BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMHgGCSqGSIb3DQEJDwRrMGkwDgYIKoZI
hvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDALBglghkgBZQMEASowCwYJYIZIAWUD
BAEtMAsGCWCGSAFlAwQBAjALBglghkgBZQMEAQUwBwYFKw4DAgcwCgYIKoZIhvcN
AwcwHQYDVR0OBBYEFEaKqx6Auvu3fvHS6KqQl8KXoOoAMB8GA1UdIwQYMBaAFAhC
49tOEWbztQjFQNtVfDNGEYM4MIIBCgYDVR0fBIIBATCB/jCB+6CB+KCB9YZYaHR0
cDovL21zY3JsLm1pY3Jvc29mdC5jb20vcGtpL21zY29ycC9jcmwvTWljcm9zb2Z0
JTIwU2VjdXJlJTIwU2VydmVyJTIwQXV0aG9yaXR5KDgpLmNybIZWaHR0cDovL2Ny
bC5taWNyb3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMFNlY3Vy
ZSUyMFNlcnZlciUyMEF1dGhvcml0eSg4KS5jcmyGQWh0dHA6Ly9jb3JwcGtpL2Ny
bC9NaWNyb3NvZnQlMjBTZWN1cmUlMjBTZXJ2ZXIlMjBBdXRob3JpdHkoOCkuY3Js
MIG/BggrBgEFBQcBAQSBsjCBrzBeBggrBgEFBQcwAoZSaHR0cDovL3d3dy5taWNy
b3NvZnQuY29tL3BraS9tc2NvcnAvTWljcm9zb2Z0JTIwU2VjdXJlJTIwU2VydmVy
JTIwQXV0aG9yaXR5KDgpLmNydDBNBggrBgEFBQcwAoZBaHR0cDovL2NvcnBwa2kv
YWlhL01pY3Jvc29mdCUyMFNlY3VyZSUyMFNlcnZlciUyMEF1dGhvcml0eSg4KS5j
cnQwPwYJKwYBBAGCNxUHBDIwMAYoKwYBBAGCNxUIg8+JTa3yAoWhnwyC+sp9geH7
dIFPg8LthQiOqdKFYwIBZAIBCjAnBgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMC
MAoGCCsGAQUFBwMBMCYGA1UdEQQfMB2CG21hbmFnZW1lbnQuY29yZS53aW5kb3dz
Lm5ldDANBgkqhkiG9w0BAQUFAAOCAQEAsqHBR/JxRnGQMTXxJzCau49dDgeum1JH
heA38lzsoUaRELHxxrQZskjSqc0HrI7cnJPSipWQseDDwKtLwXzukCdZNk84u7xo
uHa7/dmxo1m+z353HSvEr85ZE2mzwF6qmwGMmvvVzIJ94M8fcN55yoF64vQsAWFF
k2QJC9ccb8eDoTs5NX4ntpz02xf8eEBQ5yKZySfi3+oFJEUnLmXcvHTTMl/1N/NI
fWiKIZ9PDTBlPxL5kNJ/aDGIgiqCi7Vm7KfjvWSFhopUPtVeeItgW9wMLEkuQsw6
sViSbU50CMPWTJAslLZgCju6cxszgpLl19xrgNteHRw2HouwTTsJnA==
-----END CERTIFICATE-----
subject=/CN=management.core.windows.net
issuer=/DC=com/DC=microsoft/DC=corp/DC=redmond/CN=Microsoft Secure Server Authority
---
No client certificate CA names sent
---
SSL handshake has read 4691 bytes and written 450 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: <SNIP>
    Session-ID-ctx: 
    Master-Key: <SNIP>
    Key-Arg   : None
    Start Time: 1324443511
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
GET /<SUBSCRIPTION_ID>/locations HTTP/1.1
Accept-Encoding: identity
X-Ms-Version: 2011-10-01
Host: management.core.windows.net
Connection: close

在较新的甚至稍微较旧的(例如,Ubuntu10.04的0.9.8e)OpenSSL中,服务器以预期的方式响应请求:

<Locations xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Location><Name>Anywhere US</Name><DisplayName>Anywhere US</DisplayName></Location><Location><Name>South Central US</Name><DisplayName>South Central US</DisplayName></Location><Location><Name>Anywhere Europe</Name><DisplayName>Anywhere Europe</DisplayName></Location><Location><Name>West Europe</Name><DisplayName>West Europe</DisplayName></Location><Location><Name>Anywhere Asia</Name><DisplayName>Anywhere Asia</DisplayName></Location><Location><Name>Southeast Asia</Name><DisplayName>Southeast Asia</DisplayName></Location><Location><Name>East Asia</Name><DisplayName>East Asia</DisplayName></Location><Location><Name>North Central US</Name><DisplayName>North Central US</DisplayName></Location><Location><Name>North Europe</Name><DisplayName>North Europe</DisplayName></Location></Locations>

但是使用OpenSSL 0.9.8l我什么都没得到。

以下使用Windows 7上的IronPython 2.7.1和OS X 10.6.8上的CPython 2.6.6进行预期工作:

import socket, ssl, sys

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('management.core.windows.net',443)) 

s = ssl.wrap_socket(sock, certfile=sys.argv[1])
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')

print(s.read(4096))

[注意:我将MYKEYFILENAME.pem作为命令行参数传递。]

快乐的Azure黑客!

我不是Python开发人员。但是我在处理来自iPhone和Windows Phone的Azure服务时遇到了很多问题。请确保以下内容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM