Firebase 凭据作为 Python 环境变量:无法反序列化关键数据

问题描述 投票:0回答:3

我正在使用

firebase_admin
库开发一个带有 Firestore 实时数据库的 Python Web 应用程序。 Firestore 密钥采用包含 10 个变量的 .json 文件形式。但是,我想将其中一些变量存储为环境变量,这样它们就不会公开可见。因此,我不使用 Firebase SDK .json 文件,而是使用该文件的元素创建自己的字典。字典看起来像这样,所有内容都是直接从 .json 文件复制的:

my_credentials = {
    "type": "service_account",
    "project_id": "bookclub-b2db5",
    "private_key_id": os.environ.get("PRIVATE_KEY_ID"),
    "private_key": os.environ.get("PRIVATE_KEY"),
    "client_email": os.environ.get("CLIENT_EMAIL"),
    "client_id": os.environ.get("CLIENT_ID"),
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": os.environ.get("AUTH_PROVIDER_X509_CERT_URL"),
    "client_x509_cert_url": os.environ.get("AUTH_PROVIDER_X509_CERT_URL")
}

我已将私钥设置为

PRIVATE_KEY
环境变量。 私钥大概是这样的(这里的字符是组成的):

"-----BEGIN PRIVATE KEY-----\nEW8nYP9T840Sb8tQMi\nhZ(...MORE CHARACTERS HERE...)EW8nYP9T840Sb8tQMi/EW8nYP9T840Sb8tQMi\EW8nYP9T840Sb8tQMi/EW8nYP9T840Sb8tQMi=\n-----END PRIVATE KEY-----\n"

然后,我尝试根据这些凭据创建 Firebase 证书并初始化应用程序

cred = firebase_admin.credentials.Certificate(my_credentials)

firebase_admin.initialize_app(cred, {'databaseURL': 'https://myapp.firebasedatabase.app/'})

然而,事实证明 PRIVATE_KEY 环境变量不可读(无法反序列化),并且抛出错误:

Traceback (most recent call last):
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\firebase_admin\credentials.py", line 96, in __init__
    self._g_credential = service_account.Credentials.from_service_account_info(
  File "C:\Users\jarem\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\service_account.py", line 221, in from_service_account_info
    signer = _service_account_info.from_dict(
  File "C:\Users\jarem\AppData\Local\Programs\Python\Python39\lib\site-packages\google\auth\_service_account_info.py", line 58, in from_dict
    signer = crypt.RSASigner.from_service_account_info(data)
  File "C:\Users\jarem\AppData\Local\Programs\Python\Python39\lib\site-packages\google\auth\crypt\base.py", line 113, in from_service_account_info
    return cls.from_string(
  File "C:\Users\jarem\AppData\Local\Programs\Python\Python39\lib\site-packages\google\auth\crypt\_cryptography_rsa.py", line 133, in from_string
    private_key = serialization.load_pem_private_key(
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\cryptography\hazmat\primitives\serialization\base.py", line 22, in load_pem_private_key
    return ossl.load_pem_private_key(data, password)
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 921, in load_pem_private_key
    return self._load_key(
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1189, in _load_key
    self._handle_key_loading_error()
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 1248, in _handle_key_loading_error
    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).', [_OpenSSLErrorWithText(code=503841036, lib=60, reason=524556, reason_text=b'error:1E08010C:DECODER routines::unsupported')])

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\main.py", line 71, in <module>
    cred = credentials.Certificate(my_credentials)
  File "C:\Users\jarem\Desktop\data_science\python-working-directory\_MyApps\BookClub2.0\venv\lib\site-packages\firebase_admin\credentials.py", line 99, in __init__
    raise ValueError('Failed to initialize a certificate credential. '
ValueError: Failed to initialize a certificate credential. Caused by: "('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).', [_OpenSSLErrorWithText(code=503841036, lib=60, reason=524556, reason_text=b'error:1E08010C:DECODER routines::unsupported')])"

所有其他环境变量似乎都是可读的。它可能与环境变量的格式有关,但我不知道到底是什么。什么都不起作用,我不知道这个错误的原因。我使用 Windows 11 并使用

cryptography
版本 35.0.0。

如何修复此问题以提取私钥?

更新: 我发现当我直接打印私钥时,它会打印新行,例如:

-----BEGIN PRIVATE KEY-----
ZGVNvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDtuzZSrBuf4Lv3
DJTPJDj34jfknDJOJjfpitjrpZGVNvgIBADANBgkqhkiG9w0BAQZGVNvgI+DIome
ZGVNvgIBADANBgkqhkiG9w0BAQVdFkqJd5j53tZFgX5VLOf7g23/Zvgq+BFIHe34
(...MORE LINES HERE...)
-----END PRIVATE KEY-----

但是,当我打印

os.environ.get('PRIVATE KEY')
获得的私钥时,没有出现换行符:

-----BEGIN PRIVATE KEY-----ZGVNvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDtuzZSrBuf4Lv3\nDJTPJDj34jfknDJOJjfpitjrpZGVNvgIBADANBgkqhkiG9w0BAQZGVNvgI+DIome\nZGVNvgIBADANBgkqhkiG9w0BAQVdFkqJd5j53tZFgX5VLOf7g23/Zvgq+BFIHe34\n(...MORE CHARACTERS HERE...)-----END PRIVATE KEY-----

阅读“似乎有问题” “通过环境变量系统。但是,我仍然不知道如何克服这个错误。

python firebase oauth firebase-admin python-cryptography
3个回答
11
投票

我已经解决了问题:

解决问题“ “我必须更换原始字符串” “ 和 ” ",因为(大概)环境变量返回一个原始字符串,它将反斜杠 () 视为文字字符。解决方案如下所示:

my_credentials = {
    "type": "service_account",
    "project_id": "bookclub-b2db5",
    "private_key_id": os.environ.get("PRIVATE_KEY_ID"),
    "private_key": os.environ.get("PRIVATE_KEY").replace(r'\n', '\n'),  # CHANGE HERE
    "client_email": os.environ.get("CLIENT_EMAIL"),
    "client_id": os.environ.get("CLIENT_ID"),
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": os.environ.get("AUTH_PROVIDER_X509_CERT_URL"),
    "client_x509_cert_url": os.environ.get("AUTH_PROVIDER_X509_CERT_URL")
}

现在,一切正常。


0
投票

这可以简化为包含 JSON 文件内容的单个环境变量:

input_data = json.loads(os.environ.get("GCP_CREDENTIAL")
certificate = firebase_admin.credentials.Certificate(input_data)
firebase_admin.initialize_app(certificate)

0
投票

我做了以下事情:

  1. 将 .json 内容复制到剪贴板
  2. 在 python 控制台中,运行:
    import json

    my_dict = (paste clipboard)
    json_string = json.dumps(my_dict)
    print(json_string)
  1. 将 json 字符串复制到 .env 文件或 Github Secret 中。
  2. 将此代码添加到设置文件中:
    raw_creds = json.loads(os.environ.get('FIREBASE_CREDENTIALS'))
    raw_creds['private_key'] = raw_creds['private_key'].replace('\\n', '\n')
    cred = credentials.Certificate(raw_creds)
    FIREBASE_APP = initialize_app(cred)

对我来说效果很好。

© www.soinside.com 2019 - 2024. All rights reserved.