2011-12-01 11 views
15

Recientemente extendí una API de Python para las API de almacenamiento de Windows Azure (PyAzure) para incluir compatibilidad con las API de administración de servicios. Ver https://github.com/bmb/pyazure.Python HTTPS contra la API de administración de servicios de Azure falla en Windows

Estoy usando un HTTPSClientAuthHandler como el sugerido en using pyOpenSSL to create urllib custom opener. En Linux, con varias versiones de Python 2.6 y 2.7 esto funciona bien. Sin embargo, Windows es otra historia. Todas las peticiones en contra de la dirección de host de administración Azure fallan con:

[Errno 10054] Una conexión existente forzosamente fue cerrada por el host remoto

Lo que creo, es el restablecimiento de conexión socket errno 10054" por peer ", en arrastre.

Esto no parece ser un problema en mi código API (a menos que el método de autenticación de certificado de cliente que estoy usando es falsa de alguna manera), pero algo de nivel inferior. Puedo reproducir el problema sin urllib2 o httplib simplemente configurando un socket SSL y enviando la misma solicitud HTTP por el canal como lo haría urllib2, p. para enumerar las ubicaciones de los centros de datos válidos 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 

Reemplazar SUBSCRIPTION_ID arriba, con su ID de suscripción Azure. La excepción se aumenta ~ 45s después de llamar a SSLSocket.read. El certificado es un archivo PEM con el formato adecuado que incluye tanto la clave privada y el certificado, se convirtió desde el PFX (en Ubuntu 10.04) usando:

openssl pkcs12 -en PFXFile salida privado pemfile -nodes

No creo que importe aquí, pero también probé unix2dos -ing el archivo PEM, sin ningún resultado. Me sale el mismo comportamiento, incluso cuando yo no proporcionan ningún certificado, pero hacerlo en Linux resulta en un error de la API adecuada desde el servidor:

'HTTP/1.1 403 Forbidden \ r \ nContent-Longitud: 0 \ r \ nserver: Microsoft-HTTPAPI/2.0 \ r \ nDate: Jue 01 Dic 2011 13:59:29 GMT \ r \ nConnection: cerrar \ r \ n \ r \ n'

Ésta ha sido verificado independientemente por otra persona que usa Windows 7 (igual que yo). No es un problema de cortafuegos del lado del cliente - el mismo código funciona en un NAT-ed Linux VM que se ejecutan en el mismo host.

Estoy perplejo. Realmente agradecería cualquier ayuda aquí la gente podría ser capaz de proporcionar ...

Actualización: Esto parece estar relacionado con la implementación de SSL subyacente en Python. CPython 2.7.1 tiene el comportamiento de error como se muestra arriba, pero desde que he probado y tenido éxito con ActiveState Python (ambos 2,7 y 2,6), por ejemplo:

>>> 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>' 

Y como era de esperar mi API también funciona:

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'] 

Los archivos Lib \ ssl.py en CPython2.7 y ActivePython2.7 son idénticos, así que supongo que esto se debe a alguna diferencia en las bibliotecas C subyacentes, quizás un error en CPython. ¿Algún gurú por ahí?

+0

¿Tiene algún proceso proxy como Fiddler en su equipo? –

+0

Sin proxy local ni sniffer. – Blairo

Respuesta

2

no he sido capaz de precisar una explicación definitiva para esto, pero después de un poco de ensayo y error estoy seguro de dónde pone el tema ...

Respuesta corta: es la Implementación de ssl en el paquete de Windows http://www.python.org/. Use ActiveState Python en su lugar.

Respuesta larga: Las distribuciones de Windows CPython disponible de http://www.python.org/download/ paquete bastante una versión antigua de OpenSSL (0.9.8l), en comparación con las distribuciones ActiveState Python que se basan en CPython pero (entre otras cosas) proporcionan actualizaciones regulares a tercera inclusiones de fiesta como OpenSSL (actualmente 0.9.8r).

He descargado binarios de Windows de OpenSSL y probados a través de la interfaz s_client OpenSSL, por ejemplo:

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

La versión actual funciona, como se esperaba. Desafortunadamente parece difícil tener las manos en viejos binarios OpenSSL para Windows, lo que tal vez no sea sorprendente dado que es una biblioteca de seguridad ... Pero de todos modos, construí 0.9.8l desde el código fuente en Ubuntu 10.04 y encontré que se bloquea después de enviar una solicitud HTTP por el tubo, es de suponer que el servidor en silencio interrumpe la conexión por alguna razón:

[email protected]:~/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 

Bajo nueva e incluso un poco mayor (por ejemplo, 0.9.8e de Ubuntu10.04) OpenSSLs el servidor responde a la solicitud con la esperada:

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

Pero con OpenSSL 0.9.8l no obtengo nada.

0

No soy un desarrollador de Python.Pero me he enfrentado a muchos problemas cuando se trata de servicios de Azure de iPhone y Windows Phone Éntrenos en asegurar la siguiente

+0

No es un problema con el certificado o la clave (a menos que se relacione con un problema con la lectura de las codificaciones por una versión particular de OpenSSL). Están codificados en PEM, por lo que no tienen una URL en ellos. No hay que preocuparse por la existencia de un almacén de certificados, se trata de una plataforma simple de Python que usa archivos, no tiene enredo .NET. – Blairo

2

Los siguientes trabajos como se esperaba mediante IronPython 2.7.1 en Windows 7 y CPython 2.6.6 en OS X 10.6.8:

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)) 

[NOTA: Estoy de paso MYKEYFILENAME.pem como de comandos parámetro de línea.]

Happy Azure hackear!

Cuestiones relacionadas