【问题标题】:How to signed url for Google cloud storage on Google App Engine Standard environment with Python3.7?如何使用 Python3.7 在 Google App Engine 标准环境中为 Google 云存储签名 url?
【发布时间】:2019-08-16 04:14:35
【问题描述】:

我找不到使用 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.appenginepackage,这在 python 3.7 env 上不可用,解释为 here

专有的 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.') raise here 依赖专有 api:

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

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

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

有什么建议吗?

【问题讨论】:

    标签: python-3.x google-app-engine google-cloud-storage


    【解决方案1】:

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

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

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

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

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

    也可以sign blobs with appengine api 使用:

    google.appengine.api.app_identity.sign_blob()
    

    【讨论】:

    • storage.Client() 运行良好,我可以访问 GCS 存储桶,但我需要一个 SignedUrl。服务帐户上有一个 Credential.sign_blob() 运行良好,但我无法使用 AppEngine 找到它,或者我找不到允许我自己签名的 appengine 私钥! Oauth 密钥不是选项,因为凭据没有 sign_method ...
    • 如果你不想使用使用 .signBlob 的 google-cloud-storage 库,它会变得更复杂,please see the solution provided here
    • 这是另一个如何签名 url 的示例:github.com/GoogleCloudPlatform/storage-signedurls-python
    【解决方案2】:

    这个问题可能很老,但它是第一个在 Google 搜索中显示的问题,所以我认为它可能会帮助将来寻找此问题的人也在这里发布。

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

    这允许 默认服务帐户 根据 signBlob documentation 对 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 本身中运行,您可以忽略它们。

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 2018-03-12
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 2015-01-26
      • 2019-03-09
      相关资源
      最近更新 更多