S3 Bucket Lambda Event: Unable to validate the following destination configurations

You are getting this message because your s3 bucket is missing permissions for invoking your lambda function.

According to AWS documentation! there are two types of permissions required:

  1. Permissions for your Lambda function to invoke services
  2. Permissions for Amazon S3 to invoke your Lambda function

You should create an object of type 'AWS::Lambda::Permission' and it should look similar to this:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "<optional>",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "<ArnToYourFunction>",
      "Condition": {
        "StringEquals": {
          "AWS:SourceAccount": "<YourAccountId>"
        },
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:s3:::<YourBucketName>"
        }
      }
    }
  ]
}

Finally looked at this again after a year. This was a hackathon project from last year that we revisted. @davor.obilinovic's answer was very helpful in pointing me to the Lambda permission I needed to add. Still took me a little bit to figure out exactly what I needed it to look like.

Here are the AWS JavaScript SDK and Lambda API docs https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#addPermission-property https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html

The JS SDK docs have this line:

SourceArn: "arn:aws:s3:::examplebucket/*",

I couldn't get it working for the longest time and was still getting the Unable to validate the following destination configurations error.

Changing it to

SourceArn: "arn:aws:s3:::examplebucket",

fixed that issue. The /* was apparently wrong and I should have looked at the answer I got here more closely but was trying to follow the AWS docs.

After developing for a while and creating lots of buckets, Lambda permissions and S3 Lambda notifications, calling addPermission started throwing a The final policy size (...) is bigger than the limit (20480). Adding new, individual, permissions for each bucket adds them to the bottom of the Lambda Function Policy and apparently that policy has a max size.

The policy doesn't seem editable in the AWS Management Console so I had fun deleting each entry with the SDK. I copied the policy JSON, pulled the Sids out and called removePermission in a loop (which threw rate limit errors and I had to run it many times).

Finally I discovered that omitting the SourceArn key will give Lambda permission to all S3 buckets.

Here's my final code using the SDK to add the permission I needed. I just ran this once for my function.

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

aws.config.update({
  accessKeyId:     process.env.AWS_ACCESS,
  secretAccessKey: process.env.AWS_SECRET,
  region:          process.env.AWS_REGION,
});

// Creates Lambda Function Policy which must be created once for each Lambda function
// Must be done before calling s3.putBucketNotificationConfiguration(...)
function createLambdaPermission() {
  const lambda = new aws.Lambda();

  const params = {
    Action:        'lambda:InvokeFunction',
    FunctionName:  process.env.AWS_LAMBDA_ARN,
    Principal:     's3.amazonaws.com',
    SourceAccount: process.env.AWS_ACCOUNT_ID,
    StatementId:   `example-S3-permission`,
  };

  lambda.addPermission(params, function (err, data) {
    if (err) {
      console.log(err);
    } else {
      console.log(data);
    }
  });
}