5

我找不到使用 Python3.7 在 Google App Engine 标准环境中使用签名 URL 的方法。

我在这里查看了文档: https ://cloud.google.com/storage/docs/access-control/signing-urls-manually

在 Google App Engine 应用程序中,您可以使用App Engine App Identity服务对您的字符串进行签名。

但是 App Engine App Identity 依赖于google.appengine包,这在 python 3.7 env 上不可用,如此处所述

专有的 App Engine API 在 Python 3 中不可用。本节列出了推荐的替换。

总体目标是您的应用程序应该是完全可移植的并且可以在任何标准 Python 环境中运行。您编写的是标准 Python 应用程序,而不是 App Engine Python 应用程序。作为这一转变的一部分,您不再需要为应用的核心功能使用专有的 App Engine API 和服务。目前,App Engine API 在 Python 3.7 运行时中不可用。

sdk 上的所有 api 都依赖google.appengine并在 python 3.7 env 上引发异常:在此处EnvironmentError('The App Engine APIs are not available.')引发 依赖专有 api 的异常:

try:
    from google.appengine.api import app_identity
except ImportError:
    app_identity = None

我知道我可以使用许多解决方案,ServiceAccountCredentials.from_json_keyfile_dict(service_account_dict)但我必须直接在应用程序引擎上上传带有凭据的文件,我不能这样做,因为项目凭据将在 git 或 ci 上公开。

我真的很想依赖来自应用引擎的默认凭据,例如其他 Google Cloud api storage.Client(),例如开箱即用的。

有什么建议吗?

4

2 回答 2

1

对于与 Google Cloud 的 Python 交互,请使用App Engine 标准 Python 3 运行时支持的Python 客户端。

要使用 App Engine Standard 中的 google-cloud-storage 访问 Cloud Storage:

  1. 将依赖项添加到 requirements.txt > google-cloud-storage==1.14.0
  2. 使用Storage Client librarystorage.Client()仅使用身份验证。

根据您需要实现的目标,我还建议尝试不同的可能方法:

  1. 允许匿名访问存储在存储桶中的公共数据。
  2. 对于签名的 URL API 调用,使用方法:projects.serviceAccounts.signBlob。文档包括示例:

也可以使用 appengine api 对 blob 进行签名

google.appengine.api.app_identity.sign_blob()
于 2019-03-26T12:05:33.647 回答
0

这个问题可能很老,但它是第一个在谷歌搜索上显示的问题,所以我认为它可能有助于将来寻找此问题的人在这里发布。

此处发布的答案@guillaume-blaquiere确实有效,但它需要一个未提及的额外步骤,即将IAM 中的角色添加到您的默认服务帐户,这将允许所述默认服务帐户“模拟服务帐户(创建 OAuth2 访问令牌、签名 blob 或 JWT 等)。”Service Account Token Creator

这允许默认服务帐户根据signBlob 文档对 blob 进行签名。

我在 AppEngine 上进行了尝试,一旦获得许可,它就可以完美运行。

import datetime as dt

from google import auth
from google.cloud import storage

# SCOPES = [
#     "https://www.googleapis.com/auth/devstorage.read_only",
#     "https://www.googleapis.com/auth/iam"
# ]

credentials, project = auth.default(
#     scopes=SCOPES
)
credentials.refresh(auth.transport.requests.Request())

expiration_timedelta = dt.timedelta(days=1)

storage_client = storage.Client(credentials=credentials)
bucket = storage_client.get_bucket("bucket_name")
blob = bucket.get_blob("blob_name")

signed_url = blob.generate_signed_url(
    expiration=expiration_timedelta,
    service_account_email=credentials.service_account_email,
    access_token=credentials.token,
)

我下载了 AppEngine默认服务帐户的密钥以在本地进行测试,为了使其在 AppEngine 环境之外正常工作,我必须根据设置SCOPES. 如果仅在 AppEngine 本身中运行,您可以忽略它们。

于 2021-12-15T19:38:13.893 回答