簡體   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