Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在Google Cloud Run中生成Blob签名的url?_Python_Google Cloud Storage_Google Cloud Run_Google Iam - Fatal编程技术网

Python 如何在Google Cloud Run中生成Blob签名的url?

Python 如何在Google Cloud Run中生成Blob签名的url?,python,google-cloud-storage,google-cloud-run,google-iam,Python,Google Cloud Storage,Google Cloud Run,Google Iam,在Google Cloud Run下,您可以选择容器正在运行的服务帐户。使用默认计算服务帐户无法生成签名url 这里列出的解决方法适用于谷歌云计算——如果您允许服务帐户的所有作用域。在云端,我似乎找不到那个样做的机会 我尝试过的事情: 为服务帐户分配了角色:roles/iam.serviceAccountTokenCreator 在虚拟机与云运行中验证了同一GCP项目中的解决方案 验证代码在容器中本地工作,服务帐户通过json文件从私钥加载。 在以下情况下失败: you need a priva

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

这里列出的解决方法适用于谷歌云计算——如果您允许服务帐户的所有作用域。在云端,我似乎找不到那个样做的机会

我尝试过的事情:

为服务帐户分配了角色:roles/iam.serviceAccountTokenCreator 在虚拟机与云运行中验证了同一GCP项目中的解决方案 验证代码在容器中本地工作,服务帐户通过json文件从私钥加载。 在以下情况下失败:

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
Github问题中提到的解决方案代码:

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? 在这一点上,我似乎必须装载我想要避免的服务帐户密钥

编辑:
为了尝试和澄清,服务帐户具有正确的权限-它在GCE中工作,并在本地使用JSON私钥。

您不能使用默认服务帐户对URL进行签名

请使用具有权限的专用服务帐户重试您的服务代码,并查看这是否可以解决您的错误

参考文献和进一步阅读:


是的,你可以,但是如果你不在乎细节的话,我不得不深入研究如何跳到最后

如果你走进去,你可以看到这个

if access_token and service_account_email:
   signature = _sign_message(string_to_sign, access_token, service_account_email)
...
如果您提供访问令牌和服务帐户电子邮件,则可以使用签名消息方法。此方法使用at

这一点很重要,因为您现在可以在没有本地私钥的情况下对blob进行签名!!所以,这就解决了问题,下面的代码可以在Cloud Run上运行,我确信它可以在Cloud函数上运行

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

如果不清楚,请告诉我,GCP中已添加了更新的方法,用于无服务器实例,如Cloud Run和App Engine

下面显示如何从存储库创建签名URL

def生成\上传\签名\ url \ v4bucket\名称、blob\名称: 生成v4签名的URL,用于使用HTTP PUT上载blob。 请注意,此方法需要服务帐户密钥文件。你不能使用 如果您使用的是来自Google Compute的应用程序默认凭据,则会出现此问题 引擎或从谷歌云SDK。 bucket\u name='您的bucket name' blob_name='您的对象名称' storage\u client=storage.client bucket=存储\客户端.bucketbucket\名称 blob=bucket.blobblob\u名称 url=blob.generate\u signed\u url 版本=v4, 此URL的有效期为15分钟 expiration=datetime.timedeltaminutes=15, 允许使用此URL放置请求。 方法=投入, 内容类型=应用程序/八位字节流, 返回url 一旦后端返回已签名的URL,就可以从前端执行curl-put请求,如下所示

curl-X PUT-H“内容类型:应用程序/八位字节流”-上载文件我的文件“我的签名url”
同一个问题?同一个问题是关于golang和python的。我已经添加了一些工作,尝试将访问令牌更改为JWT,但在Cloud Run中不起作用。它在GCE虚拟机中工作。谢谢。这不是问题所在。服务帐户具有正确的权限-我可以获得在GCE VM和docker容器中本地工作的简单代码。在Cloud Run中,您将获得一个访问令牌和json私钥。我找不到关于如何将访问令牌转换为JWT的文档。当我说默认服务帐户时,我指的是默认计算服务帐户。您应该能够使用import google.auth;凭证,project_id=google.auth.default,在云运行环境中。您的解决方案代码专门调用compute_引擎,仅凭名称可能无法在任何其他环境中工作。@glasnt,现在您可以了!!我相信这是最近的事!不幸的是,在云功能中使用默认的应用程序引擎服务帐户似乎不起作用。它引发了一个异常:AttributeError:您需要一个私钥来签署凭据。您当前使用的凭据只包含一个令牌。看见https://googleapis.dev/python/google-api-core/latest/auth.htmlsetting-up-a-service-account 有关更多详细信息,App Engine与旧版服务帐户管理系统略有不同,是的,它不兼容。事实上,您在默认凭据中没有收到服务帐户电子邮件,因此,它不起作用,或者与服务帐户密钥文件一起工作。或者,我可能不清楚,在云功能中,使用默认的应用程序引擎服务帐户时,上述功能不起作用。credentials.service\u account\u电子邮件获得了正确的电子邮件地址,但不幸的是,签名不起作用。我的错,你很清楚,我读得太快了!你的案子很奇怪!云运行和云函数共享很多公共组件,身份验证机制是相同的。它应该以完全相同的方式工作。你能分享这个版本吗
关于你的依赖关系?当然!在我的例子中,我使用的是GoogleAPIcore==1.24.1;googleauth==1.24;谷歌云核心==1.5.0;google cloud storage==1.35.0如果您使用的是来自google Compute Engine或google cloud SDK的应用程序默认凭据,则无法使用此选项。所以,同样,如果没有密钥文件,这也不起作用。
if access_token and service_account_email:
   signature = _sign_message(string_to_sign, access_token, service_account_email)
...
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