【问题标题】:How do I authenticate a management service request to Windows Azure?如何验证对 Windows Azure 的管理服务请求?
【发布时间】:2012-08-15 21:36:44
【问题描述】:

我正在尝试通过 Python 向 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 安装到某种证书存储中 - 在 Linux 中是否有一个等效项,我需要在使用它进行身份验证之前从中检索证书?感谢您的帮助 =)

【问题讨论】:

  • 您的第二个代码示例是否遗漏了什么?我看不到您在哪里使用变量cert_file。你在正确的轨道上,我怀疑你是对的,这是一个文件格式问题。
  • 哎呀,修好了,谢谢你的收获。是的,msdn.microsoft.com/en-us/library/windowsazure/gg651127.aspx 提供的示例项目完美运行......我并不完全清楚证书的存储方式和 ssl auth 的工作方式,但我认为这可能与我获取证书和添加的方式有些摩擦它是导致问题的请求,考虑到它在示例中完成的花哨方式lol

标签: python ssl azure ssl-certificate


【解决方案1】:

这里有一些可用的 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_filekey_file)。

您已经拥有证书文件,但我认为您实际上可能需要通过 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 文件,将密钥和证书转储到当前目录中的单个文件 (cert.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

【讨论】:

  • 顺便说一句,如果您想坚持使用您生成的证书,您应该能够将其导出为 PFX,然后改用 cert = load_pkcs12(the_pfx_contents)
  • 我确实为此写了一篇博文:blog.smarx.com/posts/wa-smapi-python。我在那里更改了一些代码,主要是为了使它对 Windows 友好。
  • 要跟进似乎是最初的问题 - 将您的代码创建的证书与 makecert 创建的证书进行比较,我收到的 .cer 似乎是使用 DER 编码的,但是当我使用 Base_64 重新导出它时,我可以以纯文本形式查看它 - 它只有证书组件,没有私钥。查看 MMC 中的证书(MSFT MGMT CNSL),证书肯定是使用私钥生成的,但我仍然不确定如何单独导出或与证书一起导出。
  • 这引用了我在 MMC 中使用的同一个 snap... 但是,我最终确实弄清楚了如何从我最初创建的证书中获取可用的证书,我将详细说明它是如何工作的这个问题的额外答案
【解决方案2】:

这就是我如何将我在问题中创建的证书转换为一种格式,我可以使用它来验证我对 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

现在,此证书应正确验证对 Azure 的服务管理请求:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 2018-01-07
    • 2017-04-02
    相关资源
    最近更新 更多