AWS Lambda - CredentialsProviderError

0

I am encountering a "CredentialsProviderError" in my AWS Lambda function. The Lambda function is designed to interact with Amazon S3. The primary task of this Lambda function involves fetching a JSON file from a specified S3 bucket and responding with the retrieved data.

Despite having an IAM role associated with the function and the appropriate policies attached, the Lambda execution is failing to load credentials from any providers. This operation worked seamlessly when the Lambda function was utilizing AWS SDK v2. However, upon migrating to AWS SDK v3, the Lambda function encounters a "CredentialsProviderError."

The Lambda function does not explicitly set AWS SDK credentials, as it is expected to inherit them from the execution role.

Execution Role Trust Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

IAM Policy Attached to Execution Role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "s3-object-lambda:*"
            ],
            "Resource": "*"
        }
    ]
}
profile picture
asked 2 months ago141 views
1 Answer
0

Hi Utsab,

this might be related to a change in behavior with the AWS SDK v3. A similar issue is documented in this GitHub issue: https://github.com/aws/aws-sdk-js-v3/issues/4867

Could you maybe share the relevant code parts of your Lambda function to help narrow this down?

Thanks, Ben

profile pictureAWS
EXPERT
answered 2 months ago
  • Hi Ben, thank you for your prompt response.

    As I mentioned earlier, the Lambda function is quite straightforward. It simply retrieves a JSON file from an S3 bucket and returns the corresponding JSON response.

    import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
    import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
    
    const credentials = fromNodeProviderChain();
    const s3 = new S3Client({ credentials });
    
    const Bucket = "<bucket-name>"
    const Key = "<file-name>"
    
    export const handler = async function (event) {
      try {
        const command = new GetObjectCommand({ Bucket, Key });
        const response = await s3.send(command);
        const str = await response.Body.transformToString(); 
        const body = JSON.parse(str);
        return {
          statusCode: 200,
          body,
        }
      } catch (err) {
        console.error('Failed to get the file from S3', err);
        throw err;
      }
    };
    
  • Thanks for sharing the code. Is there a particular reason why you need the credentials explicitly? You can just create the S3 Client without additional configuration. See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html for

    AWS SDK for JavaScript V3 provides a default credential provider chain in Node.js, so you are not required to supply a credential provider explicitly.

    Please be also aware that as per documentation https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html, you normally don't need to use fromNodeProviderChain explicitly:

    but with default role assumers so you don't need to import them from STS client and supply them manually. You normally don't need to use this explicitly in the client constructor.

  • Appreciate the detailed explanation! I initially faced issues with the default configuration of the S3 client, resulting in Could not load credentials from any providers error. To address this, I added fromNodeProviderChain as a precautionary measure. Interestingly, it didn't resolve the issue either.

    import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
    
    const s3 = new S3Client({ region: 'eu-west-1' });
    
    const Bucket = "<bucket-name>"
    const Key = "<file-name>"
    
    export const handler = async function (event) {
      try {
        const command = new GetObjectCommand({ Bucket, Key });
        const response = await s3.send(command);
        const str = await response.Body.transformToString(); 
        const body = JSON.parse(str);
        return {
          statusCode: 200,
          body,
        }
      } catch (err) {
        console.error('Failed to get the file from S3', err);
        throw err;
      }
    };
    
  • Hi, thanks for the quick response. Have you tried using the @aws-sdk/credential-provider-node instead. See also the comment on this question: https://repost.aws/questions/QUXMX9z9zCSb21qsnedFZQpg/having-trouble-converting-aws-node-sdk-v2-lambda-to-v3

  • Tried using the @aws-sdk/credential-provider-node as well. Still getting the same error

    import { defaultProvider } from '@aws-sdk/credential-provider-node';
    import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
    
    const s3 = new S3Client({ region:'eu-west-1',  credentials: defaultProvider() });
    

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions