使用 ACL 'public-read' 保存到 s3 时,具有 AdministratorAccess 的 AWS Lambda 抛出 'Access Denied'

AWS Lambda with AdministratorAccess throws 'Access Denied' when saving to s3 with ACL 'public-read'

我正在关注从 S3 存储桶生成缩略图的 AWS Walkthrough on setting up AWS Lambda:当 sourcebucket 接收到一个新对象时,它会调用 lambda 来转换该对象并将其缩略图保存到 destination bucket.一切都使用默认代码片段,其中没有为对象指定 ACL,在这种情况下,S3 自动将其设置为 private。但是,当我修改代码并将对象的 ACL 设置为 'public-read' 时,Lambda 无法将对象保存到目标存储桶中并引发 'Access Denied' 错误。

s3.putObject({
    Bucket: dstBucket,
    Key: dstKey,
    Body: data,
    ContentType: 'image/jpeg',
    ACL: 'public-read',
    StorageClass: style.storageClass})

按照教程,我通过 IAM adminuser 向 lambda 添加了以下访问策略:

aws lambda add-permission \
--function-name CreateThumbnail \
--region eu-west-1 \
--statement-id some-unique-id \
--action "lambda:InvokeFunction" \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::sourcebucket \
--source-account bucket-owner-account-id \
--profile adminuser

adminuser 是 AdministratorAccess 允许对所有资源执行所有操作的组的一部分:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

所以我真的不确定为什么 Lambda 没有权限保存 'public-read' 个对象。

按照教程,Lambda 也有一个 AWSLambdaExecute 角色,授予它在存储桶上执行所有必要操作的权限:

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

虽然我可以在存储桶级别对所有资源设置 'public-read' 策略,但我想在目标存储桶中将一些对象设为私有。

看起来 AWSLambdaExecute 本教程建议附加到 Lambda 的角色策略缺少指定对象 ACL 的权限。为了解决这个问题,我附加了一个额外的内联策略,该策略也授予 lambda 执行 "s3:PutObjectAcl" 操作的权限:

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

为避免 lambda 有两种策略,您可以只指定一种自定义策略,如下所示:

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

感谢this answer