Uche Ozoemena
Uche Ozoemena

Reputation: 926

Getting "AccessDenied: Access Denied" inside lambda when getting an object from s3

Update 2

I've tried changing our custom policy to allow access to the particular bucket that's giving the AccessDenied error, without any luck. Imagine that bucket1 is a bucket that the lambda normally accesses, and bucket2 is the bucket that's throwing AccessDenied when the lambda accesses it. I've changed the Resource block from

{
        ...
        {
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::us-east-1-bucket1/*",
            "Effect": "Allow"
        }
        ...

to

{
        ...
        {
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::us-east-1-bucket1/*",
                "arn:aws:s3:::us-east-1-bucket2/*"
            ],
            "Effect": "Allow"
        }
        ...

I'm still getting the AccessDenied error.


Update

Per @Caldazar's comment about IAM users vs roles, the lambda's execution role has 3 policies:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords",
                "xray:GetSamplingRules",
                "xray:GetSamplingTargets",
                "xray:GetSamplingStatisticSummaries"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:*"
            ],
            "Resource": "arn:aws:logs:us-east-1:*:log-group:/aws/lambda/*:*:*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetObject"
            ],
            "Resource": "arn:aws:s3:::us-east-1-bucket1/*",
            "Effect": "Allow"
        }
    ]
}

In lambda@edge I have an origin-response response lambda that is trying to pull an object out of s3 to be used as the response. However I'm getting this AccessDenied error when I try to list the contents of the bucket using a particular prefix. This is my code:

const getVidS3 = (s3, bucketName, fileName) =>
    new Promise((res, rej) => {
        const start = Date.now();
        s3.listObjects(
            {
                Bucket: bucketName,
                Delimiter: '/',
                Prefix: `${fileName}/`,
                MaxKeys: 1,
            },
            function (err, data) {
                console.log(
                    '================ milliseconds to list objects:',
                    Date.now() - start
                );
                if (err) return rej(err);
                if (!Array.isArray(data.Contents) || data.Contents.length < 1) {
                    return rej('original raw video not found');
                }
                console.log('============= s3 objects:', data);
                const rawVidFileKey = data.Contents[0].Key;
                s3.getObject(
                    {
                        Bucket: bucketName,
                        Key: rawVidFileKey,
                    },
                    (err, data) => {
                        console.log(
                            '================ milliseconds to get video object:',
                            Date.now() - start
                        );
                        if (err) {
                            return rej(err);
                        }

                        const contentType = data.ContentType;
                        const video = data.Body;
                        console.log('=============== S3 video data', data);
                        return res({ video, contentType });
                    }
                );
            }
        );
    });

The error is from listObjects. I've gone over this set of suggestions but I'm not sure I took the right steps because I used the IAM user that I use to access the dashboard, which may have higher permissions than the one the lambda uses. More so, I recreated this getVidS3 function locally using my admin credentials and it works, so I think I need help determining how to give the lambda the appropriate permissions. I didn't create the system and I'm not very proficient with aws, so bear with me if this feels incomplete. What/where else can I check to see why this is happening? Thanks in advance.

Upvotes: 0

Views: 1189

Answers (1)

Caldazar
Caldazar

Reputation: 3757

The problem is in your policy. The policy allows GET of the objects, but not List. You're missing the ListBucket action on the bucket itself.

You need to change this:

{
        "Action": [
            "s3:GetObject"
        ],
        "Resource": "arn:aws:s3:::us-east-1-bucket1/*",
        "Effect": "Allow"
    }

To this:

{
        "Action": [
            "s3:GetObject",
            "s3:ListBucket"
        ],
        "Resource": [
             "arn:aws:s3:::us-east-1-bucket1/*",
             "arn:aws:s3:::us-east-1-bucket1"
         ]
        "Effect": "Allow"
    }

Upvotes: 2

Related Questions