Google云端存储500内部服务器错误' Google :: Cloud :: Storage :: SignedUrlUnavailable'

时间:2018-05-27 05:06:56

标签: google-cloud-storage

尝试让Google云端存储在我的应用上运行。我成功将图像保存到存储桶,但在尝试检索图像时,我收到此错误:

GCS Storage (615.3ms) Generated URL for file at key: 9A95rZATRKNpGbMNDbu7RqJx ()
Completed 500 Internal Server Error in 618ms (ActiveRecord: 0.2ms)

Google::Cloud::Storage::SignedUrlUnavailable (Google::Cloud::Storage::SignedUrlUnavailable):

知道发生了什么事吗?我无法在其文档中找到此错误的解释。

3 个答案:

答案 0 :(得分:3)

在这里提供一些解释...

Google App Engine(以及Google Compute Engine,Kubernetes Engine和Cloud Run)提供与正在运行的VM或实例相关联的“环境”凭据,但仅以OAuth令牌的形式提供。对于大多数API调用而言,这是足够且方便的。

但是,例外情况很少,Google Cloud Storage就是其中之一。最近的存储客户端(包括google-cloud-storage gem)可能需要完整的服务帐户密钥才能支持涉及signed URLs的某些呼叫。此完整密钥不是由App Engine(或其他托管环境)自动提供的。您需要自己提供一个。因此,如先前的回答所示,如果您使用的是Cloud Storage,则可能无法依赖“环境”凭据。相反,您应该create a service account,下载service account key并将其提供给您的应用程序(例如,通过ActiveStorage configs或通过设置GOOGLE_APPLICATION_CREDENTIALS环境变量)。

答案 1 :(得分:2)

我能够弄清楚这一点。我一直在关注Rail's guide on Active Storage with Google Storage Cloud,并且不清楚如何生成我的凭证文件。

google:
  service: GCS
  credentials: <%= Rails.root.join("path/to/keyfile.json") %>
  project: ""
  bucket: ""

最初,我认为由于Google's Cloud Storage authentication documentation中的这句话,我不需要密钥文件:

  

如果您在Google App Engine或Google上运行您的应用程序   计算引擎,环境已经提供了服务帐户   身份验证信息,因此无需进一步设置。

(我正在使用Google App Engine)

所以我注释掉凭证行并开始测试。奇怪的是,我能够毫无问题地写入Google云端存储。但是,在检索图像时,我会收到500服务器错误Google::Cloud::Storage::SignedUrlUnavailable

我通过generating my private key修复此问题并将其添加到我的rails应用程序。

答案 2 :(得分:0)

自2020年8月起,谷歌云存储gem版本1.27的另一个可能解决方案是documented here。我在文档中使用的Google::Auth.get_application_default返回了一个空对象,但是使用Google::Cloud::Storage::Credentials.default.client可以工作。

如果在签名时收到Google::Apis::ClientError: badRequest: Request contains an invalid argument响应,请检查签名URL中的项目名称是否带有破折号(即,路径中的projects/-/serviceAccounts显式项目名称已弃用,不再有效)并且您具有正确的“发布者”字符串,因为服务帐户的完整电子邮件地址标识符(不仅仅是服务帐户名)。

如果您获得Google::Apis::ClientError: forbidden: The caller does not have permission,请验证您的服务帐户具有的角色:

gcloud projects get-iam-policy <project-name>
  --filter="bindings.members:<sa_name>"
  --flatten="bindings[].members" --format='table(bindings.role)'

=> ROLE
     roles/iam.serviceAccountTokenCreator
     roles/storage.admin

serviceAccountTokenCreator是调用signBlob服务所必需的,并且您需要storage.admin来拥有您需要签名的内容的所有权。我认为这些是项目的全球权利,很遗憾,我无法让它与更细粒度的权限一起使用(即,某个存储桶的管理员是一个应用程序)