【问题标题】:Sign Google Cloud Storage URLs with Google Compute Engine default service account使用 Google Compute Engine 默认服务帐号签署 Google Cloud Storage URL
【发布时间】:2019-01-19 21:08:13
【问题描述】:

我正在尝试使用 GCE 默认服务帐户签署 GCS URL。我为计算默认服务帐户提供了必要的“服务帐户令牌创建者”角色。当我尝试在以下 Python 代码中签署 url 时,出现错误:

import google.auth
import google.auth.iam
from google.auth.transport.requests import Request as gRequest

creds, _ = google.auth.default(request=gRequest(), scopes=[
    'https://www.googleapis.com/auth/cloud-platform',
    'https://www.googleapis.com/auth/devstorage.read_write',
    'https://www.googleapis.com/auth/logging.write',
    'https://www.googleapis.com/auth/firebase',
    'https://www.googleapis.com/auth/compute.readonly',
    'https://www.googleapis.com/auth/userinfo.email',
])
## creds is a google.auth.compute_engine.credentials.Credentials
## creds.service_account_email is '<project-id>-compute@developer.gserviceaccount.com'
signer = google.auth.iam.Signer(
    gRequest(), credentials=creds,
    service_account_email=creds.service_account_email)

signer.sign('stuff')

错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  <TRUNCATED - my code>
  File "/usr/local/lib/python3.6/dist-packages/google/auth/iam.py", line 101, in sign
    response = self._make_signing_request(message)
  File "/usr/local/lib/python3.6/dist-packages/google/auth/iam.py", line 85, in _make_signing_request
    response.data))
google.auth.exceptions.TransportError: Error calling the IAM signBytes API: b'{\n  "error": {\n    "code": 400,\
n    "message": "Invalid service account email (default).",\n    "status": "INVALID_ARGUMENT"\n  }\n}\n'

是否不允许使用 GCE 默认 SA?是否存在其他不允许的默认 SA(特别是 Google App Engine 灵活 SA)?

【问题讨论】:

    标签: python google-cloud-storage google-compute-engine google-iam


    【解决方案1】:

    你需要两个角色。您无法在 Google Cloud Console 中将其中一项授予您的默认 GCE 服务帐户。记下您要使用的服务帐户电子邮件地址。

    [2019 年 1 月 19 日更新]

    当您创建凭据时,它们在需要之前不会被初始化(例如,不请求访问令牌)。预初始化凭据:

    auth_url = "https://www.googleapis.com/oauth2/v4/token"
    headers = {}
    request = google.auth.transport.requests.Request()
    creds.before_request(request, "POST", auth_url, headers)
    

    [结束更新]

    授予您的服务帐户roles/iam.serviceAccounts.signBlob角色

    gcloud projects add-iam-policy-binding <project-id> --member=serviceAccount:<project-id>-compute@developer.gserviceaccount.com --role=roles/iam.serviceAccounts.signBlob
    

    现在此服务帐户可以使用私钥对数据进行签名。

    现在授予此服务帐户roles/iam.serviceAccountTokenCreator角色

    gcloud iam service-accounts add-iam-policy-binding <project-id>-compute@developer.gserviceaccount.com --member=<project-id>-compute@developer.gserviceaccount.com --role=roles/iam.serviceAccountTokenCreator
    

    现在此服务帐户可以使用此服务帐户创建令牌。在命令中,您授予第一个 service_account_email 使用第二个 service_account_email 的权限。将此视为委托。请注意,一个角色位于项目级别,而另一个角色分配给服务帐户本身。

    在我的代码中,我实际上创建了一个新的服务帐户并使用该服务帐户的电子邮件地址进行签名。我授予新服务帐户的权限(使用第一个命令),并授予使用我的凭据(第二个命令)使用新服务帐户的权限。

    【讨论】:

    • 我为计算默认服务帐户赋予了必要的“服务帐户令牌创建者”角色。我认为这实际上可能是由于在它有机会从元数据服务器获取服务帐户信息之前尝试使用凭据对象。原来creds.service_account_email 返回'default',直到它获取该信息。
    • @ScottCrunkleton - 我不确定你想告诉我什么。
    • 我更新了我的答案,解决了您的服务帐户电子邮件地址问题。
    猜你喜欢
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 2016-12-05
    • 2018-07-31
    • 2014-07-10
    • 2016-06-01
    • 2014-03-22
    • 2015-10-29
    相关资源
    最近更新 更多