python - 来自 GAE 的 Cloud Storage API 请求 - 403 访问未配置

标签 python google-app-engine google-cloud-storage google-api-python-client

我的 GAE 应用正在尝试操作存储在 Google Cloud Storage 上的文件。

文件存储在我的应用程序的默认存储桶中。我已经设法使用 GCS Python 客户端库 ( https://developers.google.com/appengine/docs/python/googlecloudstorageclient/ ) 将文件读/写到该存储桶。

不幸的是它不支持复制。相反,我正在尝试使用 API 客户端库 ( https://google-api-client-libraries.appspot.com/documentation/storage/v1/python/latest/storage_v1.objects.html ) 和服务帐户 ( https://developers.google.com/api-client-library/python/guide/google_app_engine#ServiceAccounts ) 的 JSON API

到目前为止,我在请求云存储 url 时收到错误 403。

代码如下:

credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/devstorage.read_write')
http = credentials.authorize(httplib2.Http(memcache))
service = discovery.build('storage', 'v1', http=http, developerKey='api_key_generated_from_the_dev_console')
bucket_name = app_identity.get_default_gcs_bucket_name()

# I'm planning to batch multiple requests, although there is just one in this example
batch = BatchHttpRequest()

# process_list_response outputs the exception if any
batch.add(service.objects().list(bucket=bucket_name), callback=process_list_response) 
batch.execute(http=http)

这是日志:

URL being requested: https://www.googleapis.com/discovery/v1/apis/storage/v1/rest?userIp=x.x.x.x

Attempting refresh to obtain initial access_token

URL being requested: https://www.googleapis.com/storage/v1/b/xxx.appspot.com/o?alt=json

HttpError 403 when requesting https://www.googleapis.com/storage/v1/b/xxx-dev.appspot.com/o?alt=json returned "Access Not Configured. Please use Google Developers Console to activate the API for your project."

这是我在开发控制台中所做的:

  • Google Cloud Storage 和 Google Cloud Storage JSON API 已切换 开启。
  • 我创建了一个用于构建服务的 API key (因为我还使用 Oauth,是否有必要?)
  • 在权限下,我使用电子邮件 xxx@appspot.gserviceaccount.com 为我的应用程序添加了一个成员

我怎样才能让它工作?

最佳答案

将此作为答案发布,因为我的编辑(我们一起工作)似乎被默默地拒绝了,而且评论太有限了。这不是答案,而是在扩展问题。

带有单个 http 请求的更简单示例。似乎 JSON API 根本无法在 API 资源管理器之外工作。 XML/REST API 工作并返回存储桶中的文件列表。

credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/devstorage.read_write')
http = credentials.authorize(httplib2.Http(memcache))

bucket_name = app_identity.get_default_gcs_bucket_name()

# This works (200 with list of files in the content)
request_url = 'http://commondatastorage.googleapis.com/' + bucket_name
response, content = http.request(request_url, method="GET")

# This doesn't work (403, Access not configured)
request_url = 'https://www.googleapis.com/storage/v1/b/' + bucket_name + '/o?alt=json'
response, content = http.request(request_url, method="GET")

# This doesn't work (403, Access not configured), the key and project id header seem useless.
request_url = 'https://www.googleapis.com/storage/v1/b/' + bucket_name + '/o?alt=json&key=' + API_KEY
response, content = http.request(request_url, method="GET", headers={'x-goog-project-id': PROJECT_ID})

另外,查看AppAssertionCredentials的代码,我们可以看到:

  kwargs: optional keyword args, including:
    service_account_id: service account id of the application. If None or
      unspecified, the default service account for the app is used.

self.service_account_id = kwargs.get('service_account_id', None)

将任何内容作为 service_account_id 参数传递都会导致异常:

Traceback (most recent call last):
  File "/base/data/home/apps/.../1.37.../backup.py", line 61, in get
    response, content = http.request(request_url, method="GET")
  File "/base/data/home/apps/.../1.377.../oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/base/data/home/apps/.../1.37.../oauth2client/client.py", line 491, in new_request
    self._refresh(request_orig)
  File "/base/data/home/apps/.../1.37.../oauth2client/appengine.py", line 197, in _refresh
    raise AccessTokenRefreshError(str(e))
AccessTokenRefreshError

我已经测试过传递 app_identity.get_service_account_name() 返回的值,但这是行不通的。 (即使文档说如果未设置,它将使用 “应用程序的默认服务帐户”)。

我已经测试通过在开发者控制台中找到的服务帐户电子邮件,其格式为:3....-v0....@developer.gserviceaccount.com。相同的 token 异常。

那么,当 Cloudstorage JSON API 在我们的 api/服务下明确启用时,为什么我们会收到未配置的 403 访问?

为什么将 service_account_id 传递给 AppAssertionCredentials 失败并出现 AccessTokenRefreshError?

编辑:

解决方案很荒谬:关闭 Google Cloud Storage API,然后重新打开。

我假设该应用程序是一个“遗留”应用程序,这样做使最后一个要点 12 在这里起作用:https://developers.google.com/appengine/docs/python/googlecloudstorageclient/activate

关于python - 来自 GAE 的 Cloud Storage API 请求 - 403 访问未配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24327924/

相关文章:

python - Python 2.5 中的类装饰器?

database - 在 App Engine 数据存储中查找重复项

java - 如何在 Flink 中为 Google Cloud Storage 创建 RecoverableWriter

python - 如何将谷歌云存储中的文件打开到云函数中

amazon-s3 - 我可以在较大的文件中将 AWS S3 与 Google Speech-to-Text 结合使用吗?

python - iloc 给 'IndexError: single positional indexer is out-of-bounds'

python - GAE(python)如何需要接收邮件并在留言板上发布然后向所有用户发送邮件?

python - ReportLab 中的动态垫片

python - 条件列创建 DF Pandas

python - 具有质心约束的 k-means