使用 Lambda 函数将文件上传到另一个 AWS 账户中的 Amazon S3 存储桶时,为什么会出现“拒绝访问”错误?

上次更新时间:2022 年 3 月 28 日

当我使用 AWS Lambda 函数将文件上传到 Amazon Simple Storage Service (Amazon S3) 存储桶时,出现“拒绝访问”错误。Amazon S3 存储桶位于另一个 AWS 账户中。我该如何排查此问题?

简短描述

如果 Lambda 函数和 Amazon S3 存储桶之间的权限不完整或不正确,则 Lambda 会返回拒绝访问错误。

若要在一个账户(账户 1)中的 Lambda 函数和另一个账户(账户 2)中的 S3 存储桶之间设置正确的权限,请执行以下操作:

1.    (在账户 1 中)创建 Lambda 执行角色,该角色允许 Lambda 函数将对象上传到 Amazon S3。

2.    (在账户 2 中)修改 S3 存储桶的存储桶策略,以允许 Lambda 函数将对象上传到存储桶。

解决方法

重要提示:以下解决方案要求一个 AWS 账户中有 Lambda 函数,另一个账户中有 S3 存储桶

用于将文件上传到 S3 存储桶的 Lambda 函数的示例代码(Python 版本 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")

(在账户 1 中)创建 Lambda 执行角色,该角色允许 Lambda 函数将对象上传到 Amazon S3

1.    为 Lambda 函数创建 AWS Identity and Access Management (IAM) 角色

2.    复制 IAM 角色的 Amazon Resource Name (ARN)

注意:您必须先获取 IAM 角色的 ARN,然后才能更新 S3 存储桶的存储桶策略。获取 IAM 角色的 ARN 的一种方法是运行 AWS Command Line Interface (AWS CLI) get-role 命令。如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新版本的 AWS CLI

3.    向 IAM 角色附加策略,该策略授予将对象 (s3:PutObject) 上传到账户 2 中的存储桶的权限。

向 IAM 角色授予 s3:PutObject 和 s3:PutObjectAcl 权限的 IAM 策略示例

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

4.    将 Lambda 函数的执行角色更改为您创建的 IAM 角色。有关说明,请参阅配置 Lambda 函数选项

(在账户 2 中)修改 S3 存储桶的存储桶策略,以允许 Lambda 函数将对象上传到存储桶

更新存储桶策略,以便将 Lambda 执行角色的 ARN 指定为可访问操作 s3:PutObject主体

允许 Lambda 函数将对象上传到存储桶的 S3 存储桶策略示例

注意:以下策略还向 Lambda 函数的执行角色授予对 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"
        }
      }
    }
  ]
}

这篇文章对您有帮助吗?


您是否需要账单或技术支持?