通过从 google 函数模拟服务帐户来创建签名 url

Creating signed url by impersonating service account from google function

我可以通过 运行 这些命令从我的 gcloud 实例成功创建签名 url :

gcloud iam service-accounts add-iam-policy-binding \
   service-account-name@project-id.iam.gserviceaccount.com \
 --member="serviceAccount:instance-name@project-name.iam.gserviceaccount.com" \
 --role="roles/iam.serviceAccountTokenCreator"

gsutil -i service-account-name@project-name.iam.gserviceaccount.com signurl -d 40m -r region --use-service-account gs://project-name/file-name

现在我想在我的 google 函数中做同样的事情,我不应该像 gcloud 文档中建议的那样存储私钥和创建签名 url。

我尝试使用此方法:gsalrashid123/gcs_signedurl 但我 运行 遇到了一些错误。

代码:

import subprocess
import shlex
import google.auth
from google.auth import impersonated_credentials
from google.auth import compute_engine
from datetime import datetime, timedelta
from google.cloud import storage
def hello_world(request):
  bucket_name = ""
  sa_email =  ""
  credentials, project = google.auth.default()
  print("credentials : {}\nproject : {}".format(credentials, project))
  storage_client = storage.Client()
  data_bucket = storage_client.bucket(bucket_name)
  blob = data_bucket.get_blob("audio.wav")
  expires_at_ms = datetime.now() + timedelta(minutes=30)
  signing_credentials = impersonated_credentials.Credentials(
    source_credentials=credentials,
    target_principal=sa_email,
    target_scopes = 'https://www.googleapis.com/auth/devstorage.read',
    lifetime=2)
  signed_url = blob.generate_signed_url(expires_at_ms, credentials=signing_credentials)
  return signed_url, 200, {'Content-Type': 'text/plain'}

错误:

Traceback (most recent call last): File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 2073, in wsgi_app response = self.full_dispatch_request() File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1518, in full_dispatch_request rv = self.handle_user_exception(e) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1516, in full_dispatch_request rv = self.dispatch_request() File "/layers/google.python.pip/pip/lib/python3.9/site-packages/flask/app.py", line 1502, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/functions_framework/__init__.py", line 99, in view_func return function(request._get_current_object()) File "/workspace/main.py", line 25, in hello_world signed_url = blob.generate_signed_url(expires_at_ms, credentials=signing_credentials) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/cloud/storage/blob.py", line 620, in generate_signed_url return helper( File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/cloud/storage/_signing.py", line 396, in generate_signed_url_v2 signed_query_params = get_signed_query_params_v2( File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/cloud/storage/_signing.py", line 81, in get_signed_query_params_v2 signature_bytes = credentials.sign_bytes(string_to_sign.encode("ascii")) File "/layers/google.python.pip/pip/lib/python3.9/site-packages/google/auth/impersonated_credentials.py", line 296, in sign_bytes raise exceptions.TransportError( google.auth.exceptions.TransportError: Error calling sign_bytes: {'error': {'code': 400, 'message': 'Request contains an invalid argument.', 'status': 'INVALID_ARGUMENT'}}

我猜我必须在第一个命令中添加与我的 gfunc 相关的内容作为 --member,因为现在我只有实例作为成员。但我不知道我该怎么做。我还使用了 --impersonate-service-account 选项和 gcloud deploy 命令,但它没有用。

将 John Hanley 的评论和 Tony Stark 的评论发布为社区维基以提高可见度。

错误发生是因为 OP 使用的 --impersonate-service-account 只有范围 devstorage.read,不足以签署数据。

John Hanley 的 following article 帮助排除故障并解决了问题。