【发布时间】:2018-02-15 11:31:26
【问题描述】:
我正在尝试使用 lambda & boto3 将文件从 1 个存储桶复制到同一个存储桶中的另一个前缀,但是我不断收到错误消息:
调用 CopyObject 时发生错误 (AccessDenied) 操作。
或
调用 HeadObject 操作时发生错误(403):禁止
取决于我使用的复制方法。
lambda 函数分配了一个角色,我认为它赋予了它所需的所有权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:HeadObject",
"s3:ListObjects"
],
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::bucket-name/folderA/folderB/*",
"arn:aws:s3:::bucket-name/folderC/folderD/*",
"arn:aws:s3:::bucket-name/folderE/folderF/*"
],
"Effect": "Allow"
}
]
}
lambda 函数是:
#connect to s3
s3 = boto3.resource('s3')
dirs = {
"folderA/folderB": "folderC/folderD"
}
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
etag = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['eTag'], encoding='utf-8')
bucket = event['Records'][0]['s3']['bucket']['name']
filePathName = key.split("/")
sourceDir = filePathName[0] + "/" + filePathName[1]
fileName = filePathName[2]
sourceKey = sourceDir + "/" + fileName
source = {'Bucket': bucket, 'Key': sourceKey}
destination = dirs[sourceDir] + "/" + fileName
##########
# This option comes up with the An error occurred (AccessDenied) when calling the CopyObject operation. Error
###########
s3.Object(bucket, destination).copy_from(CopySource=source)
###########
## This option comes up with the An error occurred (403) when calling the HeadObject operation: Forbidden error
###########
s3.meta.client.copy(source, bucket, destination)
编辑: 忘了说,如果我将角色更改为
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
],
"Effect": "Allow"
}
【问题讨论】:
-
一目了然。您是否临时授予 Lambda 函数 s3:* 权限 arn:aws:s3:::* 以验证它在获得完全权限时是否有效?只是为了排除一些愚蠢的事情,比如错误的存储桶名称?此外,记录各种值,如 bucket 和 source 以仔细检查它们。
-
是的,抱歉忘了提,如果我将 S3:* 提供给特定的存储桶(不是所有存储桶),它可以正常工作,但是当我按照上述方法将其锁定时,它不再有效并且抛出这些错误
-
我认为这里的挑战是您正在使用高级 SDK 调用(copy_from 和客户端副本),并且您不知道他们实际上在幕后进行了哪些 S3 API 调用(而 boto3 不知道) t 明确记录它们)。我假设您指定的操作列表不足。您或许可以从 CloudTrail 或通过阅读 boto3 代码找到完整列表。例如,也许 GetBucketLoction、PutObjectTagging 和对象 ACL 操作。您可以尝试找出哪个,或者为初学者添加 Get* 和 Put*。
-
已经试过了。给它 s3:Get* 和 s3:Put* 放在桶上,把 s3:* 放在没有运气的文件夹上
-
在引用存储桶时,您应该使用 arn:aws:s3:::bucket-name 而不是 arn:aws:s3:::bucket-name/。
标签: python amazon-web-services lambda boto3