aws / aws-sdk-js

AWS SDK for JavaScript in the browser and Node.js
https://aws.amazon.com/developer/language/javascript/
Apache License 2.0
7.59k stars 1.55k forks source link

InvalidSignature when calling S3.getObject on object lambda access point with special characters #4209

Closed robwruck closed 1 month ago

robwruck commented 2 years ago

Describe the bug

When calling s3.getObject() on an S3 Object Lambda Access Point, the request fails with InvalidSignature when the specified Key contains special characters such as =. Same result when URL encoding the special characters (e.g. to %3D). It does not matter whether the file actually exists or is handled by the object lambda. The same file can be fetched using the equivalent call in the AWS SDK for Java.

Expected Behavior

s3.getObject() should work with special characters, ideally without need for manual URL escaping.

Current Behavior

s3.getObject() throws InvalidSignature.

Reproduction Steps

Lambda code (try each variant for keyToFetch):

console.log('Loading function');

const aws = require('aws-sdk');

const s3 = new aws.S3();

exports.handler = async (event, context) => {
//    const keyToFetch = 'my-key';
    const keyToFetch = 'my=key';
//    const keyToFetch = 'my%3Dkey';
    console.log("Fetching "+keyToFetch);

    const data = await s3.getObject({
        Bucket: 'arn:aws:s3-object-lambda:eu-central-1:XXXXXXXXXXX:accesspoint/olambda-ap1',
        Key: keyToFetch,
    }).promise();

    if (!data.Body)
        console.log("Failed to fetch file");
    else
        console.log(data.Body.toString('utf-8').length);

    return { 'status_code': 200 };
};

Possible Solution

No response

Additional Information/Context

No response

SDK version used

Bundled with Lambda runtime Node.js 16.x

Environment details (OS name and version, etc.)

Lambda x86_64

ajredniwja commented 2 years ago

Hey @robwruck thanks for opening this issue, the lambda by default ships older version of the SDK https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html How to deploy latest version with lambda. I'll test the same with the latest version of the SDK and post my findings.

sayhimatt commented 6 months ago

Hey @robwruck thanks for opening this issue, the lambda by default ships older version of the SDK https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html How to deploy latest version with lambda. I'll test the same with the latest version of the SDK and post my findings.

@ajredniwja This issue is still occurring on Node.js 16.x when used on version 2 of the Javascript SDK. Please post your findings.

aBurmeseDev commented 5 months ago

Hi all - I just stumbled upon this issue and apologies for the long wait.

@robwruck - this error is caused by your signing method, your key in this case. Can you please upgrade your SDK to latest version, regenerate the key and give it a shot? I'm not able to reproduce it on my end with current version 2.1609.0.

@sayhimatt - unless your issue was resolved, can you please open a new one with your code example?

robwruck commented 5 months ago

Hi @aBurmeseDev, just tested: It still does not work with the SDKv2 shipped on NodeJS 16.x Lambdas (whatever version that is). The file can be fetched from the bucket directly and also from a regular S3 access point but not from an Object Lambda access point. It works with SDKv3 though (NodeJS 18.x or 20.x Lambdas) so it's no longer relevant for me...

aBurmeseDev commented 4 months ago

Thanks for your reply, it sounds like it's working out for you with v3 now. Though I'm still not able to reproduce with v2, let me know if you'd like us to further debug your v2 code. If not, I'll go ahead and close this now.

sayhimatt commented 4 months ago

@aBurmeseDev Make a new lambda with runtime Node.js 16.x with architecture x86_64 here is a small code snippet that reproduces it, simply add a valid object lambda as the bucket.


const aws = require('aws-sdk');
const s3 = new aws.S3();

exports.handler = async (event, context) => {
  // Get the object from the event and show its content type
  const bucket = 'arn:aws:s3-object-lambda:us-east-2:account:accesspoint/object-lambda-name';
  let key = 'my=key' // this won't and provides a InvalidSignature
  //let key = 'mykey' // this will work
  const params = {
      Bucket: bucket,
      Key: key,
  }; 
  try {
    console.log(key);
      const { ContentType } = await s3.getObject(params).promise();
      console.log('CONTENT TYPE:', ContentType);
      return ContentType;
  } catch (err) {
      console.log(err);
      const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
      //console.log(message);
      throw new Error(err);
  }
};
aBurmeseDev commented 1 month ago

@sayhimatt - Node.js 16 is no longer supported in Lambda runtimes, please upgrade to recent version of Node and feel free to open new issue. Closing this one.