通过 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 对象的权限可能有限
- S3 对象级读取权限被拒绝
- 附加到 lambda 的角色无权访问 get/read S3 对象
- 如果使用 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/*"
}
]
}
我使用
构建的数据处理管道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 对象的权限可能有限
- S3 对象级读取权限被拒绝
- 附加到 lambda 的角色无权访问 get/read S3 对象
- 如果使用 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/*"
}
]
}