5
votes

I just can't figure out what is wrong with my Bucket Policy in AWS. Trying to let a Lambda function to access and read an email from the S3 Bucket. But I keep getting "Access Denied"

Please note that I notice the email file is being created in the bucket. Here is my last version of the Bucket Policy:

{
    "Version": "2012-10-17",
    "Id": "Lambda access bucket policy",
    "Statement": [
        {
            "Sid": "All on objects in bucket lambda",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[MY NUMBER]:root"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::[MY BUCKET NAME]/*"
        }
    ]
}

I have tried also with "Principal": {"Service": "ses.amazonaws.com"}, alas

I keep getting Access Denied:

2017-09-17T14:12:14.231Z 10664101-9bb2-11e7-ad43-539f3e1a8626
{
    "errorMessage": "Access Denied",
    "errorType": "AccessDenied",
    "stackTrace": [
        "Request.extractError (/var/runtime/node_modules/aws-sdk/lib/services/s3.js:577:35)",
        "Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)",
        "Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)",
        "Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)",
        "Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)",
        "AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)",
        "/var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10",
        "Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)",
        "Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)",
        "Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:115:18)"
    ]
}

And here is my Lambda function:

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

var bucketName = '[MY BUCKET NAME]';

exports.handler = function(event, context, callback) {
    console.log('Process email');

    var sesNotification = event.Records[0].ses;
    if(!sesNotification) {
        callback(null, null);
        return;
    }

    console.log("SES Notification:\n", JSON.stringify(sesNotification, null, 2));

    // Retrieve the email from your bucket
    s3.getObject({
            Bucket: bucketName,
            Key: sesNotification.mail.messageId
        }, function(err, data) {
            if (err) {
                console.log(err, err.stack);
                callback(err);
            } else {
                console.log("Raw email:\n" + data.Body);

                // Custom email processing goes here

                callback(null, null);
            }
        });
};

After long time and many versions of the Bucket Policy I am thinking of trying another solution and drop AWS.

Any ideas ?

1

1 Answers

9
votes

You need to create an IAM role and attach it to the Lambda function with S3FullAccess policy or with finegrained permission for the specific bucket and actions (Recommended).

Also make sure trust relationship configuration is added to the role.

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

Note: In your current setup, it seems like you have configured the bucket policy which grants read access to the root user.