简体   繁体   中英

AWS S3's getSignedUrl for put object returns 403

I am trying to get a pre-signed URL to upload files to the S3 bucket. Here is my workflow:

1. Invoke Lambda -> 2. Get pre-signed URL -> 3. Hit the URL (PUT) with file

1. Invoke Lambda

I made sure the AWS keys have the correct permission. In fact, it has full access. Here is the Source code:

AWS.config.update({
  accessKeyId: '*****************',
  secretAccessKey: '*****************',
  region: 'us-east-1',
  signatureVersion: 'v4'
});

let requestObject = JSON.parse(event["body"]);
let fileName = requestObject.fileName;
let fileType = requestObject.fileType;
const myBucket = 'jobobo-resumes';

s3.getSignedUrl('putObject', {
"Bucket": myBucket,
"Key": fileName,
"ContentType": fileType
}, function (err, url) {

  if (err) {    
  mainCallback(null, err);
  } else {    
  mainCallback(null, url);    
  }

}

So, I am getting the filename, file type(MIME) from the request and use that to create the signature.

2. Get pre-signed URL When I hit the Lambda I get the pre-signed URL. Now, I will use this URL to upload the file to S3.

获取预签名 URL

3. Hit the URL (PUT) with file

Now, I hit the URL with HTTP method and I add the file (binary), see my Postman request:

在此处输入图像描述

You can see that I hit the request with the PUT HTTP Method. I get the 403 error. Here are the headers in the request and you can see that the content-type is image/jpeg :

在此处输入图像描述

When I try the POST method, I get that the signature is invalid. I guess that is because of the signature is signed for the PUT method.

在此处输入图像描述

Here is the S3 bucket's settings:

Since I get access denied, I completely opened the bucket, I mean Block Public access: off .

在此处输入图像描述

What is wrong with the settings? Maybe S3?

You have a service object in the variable s3 but you don't show, in your code, where that object was constructed... but it appears to be before you call AWS.config.update() which doesn't retroactively reconfigure your s3 object. The order of these operations is the problem.

Updates you make to the global AWS.config object don't apply to previously created service objects.

https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html

If you observe your generated URL closely you can see that the Lambda Execution Role credentials are actually being used, which is why access is denied.

The giveaways are that the AWSAccessKeyId in the URL is not yours, it's a session key beginning with ASIA instead of AKIA like a normal Access Key ID. Also, there's a session token x-amz-security-token which wouldn't be there in a URL generated with static credentials. Also this URL is Signature V2, so when you correct the credential configuration issue, the format of the signed URL will change significantly. Signature V4 URLs have X-Amz-Credential instead of AWSAccessKeyId .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM