如何不使用 Json 文件而是使用 python dict 设置 Google Firebase 凭据?

bil*_*ydh 1 python firebase google-cloud-platform firebase-authentication

我花了几个小时试图设置我的 Google Firebase 凭据,而不使用设置指南中推荐的 Json 文件路径,但没有成功。

我想做什么

我将服务帐户 Json 文件的内容存储在 AWS SSM 参数存储中,加密为SecureString. 在运行时,我的应用程序将获取 Json 字符串并对其进行解密。然后,我将其放入 Python 字典并将其传递给credentials.Certificate(service_acc_dict).

问题

以上是行不通的。这是我的代码。

# `secret` is the Json string I get back after decrypting the google service account credentials from aws ssm

secret = '{\\n  \"type\": \"service_account\",\\n  \"project_id\": \"some-project\",\\n  \"private_key_id\": \"11z11111z1z111111b1111111z11z11z1111111z\",\\n  \"private_key\": \"-----BEGIN PRIVATE KEY-----\\\\nZZZZzZZZZZZZZzzzzzzZ1z1ZZZZZZZZZZZzzzzZzZzEAAoIBAQC7+0fFwMo6Pbz7\\\\nyk3Fxae5/Ebq56KSzezKk30+wKPymSW/uXBlIZZXlFJdKZNTFI5UdbPsKSypp+cW\\\\nNoAq06ojJ727j25ygMAOILeFJD1fb6c0TrDHsBiw0ECmPT9EOHddjHfF8Oj/gbg+\\\\n2EyRPZiT8238QfbZHnbZ35RpsnasNfk0n0qdB5///w1iFjzfZZbf+9UX6wE6ht7q\\\\nJlBOZan104saXi4UbmAmnz3fX/RVJ4ubO9XE4iDzQbljNONBNJvSbX9GuOgiTmCw\\\\nCK/x23rihABCZ6c9Q/3rkLsJEVqHYZkVHwaGcBF4V44qUrsd3GrHryCHLawhhz8l\\\\nDd3rBDIZAgMBAAECggEAFGgebgLUUUdDfUgEclxXNGAVTdMojGxLcOBa/9V01tC2\\\\nTt5oK6peQkqpOFDbm/DG1LdkXVZI8W/3P6uR9VQ+C4v0ZmiXMln0v3PgyFTbTsF1\\\\nstF6Emt0+rjY09MhS5wfpSmrFAQcd2oasMPVaAz6Q9Fw1qoojIBooZVKbMEBbgdM\\\\nUcs9tuCnYAOggNwgYoGsldAlkjrAOx1iopyHVhBo+cHbYW03Bgncvpq7fLLL056H\\\\aaaaAAAmVDoBFnvfS2SfT9DBPLeFC0JSgc6U6b1v9lzjzRWNdG6OfBFYJIwTZ8sCd\\\\n6wT7twniL0gBPN/y3TM5Skbo0c7IYo2LVyWcFy6j4wKBgQDb85FWMchXkRWLQDRJ\\\\npJm2JcFT3TATX7RMcGD4XRk/YXDD3pgwDi6zjqYcCFtYLHGTScc2wFAvkX4xUayX\\\\zz1ZZzzzZ939DQ/S2rPkJmUJpwY3hHd3mkAMV0CzzAAf1wvLeCO0g8N1AsX2YjhJb\\\\n81yLbV44EpERTOsbMkPpEXrsbwKBgQDaylzmnYCCwWKBQoTV7x07jZmIa2vCWCol\\\\nKO3zuhwk1r6HkdKtk1wN8kp8auMGf72REU4KRvsUQ6b+IzhP7kFcDYegNwv+JdB1\\\\n2FM0ZzpFmiIIHfgHGJhb2O1z58n5m01CrhpyD39y36MDTmC6zxmS1dHry0puV/fG\\\\nS8/wZTad9wKBgQCZw9U+5N6iGRNunhvvv9qVtB9Leb46TRXGummQN8WGwaALznmm\\\\nXsPXU0pdHpp9MdTUmydh52AnYRdPc0GtWzCrxvOZMGUPqVpSuun/A92iAWYmkrKm\\\\nlNcTUM2bs9HcxcTz5FmiRcDnkS20kN3U2nVAI91SZeh0p8lU4fcH4OiGkQKBgD7b\\\\nHE10ulLWVAJmpdsAUxmk2JMEqXSv94utco8uzJ8YwqwYDLqpNy0aiqOr4YUgdcmT\\\\neyQguEleFj+0xpzQCh70FB7HMb7WBkmU2HKZpXgRi+1hDrybKEpay/0cfj4ji9K4\\\\nSgiywx6xeReeENQaY3J301M2mC+TPi/N3/NkYIiJAoGAfBwdbptV/U7hXXgTnFps\\\\nZHdpAH4SddVBe2Ki6DLIiZPliXUSKcClrhy4evl2f4mA4sy7ovlBiXRA+IoNfkTT\\\\nH1Resx2kTlrkpT5+gsmDiY5HMNBHWuPjPIWNPwxzBSU3KK64TwPLFD0FBdfC6maS\\\\nVqyeIaHUW59ExHN5+FOfmWY=\\\\n-----END PRIVATE KEY-----\\\\n\",\\n  \"client_email\": \"firebase-adminsdk-zz1zz@some-project.iam.gserviceaccount.com\",\\n  \"client_id\": \"111111111111111111111\",\\n  \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\\n  \"token_uri\": \"https://oauth2.googleapis.com/token\",\\n  \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\\n  \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-zz1zz%40some-project.iam.gserviceaccount.com\"\\n}\\n'

js = secret.replace('\\n  ', '').replace('\\\\n', '').replace('\\n', '')
js_dict = json.loads(js)

cred = credentials.Certificate(js_dict)
Run Code Online (Sandbox Code Playgroud)

导致以下错误。

Traceback (most recent call last):
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/firebase_admin/credentials.py", line 97, in __init__
    json_data, scopes=_scopes)
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/google/oauth2/service_account.py", line 201, in from_service_account_info
    info, require=["client_email", "token_uri"]
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/google/auth/_service_account_info.py", line 55, in from_dict
    signer = crypt.RSASigner.from_service_account_info(data)
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/google/auth/crypt/base.py", line 114, in from_service_account_info
    info[_JSON_FILE_PRIVATE_KEY], info.get(_JSON_FILE_PRIVATE_KEY_ID)
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/google/auth/crypt/_cryptography_rsa.py", line 147, in from_string
    key, password=None, backend=_BACKEND
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 16, in load_pem_private_key
    return backend.load_pem_private_key(data, password)
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1089, in load_pem_private_key
    password,
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1315, in _load_key
    self._handle_key_loading_error()
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1373, in _handle_key_loading_error
    raise ValueError("Could not deserialize key data.")
ValueError: Could not deserialize key data.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/joe/Library/Preferences/PyCharmCE2019.2/scratches/scratch.py", line 15, in <module>
    cred = credentials.Certificate(js)
  File "/Users/joe/something/project/venv/lib/python3.7/site-packages/firebase_admin/credentials.py", line 100, in __init__
    'Caused by: "{0}"'.format(error))
ValueError: Failed to initialize a certificate credential. Caused by: "Could not deserialize key data."

Process finished with exit code 1
Run Code Online (Sandbox Code Playgroud)

我查看/Users/joe/something/project/venv/lib/python3.7/site-packages/firebase_admin/credentials.py并可以看到它寻找client_emailand token_uri,这两个都可以从js_dictas js_dict[client_email]and 中检索js_dict[token_uri]

我在这里缺少什么?为什么这不起作用?

编辑

原始 Json 文件

这就是原始 Json 文件的样子。

{
  2   "type": "service_account",
  3   "project_id": "some-project",
  4   "private_key_id": "11z11111z1z111111b1111111z11z11z1111111z",
  5   "private_key": "-----BEGIN PRIVATE KEY-----\nZZZZzZZZZZZZZzzzzzzZ1z1ZZZZZZZZZZZzzzzZzZzEAAoIBAQC7+0fFwMo6Pbz7\nyk3Fxae5/Ebq56KSzezKk30+wKPymSW/uXBlIZZXlFJdKZNTFI5UdbPsKSypp+cW\nNoAq06ojJ727j25ygMAOILeFJD1fb6c0TrDHsBiw0ECmPT9EOHddjHfF8Oj/gbg+\n2EyRPZiT8238QfbZHnbZ35RpsnasNfk0n0qdB5///w1iFjzfZZbf+9UX6wE6ht7q\nJlBOZan104saXi4UbmAmnz3fX/RVJ4ubO9XE4iDzQbljNONBNJvSbX9GuOgiTmCw\nCK/x23rihABCZ6c9Q/3rkLsJEVqHYZkVHwaGcBF4V44qUrsd3GrHryCHLawhhz8l\nDd3rBDIZAgMBAAECggEAFGgebgLUUUdDfUgEclxXNGAVTdMojGxLcOBa/9V01tC2\nTt5oK6peQkqpOFDbm/DG1LdkXVZI8W/3P6uR9VQ+C4v0ZmiXMln0v3PgyFTbTsF1\nstF6Emt0+rjY09MhS5wfpSmrFAQcd2oasMPVaAz6Q9Fw1qoojIBooZVKbMEBbgdM\nUcs9tuCnYAOggNwgYoGsldAlkjrAOx1iopyHVhBo+cHbYW03Bgncvpq7fLLL056H\naaaAAAmVDoBFnvfS2SfT9DBPLeFC0JSgc6U6b1v9lzjzRWNdG6OfBFYJIwTZ8sCd\n6wT7twniL0gBPN/y3TM5Skbo0c7IYo2LVyWcFy6j4wKBgQDb85FWMchXkRWLQDRJ\npJm2JcFT3TATX7RMcGD4XRk/YXDD3pgwDi6zjqYcCFtYLHGTScc2wFAvkX4xUayX\nz1ZZzzzZ939DQ/S2rPkJmUJpwY3hHd3mkAMV0CzzAAf1wvLeCO0g8N1AsX2YjhJb\n81yLbV44EpERTOsbMkPpEXrsbwKBgQDaylzmnYCCwWKBQoTV7x07jZmIa2vCWCol\nKO3zuhwk1r6HkdKtk1wN8kp8auMGf72REU4KRvsUQ6b+IzhP7kFcDYegNwv+JdB1\n2FM0ZzpFmiIIHfgHGJhb2O1z58n5m01CrhpyD39y36MDTmC6zxmS1dHry0puV/fG\nS8/wZTad9wKBgQCZw9U+5N6iGRNunhvvv9qVtB9Leb46TRXGummQN8WGwaALznmm\nXsPXU0pdHpp9MdTUmydh52AnYRdPc0GtWzCrxvOZMGUPqVpSuun/A92iAWYmkrKm\nlNcTUM2bs9HcxcTz5FmiRcDnkS20kN3U2nVAI91SZeh0p8lU4fcH4OiGkQKBgD7b\nHE10ulLWVAJmpdsAUxmk2JMEqXSv94utco8uzJ8YwqwYDLqpNy0aiqOr4YUgdcmT\neyQguEleFj+0xpzQCh70FB7HMb7WBkmU2HKZpXgRi+1hDrybKEpay/0cfj4ji9K4\nSgiywx6xeReeENQaY3J301M2mC+TPi/N3/NkYIiJAoGAfBwdbptV/U7hXXgTnFps\nZHdpAH4SddVBe2Ki6DLIiZPliXUSKcClrhy4evl2f4mA4sy7ovlBiXRA+IoNfkTT\nH1Resx2kTlrkpT5+gsmDiY5HMNBHWuPjPIWNPwxzBSU3KK64TwPLFD0FBdfC6maS\nVqyeIaHUW59ExHN5+FOfmWY=\n-----END PRIVATE KEY-----\n",
  6   "client_email": "firebase-adminsdk-zz1zz@some-project.iam.gserviceaccount.com",
  7   "client_id": "111111111111111111111",
  8   "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  9   "token_uri": "https://oauth2.googleapis.com/token",
 10   "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
 11   "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-zz1zz%40some-project.iam.gserviceaccount.com"
 12 }
Run Code Online (Sandbox Code Playgroud)

从上面,我把它像这样放在 AWS SSM 参数存储中。

$ aws ssm put-parameter --name "/firebase/credentials.json" --type SecureString --key-id 11111111-123a-12a1-1111-aaaa1a1a111z --description "Firebase credentials" --value file:///Users/joe/something/some-project-firebase-adminsdk-zq1xa-12g12345a3.json
Run Code Online (Sandbox Code Playgroud)

在应用程序上,我get-parameter没有解密。在运行时,我kms像这样使用 AWS 解密 base64 编码的字符串。

import json
import os
import base64
import boto3

kms = boto3.client('kms')

encryption_context = {"PARAMETER_ARN": os.environ.get('ENCRYPTION_CONTEXT')}
credentials_encrypted = os.environ.get('ENCRYPTED_CREDENTIALS')
credentials_blob = base64.b64decode(credentials_encrypted)
credentials = kms.decrypt(CiphertextBlob=credentials_blob, EncryptionContext=encryption_context)['Plaintext'].decode('utf-8')
Run Code Online (Sandbox Code Playgroud)

log*_*icy 7

在 Firebase 文档中,他们没有提到 dicts 是一个有效的 arg 到credentials.Credential

creds_dict = json.loads(decrypt(os.environ.get(
    ("FIREBASE_SERVICE_ACCOUNT_CREDENTIAL"))))

creds = credentials.Certificate(creds_dict)

firebase_admin.initialize_app(
    creds, {'databaseURL': os.environ.get(("FIREBASE_DB_URL"))})
db = firestore.client()
Run Code Online (Sandbox Code Playgroud)

所以是的,您可以使用 dict 而不是指定密钥文件的路径。请参阅源代码