I have a NodeJS application on my local machine. I am trying to set it up with Amazon S3 services, but unfortunately, it doesn't work. I am able to get signed URL, but when uploading a file AWS returns Forbidden 403 (several times it dropped connection, but stopped after I removed timeout option from CORS)
What I have done so far:
Created new user with fallowing policy:
{ "Statement": [ { "Action": "s3:*", "Effect": "Allow", "Resource": [ "arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*" ] } ] }
Created new access key for this user
Updated CORS for bucket to
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>
Updated bucket policy
{ "Version": "2012-10-17", "Statement": [ { "Sid": "111", "Effect": "Allow", "Principal": { "AWS": "my-user-id-number" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::my-bucket/*" } ] }
Created call to sign url in NodeJS (with Express)
aws.config.accessKeyId = process.env.AWS_ACCESS_KEY_ID; aws.config.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY; router.get('/sign-s3', function (req, res) { var s3 = new aws.S3(); var fileName = req.query.fileName; var fileType = req.query.fileType; var s3Params = { Key: fileName, Bucket: process.env.S3_BUCKET_NAME, Expires: 600, ContentType: fileType, ACL: 'public-read' }; s3.getSignedUrl('putObject', s3Params, function (err, data) { if (err) { console.log(err); return res.end(); } var returnData = { signedRequest: data, url: 'https://${S3_BUCKET_NAME}.s3.amazonaws.com/${fileName}' }; res.write(JSON.stringify(returnData)); res.end(); }); });
Upload file
$http({ method: 'GET', url: '/aws/sign-s3', params: data }).then(function (response) { var fd = new FormData(); fd.append("file", file); $http({ method: 'PUT', url: response.data.signedRequest, data: fd }).then(function (response) { defer.resolve(response); }, function (err) { defer.reject(err); }); }, function (err) { defer.reject(err); });
There is one more thing I don't understand: i created a user and gave it access to s3, but I can't assign user to bucket in bucket permission. Is it missing something in access policy?
Thanks in advance for any hints!
I have figured out.
First of all, I generated new access keys to make sure these are correct. Second, I updated my upload request, to set content-type and to serialise only file, instead of FormData with file.
So the upload request looks