尝试让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):
知道发生了什么事吗?我无法在其文档中找到此错误的解释。
答案 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来拥有您需要签名的内容的所有权。我认为这些是项目的全球权利,很遗憾,我无法让它与更细粒度的权限一起使用(即,某个存储桶的管理员是一个应用程序)