如何在Firebase Hosting上设置私有环境变量?

43

Divshot最近关闭了,我已经将一些应用程序切换到Firebase主机。这些应用程序中有一些连接到外部API,因此我需要一种在Firebase托管上存储私有环境变量的方法(例如S3访问的秘密密钥) - 有人有什么想法吗?这里有一篇文章 - https://www.firebase.com/blog/2015-10-29-managing-development-environments.html - 但那只适用于非私有环境变量。

谢谢!


2
Firebase Hosting旨在用于静态资源。将其视为CDN而不是私有SSH shell。因此,它不是尝试存储安全环境变量的好地方。也许您应该从XY问题的X部分开始? - Kato
Aerobatic提供https://www.aerobatic.com/docs/configuration#environment-variables。 - motleydev
正如其他评论所暗示的那样,更好的解决方案可能是让托管在 Firebase 中的前端调用一些终端节点(可能是在 AWS API Gateway 中创建的),然后返回您想要的原始数据,这样您就不必直接从生产客户端访问 S3。 - Jim
7个回答

33

Firebase Hosting无法存储私有环境变量。它仅用于静态托管。如果您想使用私有变量,您需要在服务器端执行。

如果您想以“Firebase方式”处理秘密,您可以使用Firebase Cloud Functions,在云函数中设置环境变量。以下是如何执行此操作的文档链接:https://firebase.google.com/docs/functions/config-env

如果您的Firebase主机没有添加云函数,您可以通过Firebase cli工具进行添加:

firebase init functions
npm install --save firebase-functions@latest
npm install -g firebase-tools

更多相关信息请参考此处:https://firebase.google.com/docs/hosting/functions

要在云函数中设置环境变量,您也可以通过命令行执行如下操作:

firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"

您可以像以下方式从函数中访问变量:

const functions = require('firebase-functions');
const request = require('request-promise');

exports.userCreated = functions.database.ref('/users/{id}').onWrite(event => {
  let email = event.data.child('email').val();

  return request({
    url: 'https://someservice.com/api/some/call',
    headers: {
      'X-Client-ID': functions.config().someservice.id,
      'Authorization': `Bearer ${functions.config().someservice.key}`
    },
    body: {email: email}
  });
});

1
欢迎提供解决方案的链接,但请确保您的答案即使没有链接也是有用的:在链接周围添加上下文,以便其他用户了解它的内容和原因,然后引用您链接的页面中最相关的部分,以防目标页面不可用。仅仅提供链接的答案可能会被删除。 - Zoe stands with Ukraine
8
不回答原问题。 - Simon H
2
在前端使用 firebase-functions 安全吗? - Francis Rodrigues
Firebase函数是类似于AWS Lambda的基于云的函数。它们可以从前端调用,但在“服务器端”运行。我使用引号是因为它实际上是一个无服务器函数。 - Dylan

10

如果您想使用GitHub Actions进行Firebase部署,可以在构建和部署之前创建.env变量。

只需在GitHub存储库设置中将环境变量设置为秘密,并在.github/workflows/{action}.yml中添加此步骤即可。

...
- name: Create env file
    run: |
      touch .env
      echo API_ENDPOINT=${{ secrets.API_ENDPOINT }} >> .env
      echo API_KEY=${{ secrets.API_KEY }} >> .env
      cat .env
...

在您的代码库中,只需调用process.env.API_KEY即可使用该变量!


3
请勿转载他人的答案。如果您认为这个问题是重复的,请标记它为重复。 - Vega

9
你可以尝试使用 Google 的Secret Manager API。与在 Firebase Cloud Functions 中存储环境变量相比,这种方法更加安全的原因如下:
  1. Secret Manager API 执行最小特权原则。这意味着您可以限制对密钥的访问,从而只允许授权用户查看/编辑密钥。
  2. 使用 AES-256 加密密钥。
  3. 有一个审计日志功能,可用于异常检测。
要获取更多源代码示例,可以查看 Google Cloud 的 Secret Manager NPM 包文档 here
希望这能帮到你!

我讨厌 Firebase 在环境变量的实际文档中从未提到过这一点,只在安全检查清单中提到。即使是他们编写的手册方式,也让人觉得在 ENV Vars 中设置秘密变量完全没有问题。 - Jean Costa
在使用秘密管理器之前,请确保了解定价方案。作为比较,你可以在Cloudflare的免费层中存储64个加密的秘密。 - thdoan

8

我有一个对我有效的解决方案,基于这篇文章: https://victorbruce82.medium.com/how-to-deploy-a-react-app-to-different-firebase-hosting-environments-dev-and-prod-da3f4cae9a1e

它使用env-cmd,并且你不需要云函数来获取当前 Firebase 托管站点上的正确环境变量(因为在 Firebase 上部署时,NODE_ENV总是返回production

基于使用两个单独的 Firebase 项目,一个用于生产环境,一个用于开发环境。所以在添加用于开发的第二个 Firebase 项目之后:

使用firebase use --add将 dev 项目添加到当前项目中,并使用别名dev

创建两个 .env 文件:.env.production.env.development,每个文件中都包含一个变量。

APP_ENV="production"

(在.env.development文件中将其更改为development
(您还可以将API密钥添加到这些.env文件中,请确保您在代码库中使用.gitignore来忽略它们,以免在代码库中暴露机密信息)
(现在,在您的代码中,您可以通过process.env.APP_ENV引用它)
const websiteConfig = process.env.APP_ENV=== 'production' ? {
  themeColor: '#fff'
} : {
  themeColor: '#ccc'
}

(根据您的喜好,您还可以选择在.env文件中设置APP_THEME_COLOR并直接访问)

安装env-cmd

npm i -D env-cmd

现在在您的package.json中添加2个脚本:

"build:dev":"env-cmd -f .env.development npm run build && firebase deploy -P dev",
"build:prod":"env-cmd -f .env.production npm run build && firebase deploy -P prod"

现在您可以将代码部署到两个不同的环境/域名/主机上,同时还可以使用不同的环境变量。

(注意:在您的 .env 文件中使用 NODE_ENV 是无效的,在 firebase hosting 上部署时它总是返回 production


好的,谢谢! - Vahe
不需要使用 env-cmd。Firebase会自动读取 .env.<alias> 文件,所以你可以将你的配置文件命名为 .env.dev.env.prod,然后就可以开始使用了。更多信息 - thdoan
@thdoan дҪҶжҳҜbuildе‘Ҫд»ӨеңЁиҝҗиЎҢж—¶дёҚзҹҘйҒ“иҰҒдҪҝз”Ёе“ӘдёӘзҺҜеўғж–Ү件пјҢжҲ–иҖ…е®ғжҳҜеҗҰд»ҺдҪ иҰҒиҝҗиЎҢзҡ„build:xе‘Ҫд»ӨдёӯиҜ»еҸ–пјҹ - TrySpace
@TrySpace,如果你使用 firebase use dev,那么部署的函数将自动从 .env.dev 中读取环境变量。这在我提供的链接页面中有进一步的文档说明。 - thdoan
好的,但这取决于你使用的构建脚本是否会获取 Firebase 的任何“use”。因此需要使用 env-cmd 来将正确的环境传递给构建命令。 - TrySpace
@TrySpace 我使用 rollup,并在 npm run 脚本中设置了不同的构建命令,例如:"build": "rollup -c", "build-dev": "rollup -c rollup-dev.config.js", "deploy": "firebase use prod && npm run build && firebase deploy", "deploy-dev": "firebase use dev && npm run build-dev && firebase deploy" - thdoan

2
从2023年开始,对于大多数API访问密钥,您应该使用secrets而不是config
firebase functions:secrets:set YOUR_ENV_VARIABLE_NAME

将您的秘密复制并粘贴到控制台中。

然后在您的函数中,您可以通过以下方式访问它

exports["myfunc"] = runWith({secrets: ["YOUR_ENV_VARIABLE_NAME"]}).https.onCall(() => {
  process.env.YOUR_ENV_VARIABLE_NAME
})

如需更多信息,请查看Firebase官方文档


1
要将.env或环境值添加到Firebase托管中,请按照以下步骤操作:
  1. 转到Google Cloud帐户https://cloud.google.com/
  2. 选择与您在Firebase中托管的项目相同的项目。
  3. 进入服务cloud function
  4. 找到您的服务,单击edit,然后可以添加env变量、构建变量。
  5. (可选) 您可以查看构建文件,您可以添加/编辑.env文件

enter image description here


0
为了让React通过process.env访问这些环境变量,请使用REACT_APP_作为环境变量名称的前缀。

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