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.
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}
Navigate to the AWS S3 console and click on your bucket's name. Use the search input to find the object if necessary. Click on the checkbox next to the object's name. Click on the Copy URL button.
S3 pre-signed URLs are a form of an S3 URL that temporarily grants restricted access to a single S3 object to perform a single operation — either PUT or GET — for a predefined time limit. To break it down: It is secure — the URL is signed using an AWS access key.
By default, all S3 objects are private. Only the object owner has permission to access them. However, the object owner can optionally share objects with others by creating a presigned URL, using their own security credentials, to grant time-limited permission to download the objects.
I managed to succesfully upload a file by using your code.
Here are the steps I followed:
Created a new bucket and a new IAM user
Set IAM user's policy as below:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1418647210000", "Effect": "Allow", "Action": [ "s3:Put*" ], "Resource": [ "arn:aws:s3:::myBucket/*" ] } ] }
Did NOT create a bucket policy
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); });
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.
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); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With