Let me start of by saying that I am normally very reluctant to post this questions as I always feel that there's an answer to everything SOMEWHERE on the internet. After spending countless hours looking for an answer to this question, I've finally given up on this statement however.
Assumption
This works:
s3.getSignedUrl('putObject', params);
What am I trying to do?
- Upload a file via PUT (from the client-side) to Amazon S3 using the getSignedUrl method
- Allow anyone to view the file that was uploaded to S3
Note: If there's an easier way to allow client side (iPhone) uploads to Amazon S3 with pre-signed URLs (and without exposing credentials client-side) I'm all ears.
Main Problems*
- When viewing the AWS Management Console, the file uploaded has blank Permissions and Metadata set.
- When viewing the uploaded file (i.e. by double clicking the file in AWS Management Console) I get an
AccessDenied
error.
What have I tried?
Try #1: My original code
In NodeJS I generate a pre-signed URL like so:
var params = {Bucket: mybucket, Key: "test.jpg", Expires: 600};
s3.getSignedUrl('putObject', params, function (err, url){
console.log(url); // this is the pre-signed URL
});
The pre-signed URL looks something like this:
https://mybucket.s3.amazonaws.com/test.jpg?AWSAccessKeyId=AABFBIAWAEAUKAYGAFAA&Expires=1391069292&Signature=u%2BrqUtt3t6BfKHAlbXcZcTJIOWQ%3D
Now I upload the file via PUT
curl -v -T myimage.jpg https://mybucket.s3.amazonaws.com/test.jpg?AWSAccessKeyId=AABFBIAWAEAUKAYGAFAA&Expires=1391069292&Signature=u%2BrqUtt3t6BfKHAlbXcZcTJIOWQ%3D
PROBLEM
I get the *Main Problems listed above
Try #2: Adding Content-Type and ACL on PUT
I've also tried adding the Content-Type and x-amz-acl in my code by replacing the params like so:
var params = {Bucket: mybucket, Key: "test.jpg", Expires: 600, ACL: "public-read-write", ContentType: "image/jpeg"};
Then I try a good ol' PUT:
curl -v -H "image/jpeg" -T myimage.jpg https://mybucket.s3.amazonaws.com/test.jpg?AWSAccessKeyId=AABFBIAWAEAUKAYGAFAA&Content-Type=image%2Fjpeg&Expires=1391068501&Signature=0yF%2BmzDhyU3g2hr%2BfIcVSnE22rY%3D&x-amz-acl=public-read-write
PROBLEM
My terminal outputs some errors:
-bash: Content-Type=image%2Fjpeg: command not found
-bash: x-amz-acl=public-read-write: command not found
And I also get the *Main Problems listed above.
Try #3: Modifying Bucket Permissions to be public
All of the items listed below are ticked in the AWS Management Console)
Grantee: Everyone can [List, Upload/Delete, View Permissions, Edit Permissions]
Grantee: Authenticated Users can [List, Upload/Delete, View Permissions, Edit Permissions]
Bucket Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1390381397000",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::mybucket/*"
}
]
}
Try #4: Setting IAM permissions
I set the user policy to be this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
AuthenticatedUsers group policy to be this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1391063032000",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"*"
]
}
]
}
Try #5: Setting CORS policy
I set the CORS policy to this:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
And... Now I'm here.