I have been spending a few hours trying to set my Google Firebase credentials without using a Json file path as recommended in setup guide and have no luck.
What I am trying to do
I store the content of the service-account Json file in AWS SSM parameter store, encrypted as SecureString
. During runtime, my app will get the Json string and decrypt it. Then, I turn it in a Python dictionary and pass it on to credentials.Certificate(service_acc_dict)
.
Problem
The above does not work. This is my code.
# `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)
Results in the following error.
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
I looked into /Users/joe/something/project/venv/lib/python3.7/site-packages/firebase_admin/credentials.py
and could see that it looks for client_email
and token_uri
, both of which can be retrieved from js_dict
as js_dict[client_email]
and js_dict[token_uri]
.
What am I missing here? Why doesn't this work?
Edit
Original Json file
This is how the original Json file looks like.
{
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 }
From the above, I put it in AWS SSM parameter store like this.
$ 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
On the app, I do get-parameter
with no decryption. And during runtime, I decrypt the base64 encoded string using AWS kms
like this.
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')