如何使用凭据初始化Google Cloud Storage

4
我能从文件中执行以下操作:
from google.cloud import storage
self.client = storage.Client.from_service_account_json('/Users/david/file-163219.json')

然而,如果我直接传递凭据,就会出现错误:
credentials_dict = {
      "type": "service_account",
      "project_id": "asdf-163219",
      "private_key_id": "asdf2938492837498234",
}
credentials = service_account.Credentials.from_service_account_info(credentials_dict)
self.client = storage.Client(credentials=credentials)

但是我遇到了一个错误:

google.auth.exceptions.DefaultCredentialsError: 无法自动确定凭据。请设置GOOGLE_APPLICATION_CREDENTIALS或显式创建凭据并重新运行应用程序。有关更多信息,请参见https://developers.google.com/accounts/docs/application-default-credentials

传递凭据字典的正确方法是什么?


你有跟进这个链接吗? - Klaus D.
@KlausD。是的-它提供了两个选项(我都成功地完成了),即导出变量并从凭据文件路径加载它,但我想直接从Python / JSON字典中进行操作。 - user10332687
4个回答

13

在明确设置客户端凭据时,创建存储客户端时需要传递项目名称,以便客户端代表该项目进行操作。如果未传递,则会回退到从环境推断出的默认值。

from google.cloud import storage
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_info(credentials_dict)
client = storage.Client(project='project_id', credentials=credentials)

看起来您可以为project指定None。即,storage.Client(project=None, credentials=credentials)。根据文档,仅在创建主题(用于通知)时才使用project - satwell

5

由于方法from_service_account_file需要路径,因此您可以使用临时文件。例如:

#!/usr/bin/env python
from google.cloud import storage
from google.oauth2 import service_account
import json
import os
import tempfile
if __name__ == '__main__':
    jsonfile = u"""<HERE GOES THE CONTENT OF YOUR KEY JSON FILE.
    CONSIDER THAT THERE ARE BACKSLASHES WITHIN THE PRIVATE KEY
    THEREFORE USE AN EXTRA BACKSLASH. FOR INSTANCE: 
    -----BEGIN PRIVATE KEY-----\\nSomeRandomText
    INSTEAD OF: 
    -----BEGIN PRIVATE KEY-----\nSomeRandomText"""
    fd, path = tempfile.mkstemp()
    try:
        with os.fdopen(fd, 'w') as tmp:
            tmp.write(jsonfile)
        credentials = service_account.Credentials.from_service_account_file(path)
        storage_client = storage.Client(credentials=credentials)
        bucket = storage_client.get_bucket("your-bucket")
        blobs = bucket.list_blobs()
        for blob in blobs:
            print(blob.name)
    finally:
        os.remove(path)

希望对你有所帮助。

2
好的,我明白了。我的问题是如何不从文件中读取,而是直接从字典中读取。 - user10332687
请查看此评论以获取另一个答案 - https://dev59.com/oFcO5IYBdhLWcg3woC9T#56107690 - rishi jain

0
尝试了很长时间使用一个.env文件来安全地存储我的GoogleCloud凭据,最终我明白了为什么它不起作用。在任何其他讨论中都没有找到解决方案,这就是我在这里分享的原因。
为了提供一些背景,我正在尝试将图像上传到GoogleCloud存储桶。在我的代码的初始版本中,我直接使用了一个.json文件。然而,由于不安全,我想将我的凭据存储在一个.env文件中。乍一看,这似乎非常简单,我只需要使用load_dotenv函数来检索我的秘密文件中的信息,然后可以使用这些值创建一个字典:
credentials_dict = {
        'type': 'service_account',
        "project_id": os.getenv('PROJECT_ID'),
        "private_key_id": os.getenv('PRIVATE_KEY_ID'),
        "private_key": os.getenv('PRIVATE_KEY'),
        "client_email": os.getenv('CLIENT_EMAIL'),
        "client_id": os.getenv('CLIENT_ID'),
        "auth_uri": os.getenv('AUTH_URI'),
        "token_uri": os.getenv('TOKEN_URI'),
        "auth_provider_x509_cert_url": os.getenv('AUTH_PROVIDER'),
        "client_x509_cert_url": os.getenv('CLIENT'),
        "universe_domain": os.getenv('UNIVERSE_DOMAIN')
    }

最后,为了使用我的凭据,函数service_account.Credentials.from_service_account_info(credentials_dict)应该是我所需要的一切。然而,我却收到了错误信息:
 raise ValueError(
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [<OpenSSLError(code=503841036, lib=60, reason=524556, reason_text=unsupported)>])

作为一个非专家,我试图在stackoverflow上找到解决方案,但是我什么也没找到。

最终我意识到问题出在我的.env文件的格式上。对于一些参数,比如project_idprivate_key_id(除了private_key之外的所有参数),我们不应该使用任何引号,既不是'也不是"。但是对于私钥,我们应该使用一些"。为了让你对我的.env文档是什么样子有个概念,这里有一段代码片段。

#.env
PROJECT_ID=this-is-my-project
PRIVATE_KEY_ID=44ddd555.....55111111vvddaa
PRIVATE_KEY="-----BEGIN PRIVATE KEY---the_actual_key....."
CLIENT_EMAIL=your_email@blabla.com
CLIENT_ID=123...45678
AUTH_URI=https://accounts.google.com/o/oauth2/auth
TOKEN_URI=https://oauth2.googleapis.com/token
AUTH_PROVIDER=https://www.googleapis.com/oauth2/v1/certs
CLIENT=https://www.googleapis.com/gserviceaccount.com
UNIVERSE_DOMAIN=googleapis.com

希望这能对一些读者有所帮助!

0
在弗雷德的答案之上,我意识到os.getenv会自动转义反斜杠。例如,在PRIVATE_KEY中的\n会变成\\n,因此会导致错误。
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [<OpenSSLError(code=503841036, lib=60, reason=524556, reason_text=unsupported)>])

一种解决方案是像Fred建议的那样,使用双引号来表示环境变量PRIVATE_KEY,如果无法编辑环境变量,我们也可以使用os.getenv('PRIVATE_KEY').replace(r'\n', '\n')来绕过这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接