Sign Google Cloud Storage URLs with Google Compute Engine default service account

不羁的心 提交于 2021-01-29 10:32:18

问题


I'm trying to sign GCS URLs with the GCE default service account. I gave the compute default service account the necessary "Service Account Token Creator" role. When I try to sign a url in the following Python code, I get an error:

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')

Error:

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'

Is using the GCE default SA not allowed? Are there other default SAs that aren't allowed (specifically the Google App Engine Flexible SA)?


回答1:


You need two roles. One of which you cannot grant in the Google Cloud Console to your default GCE service account. Make note of your service account email address that you want to use.

[UPDATE 01/19/2019]

When you create credentials, they are not initialized until required (e.g. no access token is requested). To preinitialize the credentials:

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

[END UPDATE]

Grant your service account the role 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

Now this service account can sign data using the private key.

Now grant this service account the role 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

Now this service account can use this service account to create tokens. In the command you are giving the first service_account_email the priviledge to use the second service_account_email. Think of this as delegation. Notice that one role is at the project level and the other role is assigned to the service account itself.

In my code, I actually create a new service account and use that service account's email address for signing. I grant permissions to the new service account (with the first command) and I grant permission to use the new service account with my credentials (the second command).



来源:https://stackoverflow.com/questions/54271402/sign-google-cloud-storage-urls-with-google-compute-engine-default-service-accoun

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!