Search code examples
amazon-web-servicesamazon-s3aws-lambdaamazon-cloudfrontaws-lambda-edge

How access S3 bucket object in cloudfront lambda@Edge Function?


I have a Lambda function which is associated to my cloudfront distribution.

I want access some S3 Bucket objects in this egde@lambda function. I did not find a way to do that and do not know what is the best way to do this and have the minimum delay.

I do not want to access bucket objects using http calls to the bucket because it will give some delay in cloudfront response.

Anyone know how I can access my S3 Bucket related to my cloudfront distribution in edge lambda function?

Many Thanks.


Solution

  • You need to grant permissions to the IAM role associated with your lambda. From AWS docs:

    Each Lambda function has an IAM role (execution role) associated with it. You specify the IAM role when you create your Lambda function. Permissions you grant to this role determine what AWS Lambda can do when it assumes the role.

    To read and write an S3 bucket from the lambda, you will need to attach an IAM policy to the IAM role associated with your lambda. From AWS docs:

    You manage access in AWS by creating policies and attaching them to IAM identities (users, groups of users, or roles) or AWS resources. A policy is an object in AWS that, when associated with an identity or resource, defines their permissions. AWS evaluates these policies when a principal entity (user or role) makes a request. Permissions in the policies determine whether the request is allowed or denied. Most policies are stored in AWS as JSON documents. AWS supports six types of policies: identity-based policies, resource-based policies, permissions boundaries, Organizations SCPs, ACLs, and session policies.

    Use this IAM policy to grant access to the IAM role associated with your lambda:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "AllowS3Access",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::<account>:role/service-role/LAMBDA_ROLE_NAME"
                },
                "Action": [
                    "s3:*"
                ],
                "Resource": [
                    "arn:aws:s3:::<bucket-name>",
                    "arn:aws:s3:::<bucket-name>/*"
                ]
            }
        ]
    }
    

    OBS: the <account> and <bucket-name> need to be replaced with the correct values.

    After that, the following code should work:

    import aws from 'aws-sdk'
    
    export default (event, context, callback) => {
      const s3 = new aws.S3()
    
      s3.getObject({
        Bucket: 'name-of-bucket',
        Key: 'my-key'
      }, (err, data) => {
        if (err) {
          callback(err)
          return
        }
    
        const objectData = data.Body.toString('utf-8')
        console.log(objectData)
      })
    }