通过 aws Lambda 使用 boto3 拒绝访问

Access Denied using boto3 through aws Lambda

我使用

构建的数据处理管道

S3 + SNS + Lambda

因为 S3 无法将通知发送出其存储区域,所以我利用 SNS 将 S3 通知发送到其他区域的 Lambda。

使用

编码的 lambda 函数
from __future__ import print_function
import boto3


def lambda_handler (event, context):
    input_file_bucket = event["Records"][0]["s3"]["bucket"]["name"]
    input_file_key = event["Records"][0]["s3"]["object"]["key"]

    input_file_name = input_file_bucket+"/"+input_file_key

    s3=boto3.resource("s3")
    obj = s3.Object(bucket_name=input_file_bucket, key=input_file_key)
    response = obj.get()

    return event #echo first key valuesdf

当我运行保存并测试时,出现以下错误

    {
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      20,
      "lambda_handler",
      "response = obj.get()"
    ],
    [
      "/var/runtime/boto3/resources/factory.py",
      394,
      "do_action",
      "response = action(self, *args, **kwargs)"
    ],
    [
      "/var/runtime/boto3/resources/action.py",
      77,
      "__call__",
      "response = getattr(parent.meta.client, operation_name)(**params)"
    ],
    [
      "/var/runtime/botocore/client.py",
      310,
      "_api_call",
      "return self._make_api_call(operation_name, kwargs)"
    ],
    [
      "/var/runtime/botocore/client.py",
      395,
      "_make_api_call",
      "raise ClientError(parsed_response, operation_name)"
    ]
  ],
  "errorType": "ClientError",
  "errorMessage": "An error occurred (AccessDenied) when calling the GetObject operation: Access Denied"
}

我用

配置了 lambda 角色
full S3 access

并在我的目标存储桶上设置存储桶策略

everyone can do anything(list, delete, etc.)

看来我的策略没设置好

您正在查找的特定 S3 对象的权限可能有限

  1. S3 对象级读取权限被拒绝
  2. 附加到 lambda 的角色无权访问 get/read S3 对象
  3. 如果使用 S3 存储桶策略授予访问权限,请验证是否提供读取权限

我遇到了类似的问题,我通过为我的用户附加适当的政策解决了这个问题。

IAM -> 用户 -> 用户名 -> 权限 -> 附加策略。

还要确保添加正确的访问密钥和秘密访问密钥,您可以使用 AmazonCLI 执行此操作。

添加到 Amri 的回答中,如果您的存储桶是私有的并且您有访问它的凭据,您可以使用 boto3.client:

import boto3
s3 = boto3.client('s3',aws_access_key_id='ACCESS_KEY',aws_secret_access_key='SECRET_KEY')
response = s3.get_object(Bucket='BUCKET', Key='KEY')

*对于此文件:s3://bucket/a/b/c/some.text,Bucket 为 'bucket',Key 为 'a/b/c/some.text'

---编辑---

例如,您可以轻松更改脚本以接受密钥作为环境变量,这样它们就不会被硬编码。为了简单起见,我就这样离开了

Omuthu 的回答实际上正确地指出了我的问题,但它没有提供解决方案,所以我想我会这样做。

当您在 IAM 中设置您的权限时,您可能会做出如下操作:

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

不幸的是,这是不正确的。您需要将对象权限应用于存储桶中的对象。所以它必须看起来像这样:

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

注意第二个 ARN,末尾有 /*

我遇到了类似的问题,不同之处在于存储桶是用 KMS 密钥加密的。

修复了: IAM -> 加密密钥 -> YOUR_AWS_KMS_KEY -> 到您的策略或帐户

在我的例子中 - 我是 运行 的 Lambda 有一个角色 blahblahRole 而这个 blahblahRole 没有 S3 存储桶的权限。

以下是一个简单的 JSON IAM 片段,可以添加到 IAM Role。虽然这为存储桶提供了 FullAccess,但通常应该不是问题,因为专用存储桶用于生产中的 Lambda 操作。

但是如果 FullAccess 不是任何操作抛出 AccessDenied 错误所需要的,则需要单独添加这些错误。

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