[英]Authenticating Firebase connection in GitHub Action
I have a Python script that reads data from an Excel file and uploads each row as a separate document to a collection in Firestore.我有一个 Python 脚本,它从 Excel 文件中读取数据,并将每一行作为单独的文档上传到 Firestore 中的集合。 I want this script to run when I push a new version of the Excel file to GitHub.
当我将 Excel 文件的新版本推送到 GitHub 时,我希望此脚本运行。
I placed the necessary credentials in GitHub repo secrets and setup the following workflow to run on push to my data/
directory:我将必要的凭据放入 GitHub repo secrets 并设置以下工作流程以在推送到我的
data/
目录时运行:
name: update_firestore
on:
push:
branches:
- main
paths:
- data/**.xlsx
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repo content
uses: actions/checkout@v2 # checkout the repository content to github runner.
- name: setup python
uses: actions/setup-python@v4
with:
python-version: '3.*' # install the latest python version
- name: install python packages
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: execute python script
env:
TYPE: service_account
PROJECT_ID: ${{ secrets.PROJECT_ID }}
PRIVATE_KEY_ID: ${{ secrets.PRIVATE_KEY_ID }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
CLIENT_EMAIL: ${{ secrets.CLIENT_EMAIL }}
TOKEN_URI: ${{ secrets.TOKEN_URI }}
run: python src/update_database.py -n ideas -delete -add
I keep getting the following error:我不断收到以下错误:
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/firebase_admin/credentials.py", line 96, in __init__
self._g_credential = service_account.Credentials.from_service_account_info(
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/google/oauth2/service_account.py", line 221, in from_service_account_info
signer = _service_account_info.from_dict(
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/google/auth/_service_account_info.py", line 58, in from_dict
signer = crypt.RSASigner.from_service_account_info(data)
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/google/auth/crypt/base.py", line 113, in from_service_account_info
return cls.from_string(
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/site-packages/google/auth/crypt/_python_rsa.py", line 171, in from_string
raise ValueError("No key could be detected.")
ValueError: No key could be detected.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/runner/work/IRIS/IRIS/src/update_database.py", line 9, in <module>
import fire
File "/home/runner/work/IRIS/IRIS/src/fire/__init__.py", line 35, in <module>
cred = credentials.Certificate(create_keyfile_dict())
File "/opt/hostedtoolcache/Python/3.10.7/x64/lib/python3.10/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: "No key could be detected."
Error: Process completed with exit code 1.
I have tried a variety of approaches including what I show above, just hardcoding each of the secrets, and copying the .json
formatted credentials directly as a single secret.我尝试了多种方法,包括我上面展示的方法,只是对每个秘密进行硬编码,并将
.json
格式的凭据直接复制为一个秘密。 I know there are some issues dealing with multiline environment variables which the PRIVATE_KEY
is.我知道有一些处理
PRIVATE_KEY
的多行环境变量的问题。 I have tried:我试过了:
PRIVATE_KEY
str directly from the download firebase provides which includes \n
PRIVATE_KEY
str 粘贴,其中包括\n
-----BEGIN PRIVATE KEY-----
BunC40fL3773R5AndNumb3r5
...
rAndomLettersANDNumb3R5==
-----END PRIVATE KEY-----
I feel like the solution should be pretty straight-forward but have been struggling and my knowledge with all this is a bit limited.我觉得解决方案应该非常简单,但一直在努力,我对这一切的了解有点有限。
Thank you in advance!先感谢您!
After hours of research, I found an easy way to store the Firestore service account JSON as a Github Secret.经过几个小时的研究,我找到了一种将 Firestore 服务帐户 JSON 存储为 Github Secret 的简单方法。
Let's name the base-64 encoded JSON SERVICE_ACCOUNT_KEY
.让我们将 base-64 编码命名为 JSON
SERVICE_ACCOUNT_KEY
。 There are two ways to get this value:有两种方法可以获取这个值:
cat path-to-your-service-account.json | base64 | xargs
This will return a single line representing the encoded service account JSON. Copy this value.这将返回代表编码服务帐户 JSON 的单行。复制此值。
import json
import base64
service_key = {
"type": "service_account",
"project_id": "xxx",
"private_key_id": "xxx",
"private_key": "-----BEGIN PRIVATE KEY-----\nxxxxx\n-----END PRIVATE KEY-----\n",
"client_email": "xxxx.com",
"client_id": "xxxx",
"auth_uri": "xxxx",
"token_uri": "xxxx",
"auth_provider_x509_cert_url": "xxxx",
"client_x509_cert_url": "xxxx"
}
# convert json to a string
service_key = json.dumps(service_key)
# encode service key
SERVICE_ACCOUNT_KEY= base64.b64encode(service_key.encode('utf-8'))
print(SERVICE_ACCOUNT_KEY)
# FORMAT: b'a_long_string'
Copy only the value between the quotes .只复制引号之间的值。 (copy
a_long_string
instead of b'a_long_string'
) (复制
a_long_string
而不是b'a_long_string'
)
I am using dotenv library to read environment variables.我正在使用dotenv 库来读取环境变量。 You will have to install it first using
pip install python-dotenv
.您必须先使用
pip install python-dotenv
安装它。 Also add this dependency in your requirements.txt
for github actions.还要在您的
requirements.txt
中为 github 操作添加此依赖项。
SERVICE_ACCOUNT_KEY
which will store the base-64 value.SERVICE_ACCOUNT_KEY
,它将存储 base-64 值。 - name: execute py script
env:
SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }}
run: python src/main.py
SERVICE_ACCOUNT_KEY
together with its value to your .env
file (which should be in the root directory of your project).SERVICE_ACCOUNT_KEY
及其值添加到您的.env
文件(应该位于项目的根目录中)。 Remember to add .env
to your .gitignore
file to avoid exposing your key on Github..env
添加到您的.gitignore
文件中,以避免在 Github 上暴露您的密钥。You will now need to get the value of SERVICE_ACCOUNT_KEY
in your Python code and convert this value back to a JSON. I am using the dotenv
library to get the value of the SERVICE_ACCOUNT_KEY
.您现在需要在 Python 代码中获取
SERVICE_ACCOUNT_KEY
的值,并将该值转换回 JSON。我正在使用dotenv
库获取SERVICE_ACCOUNT_KEY
的值。
import json
import base64
import os
from dotenv import load_dotenv, find_dotenv
# get the value of `SERVICE_ACCOUNT_KEY`environment variable
load_dotenv(find_dotenv())
encoded_key = os.getenv("SERVICE_ACCOUNT_KEY")
# decode
SERVICE_ACCOUNT_JSON = json.loads(base64.b64decode(encoded_key).decode('utf-8'))
# Use `SERVICE_ACCOUNT_JSON` later to initialse firestore db:
# cred = credentials.Certificate(SERVICE_ACCOUNT_JSON)
# firebase_admin.initialize_app(cred)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.