How do I put object to amazon s3 using presigned u

2019-03-17 22:10发布

I am trying to use signed url to upload images to s3 bucket. Following is my bucket policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::12345678:user/myuser",
                    "arn:aws:iam::12345678:root"
                ]
            },
        "Action": [
                "s3:List*",
                "s3:Put*",
                "s3:Get*"
            ],
            "Resource": [
                "arn:aws:s3:::myBucket",
                "arn:aws:s3:::myBucket/*"
            ]
        }
    ]
}

I am generating the signed url from the server as follows:

var aws = require('aws-sdk');
aws.config = {
    accessKeyId: myAccessKeyId,
    secretAccessKey: mySecretAccessKey
};

var s3 = new aws.s3();
s3.getSignedUrl('putObject', {
    Bucket: 'myBucket',
    Expires: 60*60,
    key: 'myKey'
}, function (err, url) {
    console.log(url);
});

I get the url. But when I try to put an object I get the following error:

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>FXXXXXXXXX</RequestId>
    <HostId>fXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</HostId>
</Error>

Update 1

Here is myuser's policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Sid": "",
        "Effect": "Allow",
        "Principal": {
            "AWS": [
                "arn:aws:iam::2xxxxxxxxxxx:user/myuser",
                "arn:aws:iam::2xxxxxxxxxxx:root"
            ]
        },
        "Action": [
            "s3:*"
        ],
        "Resource": [
            "arn:aws:s3:::myBucket",
            "arn:aws:s3:::myBucket/*"
        ]
    }
  ]
}

Update 2 I can upload only when following option is set. I dont understand whats the use of bucket policy if only the manual selection of permission work.

Permission for everyone

Update 3

The following code works. Now the only problem is the signed url

 #!/bin/bash

 file="$1"

 bucket="mybucket"
 resource="/${bucket}/${file}"
 contentType="image/png"
 dateValue=`date -R`
 stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
 s3Key="AKxxxxxxxxxxxxxxxxx"
 s3Secret="/Wuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
 signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret}     -binary | base64`
 curl -X PUT -T "${file}" \
   -H "Host: ${bucket}.s3.amazonaws.com" \
   -H "Date: ${dateValue}" \
   -H "Content-Type: ${contentType}" \
   -H "Authorization: AWS ${s3Key}:${signature}" \
   https://${bucket}.s3.amazonaws.com/${file}

4条回答
干净又极端
2楼-- · 2019-03-17 22:51

I managed to succesfully upload a file by using your code.

Here are the steps I followed:

  1. Created a new bucket and a new IAM user

  2. Set IAM user's policy as below:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Stmt1418647210000",
                "Effect": "Allow",
                "Action": [
                    "s3:Put*"
                ],
                "Resource": [
                    "arn:aws:s3:::myBucket/*"
                ]
            }
        ]
    }
    
  3. Did NOT create a bucket policy

  4. Used your code to generate the pre-signed URL:

    var aws = require('aws-sdk');
    aws.config = {
        accessKeyId: myAccessKeyId,
        secretAccessKey: mySecretAccessKey
    };
    
    var s3 = new aws.s3();
    s3.getSignedUrl('putObject', {
        Bucket: 'myBucket',
        Expires: 60*60,
        Key: 'myKey'
    }, function (err, url) {
        console.log(url);
    });
    
  5. Copied the URL on the screen and used curl to test the upload as below:

    curl.exe -k -X PUT -T "someFile" "https://myBucket.s3.amazonaws.com/myKey?AWSAccessKeyId=ACCESS_KEY_ID&Expires=1457632663&Signature=Dhgp40j84yfjBS5v5qSNE4Q6l6U%3D"
    

In my case it generally took 5-10 seconds for the policy changes to take effect so if it fails the first time make sure to keep sending it for a while.

Hope this helps.

查看更多
聊天终结者
3楼-- · 2019-03-17 22:56
  1. In your IAM console, click Users
  2. On the right list, choose the IAM user you used(should be 'myuser')
  3. Choose Permissions on the sub tabs
  4. Click Attach Policy and choose AmazonS3FullAccess

The final page will be like this.

You may also check Security Credentials sub tab, your accessKeyId should be on the list. The secretAccessKey just can not get again.

查看更多
一纸荒年 Trace。
4楼-- · 2019-03-17 22:58

You've correctly set up the permissions on the bucket, to allow access from the user.

But you also need to edit the policy of the user, to allow the user to access the S3 service.

Edit the IAM policy of the user whose credentials you're using to generate the self-signed URL. Something like this will definitely cover everything:

{
  "Statement": [
    {
      "Sid": "AllowAllS3Access",
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
查看更多
甜甜的少女心
5楼-- · 2019-03-17 22:58

It may help you too :) Add a ContentType property :

s3.getSignedUrl('putObject', {
    Bucket: 'myBucket',
    Expires: 60*60,
    Key: 'myKey',
    ContentType: 'image/jpeg',
}, function (err, url) {
   console.log(url);
});
查看更多
登录 后发表回答