0

我一直在学习如何通过使用开源 Eucalyptus 来使用 Amazon S3 API。到目前为止,我已经能够成功使用 REST,但现在我也想使用 SOAP。我似乎无法为我的请求生成正确的签名。该服务给我一个 403 Forbidden 错误:

Traceback (most recent call last):
  File "soap.py", line 31, in <module>
    r = w.download_file('mybucket', 'test.txt')
  File "soap.py", line 27, in download_file
    r = self.client.service.ListAllMyBuckets(self.access_key, timestamp, signature)
  File "/usr/lib/python2.6/site-packages/suds/client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "/usr/lib/python2.6/site-packages/suds/client.py", line 581, in invoke
    result = self.send(soapenv)
  File "/usr/lib/python2.6/site-packages/suds/client.py", line 619, in send
    description=tostr(e), original_soapenv=original_soapenv)
  File "/usr/lib/python2.6/site-packages/suds/client.py", line 677, in process_reply
    raise Exception((status, description))
Exception: (403, u'Forbidden')

我的代码在 Python 2 中,并使用 SUDS-Jurko 库发送 SOAP 请求:

from suds.client import Client

class WalrusSoap:
    wsdl_url = 'https://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl'
    server_url = 'https://localhost:8773/services/Walrus'

    def __init__(self, access_key, secret_key):
        self.access_key = access_key
        self.secret_key = secret_key
        self.client = Client(self.wsdl_url)
        self.client.wsdl.services[0].setlocation(self.server_url)
        #print self.client

    def create_signature(self, operation, timestamp):
        import base64, hmac, hashlib
        h = hashlib.sha1(self.secret_key)
        h.update("AmazonS3" + operation + timestamp)
        #h = hmac.new(key=self.secret_key, msg="AmazonS3" + operation + timestamp, digestmod=hashlib.sha1)
        return base64.encodestring(h.digest()).strip()

    def download_file(self, bucket, filename):
        from time import gmtime, strftime
        timestamp = strftime('%Y-%m-%dT%H:%M:%S.001Z', gmtime())
        print(timestamp)
        signature = self.create_signature('ListAllMyBuckets', timestamp)
        print(signature)
        r = self.client.service.ListAllMyBuckets(self.access_key, timestamp, signature)
        return r

w = WalrusSoap(access_key='MOBSE7FNS6OC5NYC75PG8', secret_key='yxYZmSLCg5Xw6rQVgoIuVLMAx3hZRlxDc0VOJqox')
r = w.download_file('mybucket', 'test.txt')
print(r)

我更改了服务器端点,否则 WSDL 指向 Amazon 的常规 S3 服务器。我还有两种不同的方法在我的 create_signature 函数中创建签名。我通过简单地注释掉第二个来在一个和另一个之间交换。两者似乎都不起作用。我的问题是我做错了什么?

SOAP 身份验证:http ://docs.aws.amazon.com/AmazonS3/latest/dev/SOAPAuthentication.html

SUDS-Jurko 文档:https ://bitbucket.org/jurko/suds/overview

编辑:我意识到我忘记包含一个示例,说明出于调试目的而打印的时间戳和签名。

2014-12-05T00:27:41.001Z
0h8vxE2+k10tetXZQJxXNnNUjjw=

编辑 2:另外,我知道 download_file 函数不会下载文件 :) 我仍处于测试/调试阶段

编辑 3:我知道 REST 更好用,至少根据亚马逊的说法。(我个人认为 REST 也更好。)我也已经知道 SOAP 已被 Amazon 弃用。但是,无论如何我都想走这条路,所以请帮我一个忙,不要浪费我的时间与弃用的链接。我向您保证,在编写此 SOAP 代码时,我已经清楚地意识到了弃用。事实上,我发布的其中一个链接在其页面顶部打印了弃用通知。但是,如果您有证据表明 Walrus 完全放弃了 SOAP,或者他们停止了 SOAP 部分的工作,我希望看到类似的情况。但请不要告诉我亚马逊已弃用 SOAP。

4

3 回答 3

1

S3 SOAP API 不支持“新”功能,因此应尽可能使用 REST API:

http://docs.aws.amazon.com/AmazonS3/latest/dev/SOAPAPI3.html

https://forums.aws.amazon.com/message.jspa?messageID=77821

IIRC 最新版本的 Eucalyptus 不支持带有 S3 的 SOAP。

也就是说,签名对我来说看起来不错,所以我会检查客户端/服务主机的时间是否正确,如果相差超过 15 分钟,身份验证将失败。

您还可以检查 Walrus 服务主机上的 cloud-error.log,因为那里可能有更多关于故障的详细信息。

于 2014-12-05T03:20:17.107 回答
0

Eucalyptus 确实支持 SOAP(请参阅 ZachH 关于弃用的评论): https ://www.eucalyptus.com/docs/eucalyptus/4.0.2/schemas/aws-apis/s3/index.html

我决定放弃使用 python,而是用 C# 生成了一些工作代码。原来 C# 有更好的 SOAP 库。

于 2014-12-08T03:21:22.527 回答
0

从 Eucalyptus 版本 4.0.0 起,Eucalyptus 不支持 S3 的 SOAP。

如果您使用的是旧版本的 Eucalyptus(4.0 之前),那么 SOAP 应该可以工作。但是请注意,S3 提供的 wsdl 不一定是最新的或准确的,即使是他们自己的服务。S3 因更改 API 而没有版本或 wsdl 颠簸而臭名昭著,特别是因为他们停止更新 SOAP API。因此,Walrus 的响应可能不符合已发布的 WSDL,因为我们的 XML 是根据我们从 S3(通过 REST)看到的响应进行更新的,并且 SOAP 和 REST 响应存在分歧。但是,签名应该是兼容的,所以最坏的情况是您会看到 500 或 400 错误,但不会看到 403 响应。

我的建议是,如果您真的想学习 S3 SOAP API,则必须正确使用 S3。Eucalyptus 中的 S3 SOAP 支持在 4.0 之前就已存在,但可能与 S3 SOAP 的当前状态不兼容——当 AWS 开发工具包停止使用 SOAP 以支持更好的 REST 支持时,我们直接停止了针对 S3 SOAP API 的测试,因为那是API 向前发展。

于 2014-12-05T21:55:31.237 回答