将PUT请求签名到s3

时间:2017-05-29 14:54:26

标签: python amazon-web-services amazon-s3

我正在尝试使用 curl 拨打电话来上传s3(eu-central-1)中的文件,而不使用aswcli(这是一项要求)或boto3进行上传。

我正在使用python和botocore的一些方法来签署请求,如下所示:

import datetime
from botocore.credentials import Credentials
from botocore.handlers import calculate_md5

from botocore.awsrequest import AWSRequest
from botocore.auth import S3SigV4Auth


if __name__ == "__main__":

    access_key = '<ACCESS>'
    secret_key = '<SECRET>'

    bucket = 'mybucket'

    region = 'eu-central-1'
    host = 's3.eu-central-1.amazonaws.com'

    SIGV4_TIMESTAMP = '%Y%m%dT%H%M%SZ'
    datetime_now = datetime.datetime.utcnow()
    xamzdate = datetime_now.strftime(SIGV4_TIMESTAMP)
    auth_time = xamzdate[0:8]

    filename = 'img.jpg'
    f = open(filename, 'rb')
    body = f.read()

    req = {
        'body': body,
        'headers': {}
    }
    calculate_md5(req)

    contentMd5 = req['headers']['Content-MD5']

    url = 'https://{host}/{bucket}'.format(host=host, bucket=bucket)
    params = {'encoding-type': 'url'}
    headers = {
        'Content-MD5': contentMd5,
        'X-Amz-Date': xamzdate,  # '20170529T120930Z'
        'X-Amz-Content-SHA256': 'UNSIGNED-PAYLOAD',
        'X-Amz-Acl': 'public-read',

    }
    request = AWSRequest('PUT', url, data=body, params=params, headers=headers)
    credentials = Credentials(secret_key=secret_key, access_key=access_key)

    signer = S3SigV4Auth(credentials=credentials, service_name='s3', region_name=region)
    signer.add_auth(request)

    signature = request.headers['X-Amz-Content-SHA256']

    auth = 'AWS4-HMAC-SHA256 Credential={access_key}/{auth_time}/eu-central-1/s3/aws4_request, ' \
           'SignedHeaders=content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date, ' \
           'Signature={signature}'.format(access_key=access_key,
                                          auth_time=auth_time,
                                          signature=signature,)

    print """
    curl -X PUT -T "{filename}" \
    -H "X-Amz-Date: {xamzdate}" \
    -H "Content-MD5: {contentMd5}" \
    -H "X-Amz-Content-SHA256: UNSIGNED-PAYLOAD" \
    -H "X-Amz-Acl: public-read" \
    -H "Authorization: {auth}" \
    https://{host}/{bucket}/{filename}
    """.format(host=host, bucket=bucket, xamzdate=xamzdate, contentMd5=contentMd5,
               filename=filename, auth=auth)

此python代码的输出是

curl -X PUT -T "img.jpg"     -H "X-Amz-Date: 20170529T143549Z"     -H "Content-MD5: 9WXctE9k50XC/AKwC6yYwQ=="     -H "X-Amz-Content-SHA256: UNSIGNED-PAYLOAD"     -H "X-Amz-Acl: public-read"     -H "Authorization: AWS4-HMAC-SHA256 Credential=<ACCESS_KEY>/20170529/eu-central-1/s3/aws4_request, SignedHeaders=content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date, Signature=a54ad95ede0d2ff18272bbded9e1940e71065082056ba7a76c38b45beda1b763"     https://s3.eu-central-1.amazonaws.com/MYBUCKET/img.jpg

我替换了Credential中的access_key =和url中的存储桶名称。 该命令的结果是:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <AWSAccessKeyId>MY ACCESS KEY</AWSAccessKeyId>
    <StringToSign>AWS4-HMAC-SHA256
20170529T143549Z
20170529/eu-central-1/s3/aws4_request
8901111961918762ddf496956f95d8ea9bcdb2345dee53ef8c0fb0ec49644464
    </StringToSign>
    <SignatureProvided>a54ad95ede0d2ff18272bbded9e1940e71065082056ba7a76c38b45beda1b763</SignatureProvided>
    <StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 31 37 30 35 32 39 54 31 34 33 35...</StringToSignBytes>

    <CanonicalRequest>PUT
/mybucket/img.jpg

content-md5:9WXctE9k50XC/AKwC6yYwQ==
host:s3.eu-central-1.amazonaws.com
x-amz-acl:public-read
x-amz-content-sha256:UNSIGNED-PAYLOAD
x-amz-date:20170529T143549Z

content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date
UNSIGNED-PAYLOAD

</CanonicalRequest>
    <CanonicalRequestBytes>50 55 54 0a 2f 72 7a 76 65 75 63 65 6e 74 72 61 6c 31 2f 69 6d 67...</CanonicalRequestBytes>
    <RequestId>BC854A452F8F92A5</RequestId>
    <HostId>vDY8VPIO2n/DoTagpEaUANekON0gpWPQrWfVY2QQ09srXRkgX/O3fvgyT2fNdYhiBXQrgs4yoC4=</HostId>
</Error>

似乎我想念一些东西。有没有人向s3签署一个put请求的工作示例?

1 个答案:

答案 0 :(得分:0)

我同时弄清楚如何为S3编写异步客户端,我发布了一篇博文和github上的代码。