Why do I get Access Denied errors when I use a Lambda function to upload files to an Amazon S3 bucket in another AWS account?

Last updated: 2022-03-28

I get an Access Denied error when I use an AWS Lambda function to upload files to an Amazon Simple Storage Service (Amazon S3) bucket. The Amazon S3 bucket is in another AWS account. How do I troubleshoot the issue?

Short description

If the permissions between a Lambda function and an Amazon S3 bucket are incomplete or incorrect, then Lambda returns an Access Denied error.

To set up permissions between a Lambda function in one account (account 1) and an S3 bucket in another account (account 2), do the following:

1.    (In account 1) Create a Lambda execution role that allows the Lambda function to upload objects to Amazon S3.

2.    (In account 2) Modify the S3 bucket's bucket policy to allow the Lambda function to upload objects to the bucket.

Resolution

Important: The following solution requires a Lambda function in one AWS account and an S3 bucket in another account.

Example code for a Lambda function that uploads files to an S3 bucket (Python version 3.8)

import json
import boto3

s3 = boto3.client('s3')

def lambda_handler(event,context):
    bucket = 'AccountBBucketName'
    transactionToUpload = {}
    transactionToUpload['transactionId'] = '12345'
    transactionToUpload['type'] = 'PURCHASE'
    transactionToUpload['amount'] = 20
    transactionToUpload['customerId'] = 'CID-1111'

    fileName = 'CID-1111'+'.json'
    uploadByteStream = bytes(json.dumps(transactionToUpload).encode('UTF-8'))
    s3.put_object(Bucket=bucket), Key=filename, Body=uploadByteStream, ACL='bucket-owner-full-control')
    print("Put Complete")

(In account 1) Create a Lambda execution role that allows the Lambda function to upload objects to Amazon S3

1.    Create an AWS Identity and Access Management (IAM) role for your Lambda function.

2.    Copy the IAM role's Amazon Resource Name (ARN).

Note: You must get the IAM role's ARN before you can update the S3 bucket's bucket policy. One way to get the IAM role's ARN is to run the AWS Command Line Interface (AWS CLI) get-role command. If you receive errors when running AWS CLI commands, make sure that you’re using the most recent version of the AWS CLI.

3.    Attach a policy to the IAM role that grants the permission to upload objects (s3:PutObject) to the bucket in Account 2.

Example IAM policy that grants an IAM role s3:PutObject and s3:PutObjectAcl permissions

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::AccountBBucketName/*"
    }
  ]
}

4.    Change your Lambda function's execution role to the IAM role that you created. For instructions, see Configuring Lambda function options.

(In account 2) Modify the S3 bucket's bucket policy to allow the Lambda function to upload objects to the bucket

Update the bucket policy so that it specifies the Lambda execution role's ARN as a Principal that has access to the action s3:PutObject.

Example S3 bucket policy that allows a Lambda function to upload objects to the bucket

Note: The following policy also grants the Lambda function's execution role the permission to s3:PutObjectAcl.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::AccountA:role/AccountARole"
      },
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::AccountBBucketName/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}

Did this article help?


Do you need billing or technical support?