Generating Amazon S3 CORS signature with Python

♀尐吖头ヾ 提交于 2019-12-11 02:35:45

问题


I'm having a hell of a time getting S3 to accept uploads via CORS POST request generated by PhoneGap (Cordova) FileTransfer.upload(). Any suggestions as to what I may be missing would be appreciated. Currently I'm getting a 403 AccessDenied response using the code below. I've been over it many times comparing with S3's documentation, and can't figure out the problem.

Here is the Python code that generates the signature:

# Create policy document for S3.
policy_obj = {"expiration": "2014-01-01T00:00:00Z",
  "conditions": [ 
    {"bucket": "<my.bucket.name>"}, 
    ["starts-with", "$key", "story_"],
    {"acl": "public-read"},
    ["eq", "$Content-Type", "audio/mp4"],
    ["content-length-range", str(0), str(2097152)]
  ]
}

policy = base64.b64encode(json.dumps(policy_obj))

# Create signature for S3
signature = base64.b64encode(
    hmac.new(
        key=app.config['AWS_SECRET_KEY'], 
        msg=policy, 
        digestmod=hashlib.sha1
    ).digest()
)

The signature generated by this process matches the signature produced by S3 Signature Tester (converting the base64 policy into Hex and then running that through the Signature Tester with the secret key).

The resulting policy & signature are passed to the client, and the request to S3 is built with this PhoneGap FileTransfer call:

// Upload file to Amazon S3
// r is the response object generated by Python
var options = new FileUploadOptions();
options.chunkedMode = false;
options.mimeType="audio/mp4";
options.fileKey='file';
options.fileName='story_' + uniqueKey + '.m4a';
options.params={
    "key": "${filename}",
    "acl": "public-read",
    "AWSAccessKeyId": r.aws_access_key,
    "Policy": r.policy,
    "Signature": r.signature,
};

var ft = new FileTransfer();
ft.upload(path, "http://<my.bucket.name>.s3.amazonaws.com/", uploadSuccess, uploadFail, options);

This is the CORS configuration (yes, I plan to lock it down once I get the uploads working):

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

This is the bucket policy:

{
    "Version": "2008-10-17",
    "Id": "Policy1356975063803",
    "Statement": [
        {
            "Sid": "Stmt1357234455973",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<my.bucket.name>/*"
        },
        {
            "Sid": "Stmt1356975061658",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::293855469575:root"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::<my.bucket.name>"
        }
    ]
}

UPDATE:

This is what the policy itself looks like after Python has converted the object into JSON:

{
  "conditions": [
    {
      "bucket": "<my.bucket.name>"
    }, 
    [
      "starts-with", 
      "$key", 
      "story_"
    ], 
    {
      "acl": "public-read"
    }, 
    [
      "eq", 
      "$Content-Type", 
      "audio/mp4"
    ], 
    [
      "content-length-range", 
      "0", 
      "6291456"
    ]
  ], 
  "expiration": "2014-01-01T00:00:00Z"
}

回答1:


Did you try removing newlines in your policy?

Here is the Ruby code for the policy, courtesy of s3_file_upload:

Base64.encode64(policy_data.to_json).gsub("\n", "")

Please let me know if you managed to get your upload to work, as I'm trying to do the same thing.



来源:https://stackoverflow.com/questions/14165921/generating-amazon-s3-cors-signature-with-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!