配置您的環境

通常,您需要對函數進行額外配置,例如第三方 API 密鑰或可調設置。 Firebase SDK for Cloud Functions 提供了內置的環境配置,讓您可以輕鬆地為您的項目存儲和檢索此類數據。

您可以在基於文件的環境變量配置(推薦)或使用 Firebase CLI 和functions.config的運行時環境配置之間進行選擇。本指南中介紹了這兩種方法。

環境變量

Cloud Functions for Firebase 支持dotenv文件格式,用於將.env文件中指定的環境變量加載到您的應用運行時。部署後,可以通過process.env接口讀取環境變量。

要以這種方式配置您的環境,請在您的項目中創建一個.env文件,添加所需的變量,然後部署:

  1. 在您的functions/目錄中創建一個.env文件:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. 打開.env文件進行編輯,然後添加所需的密鑰。例如:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. 部署函數並驗證是否已加載環境變量:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

部署自定義環境變量後,您的函數代碼可以使用process.env語法訪問它們:

// Responds with "Hello Earth and Humans"
exports.hello = functions.https.onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

部署多組環境變量

如果您的 Firebase 項目需要一組替代環境變量(例如暫存與生產),請創建一個.env. <project or alias >文件並在其中寫入項目特定的環境變量。來自.env和項目特定.env文件(如果存在)的環境變量將包含在所有部署的函數中。

例如,一個項目可能包含以下三個文件,其中包含稍微不同的開發和生產值:

.env .env.dev .env.prod
PLANET=地球

觀眾=人類

觀眾=開發人類觀眾=刺激人類

給定這些單獨文件中的值,與您的函數一起部署的一組環境變量將根據您的目標項目而有所不同:

$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Dev Humans

$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Prod Humans

保留的環境變量

一些環境變量鍵保留供內部使用。不要在.env文件中使用以下任何鍵:

  • 所有以 X_GOOGLE_ 開頭的鍵
  • 所有以 EXT_ 開頭的鍵
  • 所有以 FIREBASE_ 開頭的鍵
  • 以下列表中的任何鍵:
  • CLOUD_RUNTIME_CONFIG
  • 入口點
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • FUNCTION_NAME
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCTION_IDENTITY
  • FUNCTION_REGION
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICE
  • K_REVISION
  • 港口
  • K_CONFIGURATION

存儲和訪問敏感的配置信息

存儲在.env文件中的環境變量可用於功能配置,但不應將它們視為存儲敏感信息(如數據庫憑據或 API 密鑰)的安全方式。如果您將.env文件簽入源代碼管理,這一點尤其重要。

為了幫助您存儲敏感配置信息,Cloud Functions for Firebase 與 Google Cloud Secret Manager集成。此加密服務安全地存儲配置值,同時仍允許在需要時從您的函數輕鬆訪問。

創建和使用密鑰

要創建密鑰,請使用 Firebase CLI。

要創建和使用密鑰:

  1. 從本地項目目錄的根目錄運行以下命令:

    firebase functions:secrets:set SECRET_NAME

  2. 輸入SECRET_NAME的值。

    CLI 回顯成功消息並警告您必須部署函數才能使更改生效。

  3. 在部署之前,請確保您的函數代碼允許函數使用runWith參數訪問密鑰:

    exports.processPayment = functions
      // Make the secret available to this function
      .runWith({ secrets: ["SECRET_NAME"] })
      .onCall((data, context) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      });
  4. 部署雲功能:

    firebase deploy --only functions

現在您將能夠像訪問任何其他環境變量一樣訪問它。相反,如果另一個沒有在runWith中指定秘密的函數試圖訪問秘密,它會收到一個未定義的值:

exports.anotherEndpoint = functions.https.onRequest((request, response) => {
  response.send(`The secret API key is ${process.env.SECRET_NAME}`);
  // responds with "The secret API key is undefined" because the `runWith` parameter is missing
});

部署您的函數後,它將可以訪問秘密值。只有在其runWith參數中明確包含機密的函數才能將該機密作為環境變量訪問。這有助於確保秘密值僅在需要的地方可用,從而降低意外洩露秘密的風險。

管理機密

使用 Firebase CLI 管理您的機密。以這種方式管理機密時,請記住,某些 CLI 更改需要您修改和/或重新部署相關功能。具體來說:

  • 每當您為密鑰設置新值時,您必須重新部署所有引用該密鑰的函數,以便它們獲取最新值。
  • 如果您刪除一個密鑰,請確保您部署的任何函數都沒有引用該密鑰。使用已被刪除的秘密值的函數將靜默失敗。

以下是用於秘密管理的 Firebase CLI 命令的摘要:

# Change the value of an existing secret
firebase functions:secrets:set SECRET_NAME

# View the value of a secret
functions:secrets:access SECRET_NAME

# Destroy a secret
functions:secrets:destroy SECRET_NAME

# View all secret versions and their state
functions:secrets:get SECRET_NAME

# Automatically clean up all secrets that aren't referenced by any of your functions
functions:secrets:prune

對於accessdestroy命令,您可以提供可選的 version 參數來管理特定版本。例如:

functions:secrets:access SECRET_NAME[@VERSION]

有關這些操作的更多信息,請通過-h命令查看 CLI 幫助。

秘密是如何計費的

Secret Manager 允許免費使用 6 個活動密鑰版本。這意味著您每月可以在 Firebase 項目中免費擁有 6 個機密。

默認情況下,Firebase CLI 會嘗試在適當的情況下自動銷毀未使用的密鑰版本,例如當您使用新版本的密鑰部署函數時。此外,您可以使用functions:secrets:destroyfunctions:secrets:prune主動清理未使用的秘密。

Secret Manager 允許對密鑰進行每月 10,000 次未計費的訪問操作。函數實例每次冷啟動時只讀取其runWith參數中指定的秘密。如果您有大量函數實例讀取大量機密,您的項目可能會超出此限額,此時您將被收取每 10,000 次訪問操作 0.03 美元的費用。

有關更多信息,請參閱Secret Manager 定價

模擬器支持

使用 dotenv 進行環境配置旨在與本地Cloud Functions 模擬器進行互操作。

使用本地 Cloud Functions 模擬器時,您可以通過設置.env.local文件來覆蓋項目的環境變量。 .env.local的內容優先於.env和項目特定的.env文件。

例如,一個項目可以包含以下三個文件,其中包含用於開發和本地測試的略有不同的值:

.env .env.dev .env.local
PLANET=地球

觀眾=人類

觀眾=開發人類觀眾=當地人

在本地上下文中啟動時,模擬器會加載環境變量,如下所示:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

Cloud Functions 模擬器中的密鑰和憑據

Cloud Functions 模擬器支持使用機密來存儲和訪問敏感的配置信息。默認情況下,模擬器將嘗試使用應用程序默認憑據訪問您的生產機密。在某些情況下,例如 CI 環境,模擬器可能由於權限限製而無法訪問機密值。

與 Cloud Functions 模擬器對環境變量的支持類似,您可以通過設置.secret.local文件來覆蓋機密值。這使您可以輕鬆地在本地測試您的函數,尤其是在您無權訪問秘密值的情況下。

從環境配置遷移

如果您一直在使用帶有functions.config的環境配置,則可以將現有配置遷移為環境變量(以dotenv格式)。 Firebase CLI 提供了一個導出命令,該命令將目錄的.firebaserc文件(在下面的示例中為localdevprod )中列出的每個別名或項目的配置輸出為.env文件。

要遷移,請使用firebase functions:config:export命令導出現有環境配置:

firebase functions:config:export
i  Importing configs from projects: [project-0, project-1]
⚠  The following configs keys could not be exported as environment variables:

⚠  project-0 (dev):
    1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.)

Enter a PREFIX to rename invalid environment variable keys: CONFIG\_
✔  Wrote functions/.env.prod
✔  Wrote functions/.env.dev
✔  Wrote functions/.env.local
✔  Wrote functions/.env

請注意,在某些情況下,系統會提示您輸入前綴以重命名導出的環境變量鍵。這是因為並非所有配置都可以自動轉換,因為它們可能無效或可能是保留的環境變量 key

我們建議您在部署函數或將.env文件檢入源代碼控制之前仔細檢查生成的.env文件的內容。如果任何值是敏感的並且不應洩露,請將它們從您的.env文件中刪除,並將它們安全地存儲在Secret Manager中。

您還需要更新函數代碼。任何使用functions.config的函數現在都需要使用process.env ,如環境變量所示。

環境配置

firebase-functions v3.18.0發布環境變量支持之前,推薦使用functions.config()進行環境配置。這種方法仍然受支持,但我們建議所有新項目改用環境變量,因為它們更易於使用並提高代碼的可移植性。

使用 CLI 設置環境配置

要存儲環境數據,您可以使用Firebase CLI中的firebase functions:config:set命令。可以使用句點對每個鍵進行命名空間,以將相關配置組合在一起。請記住, keys 中只接受小寫字符;不允許使用大寫字符。

例如,要存儲“某些服務”的客戶端 ID 和 API 密鑰,您可以運行:

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

檢索當前環境配置

要檢查項目環境配置中當前存儲的內容,您可以使用firebase functions:config:get 。它會輸出類似這樣的 JSON:

{
  "someservice": {
    "key":"THE API KEY",
    "id":"THE CLIENT ID"
  }
}

此功能基於Google Cloud Runtime Configuration API

使用functions.config訪問函數中的環境配置

在保留的firebase命名空間下會自動提供一些配置。通過functions.config()在運行的函數中提供環境配置。要使用上面的配置,您的代碼可能如下所示:

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}
  });
});

使用環境配置初始化模塊

一些 Node 模塊無需任何配置即可準備就緒。其他模塊需要額外的配置才能正確初始化。我們建議您將此配置存儲在環境配置變量中,而不是對其進行硬編碼。這可以幫助您使您的代碼更加可移植,從而使您可以開源您的應用程序或輕鬆地在生產版本和暫存版本之間切換。

例如,要使用Slack Node SDK模塊,您可以這樣寫:

const functions = require('firebase-functions');
const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(functions.config().slack.url);

在部署之前,設置slack.url環境配置變量:

firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX

其他環境命令

  • firebase functions:config:unset key1 key2從配置中刪除指定的鍵
  • firebase functions:config:clone --from <fromProject>將另一個項目的環境克隆到當前活動的項目中。

自動填充的環境變量

在函數運行時和本地模擬函數中會自動填充一些環境變量。其中包括由 Google Cloud 填充的那些,以及特定於 Firebase 的環境變量:

process.env.FIREBASE_CONFIG :提供以下 Firebase 項目配置信息:

{
  databaseURL: 'https://databaseName.firebaseio.com',
  storageBucket: 'projectId.appspot.com',
  projectId: 'projectId'
}

當您初始化不帶參數的 Firebase Admin SDK 時,會自動應用此配置。如果您在 JavaScript 中編寫函數,請像這樣初始化:

const admin = require('firebase-admin');
admin.initializeApp();

如果您在 TypeScript 中編寫函數,請像這樣初始化:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import 'firebase-functions';
admin.initializeApp();

如果您需要使用服務帳戶憑據使用默認項目配置初始化 Admin SDK,您可以從文件加載憑據並將它們添加到FIREBASE_CONFIG ,如下所示:

serviceAccount = require('./serviceAccount.json');

const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(serviceAccount);
admin.initializeApp(adminConfig);