如何验证对Windows Azure的管理服务请求?
我想通过Python向Azure发出请求,列出我拥有的存储服务。如何验证对Windows Azure的管理服务请求?
我的基本代码是这样的:
import httplib
conn = httplib.HTTPSConnection('management.core.windows.net')
conn.request('GET', '/[subscription id]/services/storageservices/')
response = conn.getresponse()
print response.status response.reason
很显然,因为我没有验证,该打印出来403 Forbidden
于是,我跟着指示在http://msdn.microsoft.com/en-us/library/windowsazure/gg651127创建一个证书,给我cert.cer
。我将我的.cer
上传到我的Azure帐户,并将.cer
复制到我在其中使用Python的Linux VM中。我修改我的代码是:
import httplib
cert_file = '/path/to/cert.cer'
conn = httplib.HTTPSConnection('management.core.windows.net', cert_file = cert_file)
conn.request('GET', '/[subscription id]/services/storageservices/')
,并得到了错误:
ssl.SSLError: [Errno 336265225] _ssl.c:351: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
下的印象,也许这是因为我试图用一个.cer
证书代替.pem
,并根据什么是here关于.pem和.cer的差异(他们是不同的扩展名相同的东西),我只是将我的.cer的扩展名更改为.pem,然后重试,得到相同的错误。
如何正确验证自己是否能够访问Azure以访问其API?这是我上传证书的问题,还是我需要对证书进行一些操作才能使其适合呈现给服务器?在Windows上,似乎我可以将.cer
安装到某种证书存储中 - 在使用它进行身份验证之前,我需要从中获取证书吗?感谢您的帮助=)
这里的一些工作Python代码,但正如你指出的,关键是要有正确的PEM文件:
import httplib
conn = httplib.HTTPSConnection('management.core.windows.net', cert_file='cert.pem', key_file='key.pem')
conn.request('GET', '/%s/services/storageservices' % subscription_id, headers={'x-ms-version': '2011-02-25'})
print conn.getresponse().read()
我从https://github.com/smarx/waz-cmd得到了我的PEM文件,一个基于Ruby的命令我写的与线程工具API进行交互。请注意,您需要两件(cert_file
和key_file
)。
您已经有了cert文件,但我认为您可能实际上需要将其通过openssl
之类的东西转换为PEM格式。对于密钥文件,我认为您需要导出在Windows计算机上创建的证书,然后使用openssl
将私钥导出为PEM文件。
现在,您可以从Windows Azure门户下载.publishsettings
文件,而不是创建自己的证书,该文件会生成并提供一个准备就绪的证书。见http://blog.smarx.com/posts/calling-the-windows-azure-service-management-api-with-the-new-publishsettings-file。那里的证书是PFX格式的,但是正确的openssl
魔法应该会给你你需要的两件。我实际上解决了这个问题一次(在Mac上与curl
一起使用),但我不再有精确的命令。 :-(我可以尝一尝,并写在博客上关于它的这个晚上
编辑:
下面是一个完整的Python程序,需要在命令行一个.publishsettings
文件,转储将密钥和证书放入单个文件(证书。pem),然后使用它调用服务管理API并打印所有存储帐户的名称。运行前,只需pip install lxml pyopenssl
。
import httplib
import argparse
from StringIO import StringIO
from lxml import etree
import base64
from OpenSSL.crypto import *
parser = argparse.ArgumentParser()
parser.add_argument('file', metavar='file', type=str, help='Your .publishsettings file.')
args = parser.parse_args()
tree = etree.parse(args.file)
pp = tree.find('PublishProfile')
cert = load_pkcs12(base64.decodestring(pp.get('ManagementCertificate')))
with open('cert.pem', 'w') as f:
f.write(dump_certificate(FILETYPE_PEM, cert.get_certificate()))
f.write(dump_privatekey(FILETYPE_PEM, cert.get_privatekey()))
subscription_id = pp.find('Subscription').get('Id')
conn = httplib.HTTPSConnection('management.core.windows.net', cert_file='cert.pem')
conn.request('GET', '/%s/services/storageservices' % subscription_id, headers={'x-ms-version': '2011-02-25'})
for e in etree.parse(StringIO(conn.getresponse().read())).iterfind('//{http://schemas.microsoft.com/windowsazure}ServiceName'): print e.text
这是我如何转换我在我的问题创建的证书到我可以用它来验证我的请求,在Azure服务管理API的格式。 Smarx的答案也适用,实际上我使用了他的技术创建的证书,涉及.publishsettings
文件,以确定我的转换后的证书的外观。
通过打开Visual Studio命令提示符,然后输入创建证书:
makecert -r -pe -a sha1 -n "CN=My Azure Management Certificate" -ss My -len 2048 -sp
"Microsoft Enhanced RSA and AES Cryptographic Provider" -sy 24 myazuremanagementcert.cer
的指导下http://msdn.microsoft.com/en-us/library/windowsazure/gg651127。
然后,通过在搜索框中输入certmgr.msc
来打开证书管理器。我发现我的证书在Certificates - Current User/Personal/Certificates
之下。
右键单击证书,转到“所有任务”,然后单击“导出”。出现提示时,确保选择“是,导出私钥”并将其导出为.PFX(PKCS#12)。
在这里,我将我的.PFX移动到Linux VM。从这里
一切都在如下打开终端,请在http://blog.scottlowe.org/2005/12/02/certificate-conversion-using-openssl/
中规定的步骤:
openssl pkcs12 -in pfxfilename.pfx -out tempfile.pem
这将提示你对于你用来加密的.pfx的密码和新用于加密.pem的密码。 不要将此密码留空!我做了,很困惑,因为密钥不仅仅是解密,而是不包含在新的.pem中
将新.pem中的密钥和证书分离为两个不同的文件,删除其他所有多余的行比----begin/end cert/key----
线。
通过键入解密:
openssl rsa -in encryptedkey -out decryptedkey
而且,重组的关键和证书有:
cat decryptedkey certificatefile > finalfile.pem
现在,这个证书应该正确验证服务管理请求天青:
import httplib
sub_id = [subid]
conn = httplib.HTTPSConnection('management.core.windows.net', cert_file = 'finalfile.pem')
conn.request('GET', '/%s/services/storageservices' % sub_id, headers = {'x-ms-versiojn':'2012-03-01'})
response = conn.getresponse()
print reponse.status response.reason
是你的第二个代码示例丢失了什么?我没有看到你在使用变量'cert_file'的位置。你在正确的轨道上,我怀疑你是对的,这是一个文件格式问题。 – smarx 2012-08-15 22:14:25
哎呦,修好了,谢谢你的收获。是的,在http://msdn.microsoft.com/en-us/library/windowsazure/gg651127.aspx提供的示例项目完美地工作...我不完全清楚证书如何存储和ssl身份验证的作品,但我认为这可能与我获得证书的方式有些摩擦,并且将它添加到引起问题的请求中,假设您想要坚持使用您生成的证书,请参考示例lol – 2012-08-15 22:21:07