【问题标题】:gsutil cp succeeds but upload_from_filename() method from storage client failsgsutil cp 成功,但来自存储客户端的 upload_from_filename() 方法失败
【发布时间】:2020-11-06 19:12:31
【问题描述】:

我想在 python 中使用 google 存储客户端将文件上传到 GCS,但由于权限问题而失败,但是 gsutil cp 成功。我不明白为什么。

这是我使用gsutil 运行的:

BUCKET=abc
$ gcloud iam service-accounts keys create --iam-account $ACCOUNT key_file.json
created key [5006838b5984f1d3b4de6523239e9bbd2c7f7047] of type [json] as [key_file.json] for [serviceaccountname@myproject.iam.gserviceaccount.com]
$ gcloud auth activate-service-account --key-file key_file.json
Activated service account credentials for: [serviceaccountname@myproject.iam.gserviceaccount.com]
$ touch test.txt
$ gsutil cp test.txt gs://${BUCKET}/test.txt     
Copying file://test.txt [Content-Type=text/plain]...
/ [1 files][    0.0 B/    0.0 B]                                                
Operation completed over 1 objects.

这是我从 python 中尝试过的:

from google.cloud import storage
import os
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'key_file.json' #same file as downloaded above
storage_client = storage.Client()
bucket_name = "abc" #the bucket name
source_file_name = "test.txt"
destination_blob_name = f"{source_file_name}"
with open(source_file_name, 'w') as f:
        f.write("lorem ipsum")
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(destination_blob_name)
blob.upload_from_filename(source_file_name)

upload_from_filename() 函数失败并出现错误:

google.api_core.exceptions.Forbidden: 403 POST https://storage.googleapis.com/upload/storage/v1/b/abc/o?uploadType=multipart: ('Request failed with status code', 403, 'Expected one of', )

我很困惑。我原以为如果这可以从 gsutil 使用,它可以使用 python 存储客户端。任何建议都将受到欢迎。

【问题讨论】:

  • 这个 python 脚本最终会在 Google Cloud 之外运行吗(在本地,在其他云上)?
  • 它在谷歌云之外运行。它是在我的笔记本电脑上运行的。
  • 是的,但最后呢?它也将在您的笔记本电脑上运行?您打算在哪里部署此脚本?
  • 啊,我明白了。此脚本旨在作为 CI 管道中的测试运行。将运行测试以验证 $ACCOUNT 是否具有适当的权限来执行它需要能够执行的事情。
  • 您好,感谢您的回复。我已经解决了这个问题。请查看我发布的答案。

标签: google-cloud-storage


【解决方案1】:

我已经深入了解了这个问题。这是双重的。

  1. 我发现如果存储对象destination_blob_name 确实 已经存在,代码会成功。如果对象确实存在,则会发生上述错误。
  2. $ACCOUNT 访问存储桶的权限由应用于存储桶的自定义角色提供。当我向该自定义角色添加权限 storage.objects.getstorage.objects.delete 时,我的代码成功了,即使对象已经存在。

我发现storage.objects.get & storage.objects.delete 被描述为

  • 读取对象数据和元数据,不包括 ACL
  • 删除对象

https://cloud.google.com/storage/docs/access-control/iam-permissions#object_permissions

我从中学到的知识是,在某些情况下(例如,当目标对象已经存在时)gsutil cp 需要与google.cloud.storage.blob.upload_from_filename() 不同的权限。如果有人可以阐明这两种操作之间的区别,那么我很想更好地理解它。

【讨论】:

    【解决方案2】:

    这个错误(403)表示用户没有被谷歌云存储授权发出请求,基本上你需要记住:

    【讨论】:

      猜你喜欢
      • 2017-02-09
      • 2014-05-03
      • 2016-07-15
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 2019-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多