如何在Google Cloud Run中生成Blob签名的URL? [英] How to generate a Blob signed url in Google Cloud Run?

查看:132
本文介绍了如何在Google Cloud Run中生成Blob签名的URL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Google Cloud Run下,您可以选择容器正在运行的服务帐户.使用默认的计算服务帐户无法生成签名的URL.

Under Google Cloud Run, you can select which service account your container is running. Using the default compute service account fails to generate a signed url.

如果您允许服务帐户的所有范围,则此处列出的解决方法适用于Google Cloud Compute.在Cloud Run中似乎并没有做到这一点(我找不到).

The work around listed here works on Google Cloud Compute -- if you allow all the scopes for the service account. There does not seem to be away to do that in Cloud Run (not that I can find).

https://github.com/googleapis/google-auth -library-python/issues/50

我尝试过的事情:

  1. 为服务帐户分配角色:roles/iam.serviceAccountTokenCreator
  2. 验证了虚拟机(相对于Cloud Run)中同一GCP项目中的解决方法
  3. 验证代码是否在容器中本地运行,并且服务帐户是通过私钥(通过json文件)加载的.

from google.cloud import storage
client = storage.Client()
bucket = client.get_bucket('EXAMPLE_BUCKET')
blob = bucket.get_blob('libraries/image_1.png')
expires = datetime.now() + timedelta(seconds=86400)
blob.generate_signed_url(expiration=expires)

失败:

you need a private key to sign credentials.the credentials you are currently using <class 'google.auth.compute_engine.credentials.Credentials'> just contains a token. see https://googleapis.dev/python/google-api-core/latest/auth.html#setting-up-a-service-account for more details.
/usr/local/lib/python3.8/site-packages/google/cloud/storage/_signing.py, line 51, in ensure_signed_credentials

尝试添加解决方法,

Error calling the IAM signBytes API: 
{  "error": {  "code": 400,

    "message": "Request contains an invalid argument.",
    "status": "INVALID_ARGUMENT"  }
}
Exception Location: /usr/local/lib/python3.8/site-packages/google/auth/iam.py, line 81, in _make_signing_request

Github问题中提到的解决方法代码:

Workaround code as mention in Github issue:

from google.cloud import storage
from google.auth.transport import requests
from google.auth import compute_engine
from datetime import datetime, timedelta

def get_signing_creds(credentials):
    auth_request = requests.Request()
    print(credentials.service_account_email)
    signing_credentials = compute_engine.IDTokenCredentials(auth_request, "", service_account_email=credentials.ser
vice_account_email)
    return signing_credentials


client = storage.Client()
bucket = client.get_bucket('EXAMPLE_BUCKET')
blob = bucket.get_blob('libraries/image_1.png')
expires = datetime.now() + timedelta(seconds=86400)
signing_creds = get_signing_creds(client._credentials)
url = blob.generate_signed_url(expiration=expires, credentials=signing_creds)
print(url)

如何在Google Cloud Run下生成签名的URL? 此时,看来我可能必须挂载我想要避免的服务帐户密钥.

How do I generate a signed url under Google Cloud Run? At this point, it seems like I may have to mount the service account key which I wanted to avoid.

为了弄清楚,服务帐户具有正确的权限-它可以在GCE中使用,并且可以在本地使用JSON私钥.

To try and clarify, the service account has the correct permissions - it works in GCE and locally the JSON private key.

推荐答案

是的,但是我必须深入研究以找到方法(如果您不关心细节,请跳到最后)

Yes you can, but I had to deep dive to find how (jump to the end if you don't care about the details)

如果您进入 _signing.py file,第623行,您可以看到此内容

If you go in the _signing.py file, line 623, you can see this

if access_token and service_account_email:
   signature = _sign_message(string_to_sign, access_token, service_account_email)
...

如果提供access_tokenservice_account_email,则可以使用_sign_message方法.此方法使用 IAM服务SignBlob API 这行 >

If you provide the access_token and the service_account_email, you can use the _sign_message method. This method uses the IAM service SignBlob API at this line

这很重要,因为您现在可以在本地没有私钥的情况下对Blob进行签名!这样就解决了问题,下面的代码可以在Cloud Run上运行(我确定可以在Cloud Function上运行)

It's important because you can now sign blob without having locally the private key!! So, that solves the problem, and the following code works on Cloud Run (and I'm sure on Cloud Function)

def sign_url():
    from google.cloud import storage
    from datetime import datetime, timedelta

    import google.auth
    credentials, project_id = google.auth.default()

    # Perform a refresh request to get the access token of the current credentials (Else, it's None)
    from google.auth.transport import requests
    r = requests.Request()
    credentials.refresh(r)

    client = storage.Client()
    bucket = client.get_bucket('EXAMPLE_BUCKET')
    blob = bucket.get_blob('libraries/image_1.png')
    expires = datetime.now() + timedelta(seconds=86400)

    # In case of user credential use, define manually the service account to use (for development purpose only)
    service_account_email = "YOUR DEV SERVICE ACCOUNT"
    # If you use a service account credential, you can use the embedded email
    if hasattr(credentials, "service_account_email"):
        service_account_email = credentials.service_account_email

    url = blob.generate_signed_url(expiration=expires,service_account_email=service_account_email, access_token=credentials.token)
    return url, 200

让我知道是否不清楚

这篇关于如何在Google Cloud Run中生成Blob签名的URL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆