【问题标题】:boto3 s3 copyObject errorboto3 s3 copyObject错误
【发布时间】: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


【解决方案1】:

我遇到了类似的问题。解决方案:CopySource=source 中的 source 必须是从存储桶根到实际文件的完整路径,而不是存储桶名称和密钥的字典。所以我认为你的代码可能必须是:

s3.Object(bucket, destination).copy_from(CopySource=bucket + sourceDir)

【讨论】:

  • 你能告诉我这是如何工作的吗?我没有看到您在任何地方指定目标凭据和源凭据。
  • 这是对 OP 代码的修改。所以你可以在原始帖子中看到这些变量的定义。
  • bucket name 和 key 的字典实际上是推荐的指定 CopySource 的方式。参考:boto3.amazonaws.com/v1/documentation/api/latest/reference/…
猜你喜欢
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 2017-02-11
  • 2016-12-24
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多