設定環境


通常,您需要對功能進行其他配置,例如第三方 API 金鑰或可調整設定。 Firebase SDK for Cloud Functions 提供內建環境配置,讓您可以輕鬆地為專案儲存和檢索此類資料。

您可以選擇以下三個選項:

  • 參數化配置(大多數場景推薦)。這提供了強類型環境配置以及在部署時驗證的參數,從而防止錯誤並簡化偵錯。
  • 基於檔案的環境變數配置。透過這種方法,您可以手動建立dotenv檔案來載入環境變數。
  • 使用 Firebase CLI 和functions.config進行執行時間環境配置(僅限 Cloud Functions(第一代))。

對於大多數用例,建議參數化配置。此方法使配置值在執行時間和部署時都可用,並且除非所有參數都具有有效值,否則部署將被封鎖。相反,環境變數的配置在部署時不可用。

參數化配置

Cloud Functions for Firebase 提供了一個接口,用於在程式碼庫中以聲明方式定義配置參數。這些參數的值在函數部署期間、設定部署和執行時間選項時以及執行期間都可用。這意味著 CLI 將阻止部署,除非所有參數都具有有效值。

若要在程式碼中定義參數,請遵循下列模型:

const functions = require('firebase-functions');
const { defineInt, defineString } = require('firebase-functions/params');

// Define some parameters
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
  (req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

使用參數化配置變數部署函數時,Firebase CLI 首先嘗試從本機 .env 檔案載入它們的值。如果它們不存在於這些檔案中且未設定default值,CLI 會在部署期間提示輸入值,然後自動將它們的值儲存到functions/目錄中名為.env .env.<project_ID>的 .env 檔案中:

$ firebase deploy
i  functions: preparing codebase default for deployment
? Enter a string value for ENVIRONMENT: prod
i  functions: Writing new parameter values to disk: .env.projectId
…
$ firebase deploy
i  functions: Loaded environment variables from .env.projectId

根據您的開發工作流程,將產生的.env.<project_ID>檔案新增至版本控制可能會很有用。

配置 CLI 行為

可以使用Options物件配置參數,該物件控制 CLI 如何提示輸入值。以下範例設定選項來驗證電話號碼的格式,提供簡單的選擇選項,並從 Firebase 專案自動填入選擇選項:

const { defineString } = require('firebase-functions/params');

const welcomeMessage = defineString('WELCOME_MESSAGE', {default: 'Hello World',
description: 'The greeting that is returned to the caller of this function'});

const onlyPhoneNumbers = defineString('PHONE_NUMBER', {input: {text:
{validationRegex: /\d{3}-\d{3}-\d{4}/, validationErrorMessage: "Please enter
a phone number in the format XXX-YYY-ZZZZ"}}});

const selectedOption = defineString('PARITY', {input: {select: {options:
[{value: "odd"}, {value: "even"}]}}})

const storageBucket = defineString('BUCKET', {input: {resource: {type:
"storage.googleapis.com/Bucket"}}, description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets"})

參數類型

參數化配置為參數值提供強類型化,並且還支援來自 Cloud Secret Manager 的機密。支援的類型有:

  • 秘密
  • 細繩
  • 布林值
  • 整數
  • 漂浮

參數值和表達式

Firebase 會在部署時和函數執行時評估您的參數。由於這些雙重環境,在比較參數值以及使用它們為函數設定執行時間選項時必須格外小心。

若要將參數作為運行時選項傳遞給函數,請直接傳遞:

const functions = require('firebase-functions');
const { defineInt} = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');

export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
  (req, res) => {
    //…

此外,如果您需要與參數進行比較以確定選擇哪個選項,則需要使用內建比較器而不是檢查值:

const functions = require('firebase-functions');
const { defineBool } = require('firebase-functions/params');
const environment = params.defineString(‘ENVIRONMENT’, {default: ‘dev’});

// use built-in comparators
const minInstancesConfig =environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
  (req, res) => {
    //…

僅在運行時使用的參數和參數表達式可以透過其value函數進行存取:

const functions = require('firebase-functions');
const { defineString } = require('firebase-functions/params');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = functions.https.onRequest(
 (req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

內建參數

Cloud Functions SDK 提供三個預定義參數,可從firebase-functions/params子包取得:

  • projectID — 運行該函數的雲端專案。
  • databaseURL — 與該函數關聯的即時資料庫實例的 URL(如果在 Firebase 專案上啟用)。
  • storageBucket — 與該函數關聯的 Cloud Storage 儲存桶(如果在 Firebase 專案上啟用)。

這些功能在所有方面都類似於使用者定義的字串參數,但由於 Firebase CLI 始終知道它們的值,因此在部署時永遠不會提示它們的值,也不會保存到.env檔案中。

秘密參數

使用defineSecret()定義的Secret類型的參數表示具有儲存在 Cloud Secret Manager 中的值的字串參數。金鑰參數不是檢查本機.env檔案並在檔案遺失時寫入新值,而是檢查 Cloud Secret Manager 中是否存在,並在部署期間以互動方式提示輸入新金鑰的值。

以這種方式定義的秘密參數必須綁定到有權存取它們的各個函數:

const functions = require('firebase-functions');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');

export const postToDiscord = functions.runWith({ secrets: [discordApiKey] }).https.onRequest(
  (req, res) => {
    const apiKey = discordApiKey.value();
    //…

由於秘密的值在函數執行之前是隱藏的,因此您在配置函數時無法使用它們。

環境變數

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
行星=地球

觀眾=人類

受眾=開發者受眾=產品人類

給定這些單獨檔案中的值,隨您的函數部署的環境變數集將根據您的目標專案而有所不同:

$ 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_ 開頭的鍵
  • 以下列表中的任意鍵:
  • 雲端運行時配置
  • 入口點
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • 函數名稱
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • 函數標識
  • FUNCTION_地區
  • 功能_目標
  • FUNCTION_SIGNATURE_TYPE
  • K_服務
  • K_修訂版
  • 港口
  • K_配置

儲存和存取敏感配置信息

.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命令,您可以提供可選的版本參數來管理特定版本。例如:

functions:secrets:access SECRET_NAME[@VERSION]

有關這些操作的更多信息,請在命令中傳遞-h以查看 CLI 幫助。

秘密如何計費

Secret Manager 允許免費使用 6 個有效的 Secret版本。這意味著您每月可以在 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
行星=地球

觀眾=人類

受眾=開發者觀眾=當地人

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

  $ 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

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

我們建議您在部署函數或將.env檔簽入原始碼管理之前仔細檢查產生的.env檔的內容。如果任何值敏感且不應洩露,請將它們從.env檔案中刪除,並將它們安全地儲存在Secret Manager中。

您還需要更新您的函數程式碼。任何使用functions.config函數現在都需要使用process.env ,如昇級到第二代所示。

環境配置

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

使用 CLI 設定環境配置

若要儲存環境數據,您可以在Firebase CLI中使用firebase functions:config:set指令。每個鍵都可以使用句點命名空間,將相關配置分組在一起。請記住,鍵中僅接受小寫字元;不允許使用大寫字元。

例如,要儲存「Some Service」的客戶端 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);