使用ACL"public-read"保存到s3时,带有AdministratorAccess的AWS Lambda会抛出"拒绝访问"

Sbb*_*bbs 4 amazon-s3 amazon-web-services amazon-iam aws-sdk aws-lambda

我正在关注设置AWS Lambda的AWS演练,Lamb Lambda从S3存储桶生成缩略图:当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})
Run Code Online (Sandbox Code Playgroud)

在本教程之后,我通过IAM向lambda添加了以下访问策略adminuser:

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
Run Code Online (Sandbox Code Playgroud)

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

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

所以我真的不确定为什么Lambda没有权限保存"公共读取"对象.

在本教程之后,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:::*"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

虽然我可以在桶级别的所有资源上设置"公共读取"策略,但我希望在目标存储桶中保留一些私有对象.

在此输入图像描述

Sbb*_*bbs 5

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

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

要避免为lambda设置两个策略,您只需指定一个自定义策略,如下所示:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::*"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

感谢这个答案.