הגדרת הסביבה


לרוב תצטרכו להגדיר הגדרות נוספות לפונקציות, כמו מפתחות API של צד שלישי או הגדרות שניתן לשנות. ‏SDK של Firebase ל-Cloud Functions מציע הגדרת סביבה מובנית כדי שיהיה קל לאחסן ולשלוף את סוג הנתונים הזה בפרויקט.

אפשר לבחור מבין האפשרויות הבאות:

  • הגדרה עם פרמטרים (מומלצת לרוב התרחישים). כך אפשר להגדיר סביבה עם סוגים מוגדרים מראש, עם פרמטרים שמאומתים בזמן הפריסה, וכך למנוע שגיאות ולפשט את תהליך ניפוי הבאגים.
  • הגדרה של משתני סביבה שמבוססת על קבצים. בגישה הזו, יוצרים באופן ידני קובץ dotenv כדי לטעון את משתני הסביבה.

ברוב תרחישי השימוש מומלץ להשתמש בהגדרה עם פרמטרים. הגישה הזו מאפשרת לערכים של ההגדרות להיות זמינים גם במהלך זמן הריצה וגם בזמן הפריסה, והפריסה חסומה אלא אם לכל הפרמטרים יש ערך תקף. לעומת זאת, הגדרה באמצעות משתני סביבה לא זמינה בזמן הפריסה.

הגדרה עם פרמטרים

Cloud Functions for Firebase מספק ממשק להגדרת פרמטרים של תצורה באופן דקלרטיבי בתוך קוד המקור. הערך של הפרמטרים האלה זמין גם במהלך פריסה של פונקציה, כשמגדירים את אפשרויות הפריסה והזמן הריצה, וגם במהלך הביצוע. כלומר, ה-CLI ייחסום את הפריסה אלא אם לכל הפרמטרים יהיה ערך תקין.

Node.js

const { onRequest } = require('firebase-functions/v2/https');
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 = onRequest(
  { minInstances: minInstancesConfig },
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

# To use configured parameters inside the config for a function, provide them
# directly. To use them at runtime, call .value() on them.
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

כשפורסים פונקציה עם משתני תצורה עם פרמטרים, ה-CLI של Firebase מנסה קודם לטעון את הערכים שלהם מקובצי ‎.env מקומיים. אם הם לא קיימים בקבצים האלה ולא הוגדר default, ה-CLI יציג בקשה לערכים במהלך הפריסה, ואז ישמור אותם באופן אוטומטי בקובץ .env בשם .env.<project_ID> בספרייה functions/:

$ 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> שנוצר למערכת בקרת הגרסאות.

שימוש בפרמטרים בהיקף גלובלי

במהלך הפריסה, קוד הפונקציות נטען ונבדק לפני שיש לפרמטרים ערכים ממשיים. כלומר, אחזור של ערכי פרמטרים ברמת ההיקף הגלובלי גורם לכישלון הפריסה. במקרים שבהם רוצים להשתמש בפרמטר כדי לאתחל ערך גלובלי, אפשר להשתמש בקריאה החוזרת (callback) של האתחול onInit(). הקריאה החוזרת הזו פועלת לפני שהפונקציות פועלות בסביבת הייצור, אבל היא לא נקראת במהלך הפריסה, כך שזו נקודה בטוחה לגשת לערכים של פרמטרים.

Node.js

const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v2/core');

const apiKey = defineSecret('GOOGLE_API_KEY');

let genAI;
onInit(() => {
  genAI = new GoogleGenerativeAI(apiKey.value());
})

Python

from firebase_functions.core import init
from firebase_functions.params import StringParam, PROJECT_ID
import firebase_admin
import vertexai

location = StringParam("LOCATION")

x = "hello"

@init
def initialize():
  # Note: to write back to a global, you'll need to use the "global" keyword
  # to avoid creating a new local with the same name.
  global x
  x = "world"
  firebase_admin.initialize_app()
  vertexai.init(PROJECT_ID.value, location.value)

אם משתמשים בפרמטרים מהסוג Secret, חשוב לזכור שהם זמינים רק בתהליך של הפונקציות שקישרו את הסוד. אם סוד מקושר רק בפונקציות מסוימות, צריך לבדוק אם secret.value() שגוי לפני שמשתמשים בו.

הגדרת ההתנהגות של CLI

אפשר להגדיר פרמטרים באמצעות אובייקט Options שקובע איך ה-CLI יציג בקשה להזנת ערכים. בדוגמה הבאה אפשר לאמת את הפורמט של מספר הטלפון, לספק אפשרות בחירה פשוטה ולאכלס אפשרות בחירה באופן אוטומטי מהפרויקט ב-Firebase:

Node.js

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: params.select(["odd", "even"])});

const memory = defineInt("MEMORY", {
  description: "How much memory do you need?",
  input: params.select({ "micro": 256, "chonky": 2048 }),
});

const extensions = defineList("EXTENSIONS", {
  description: "Which file types should be processed?",
  input: params.multiSelect(["jpg", "tiff", "png", "webp"]),
});

const storageBucket = defineString('BUCKET', {
  description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets",
  input: params.PICK_STORAGE_BUCKET,
});

Python

from firebase_functions.params import (
    StringParam,
    ListParam,
    TextInput,
    SelectInput,
    SelectOptions,
    ResourceInput,
    ResourceType,
)

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

WELCOME_MESSAGE = StringParam(
    "WELCOME_MESSAGE",
    default="Hello World",
    description="The greeting that is returned to the caller of this function",
)

ONLY_PHONE_NUMBERS = StringParam(
    "PHONE_NUMBER",
    input=TextInput(
        validation_regex="\d{3}-\d{3}-\d{4}",
        validation_error_message="Please enter a phone number in the format XXX-YYY-XXX",
    ),
)

SELECT_OPTION = StringParam(
    "PARITY",
    input=SelectInput([SelectOptions(value="odd"), SelectOptions(value="even")]),
)

STORAGE_BUCKET = StringParam(
    "BUCKET",
    input=ResourceInput(type=ResourceType.STORAGE_BUCKET),
    description="This will automatically populate the selector field with the deploying Cloud Project's storage buckets",
)

סוגי פרמטרים

הגדרה עם פרמטרים מספקת סוגים חזקים לערכים של פרמטרים, ותומכת גם בסודות מ-Cloud Secret Manager. הסוגים הנתמכים הם:

  • סודי
  • String
  • בוליאני
  • מספר שלם
  • Float
  • רשימה (Node.js)

ערכים וביטויים של פרמטרים

מערכת Firebase מעריכה את הפרמטרים גם בזמן הפריסה וגם בזמן ההפעלה של הפונקציה. בגלל הסביבות הכפולות האלה, צריך להיזהר כשמשווים בין ערכי הפרמטרים, וכשמשתמשים בהם כדי להגדיר אפשרויות בסביבת זמן הריצה של הפונקציות.

כדי להעביר פרמטר לפונקציה כאפשרות בסביבת זמן הריצה, מעבירים אותו ישירות:

Node.js

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

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

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

בנוסף, אם אתם צריכים להשוות לערך של פרמטר כדי לדעת איזו אפשרות לבחור, תצטרכו להשתמש במנגנוני השוואה מובנים במקום לבדוק את הערך:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const environment = params.defineString(ENVIRONMENT, {default: 'dev'});

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

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

ENVIRONMENT = StringParam("ENVIRONMENT", default="dev")
MIN_INSTANCES = ENVIRONMENT.equals("PRODUCTION").then(10, 0)

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

אפשר לגשת לפרמטר ולביטוי הפרמטר שמשמשים רק במהלך זמן הריצה באמצעות הפונקציה value:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
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 = onRequest(
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import StringParam

WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

@https_fn.on_request()
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

פרמטרים מובנים

ב-Cloud Functions SDK יש שלושה פרמטרים מוגדרים מראש, שזמינים בחבילת המשנה firebase-functions/params:

Node.js

  • projectID – הפרויקט ב-Cloud שבו הפונקציה פועלת.
  • databaseURL – כתובת ה-URL של המכונה של 'מסד נתונים בזמן אמת' שמשויכת לפונקציה (אם היא מופעלת בפרויקט Firebase).
  • storageBucket – הקטגוריה ב-Cloud Storage שמשויכת לפונקציה (אם היא מופעלת בפרויקט Firebase).

Python

  • PROJECT_ID – הפרויקט ב-Cloud שבו הפונקציה פועלת.
  • DATABASE_URL – כתובת ה-URL של המכונה של Realtime Database שמשויכת לפונקציה (אם היא מופעלת בפרויקט Firebase).
  • STORAGE_BUCKET – הקטגוריה ב-Cloud Storage שמשויכת לפונקציה (אם היא מופעלת בפרויקט Firebase).

הם פועלים כמו פרמטרים של מחרוזות שהוגדרו על ידי משתמשים מכל הבחינות, מלבד העובדה שמכיוון שהערכים שלהם תמיד ידועים ל-CLI של Firebase, אף פעם לא תופיע בקשה להזין את הערכים שלהם בזמן הפריסה, והם גם לא יישמרו בקובצי .env.

פרמטרים סודיים

פרמטרים מסוג Secret, שמוגדרים באמצעות defineSecret(), מייצגים פרמטרים של מחרוזת שיש להם ערך שמאוחסן ב-Cloud Secret Manager. במקום לבדוק מול קובץ .env מקומי ולכתוב ערך חדש לקובץ אם הם חסרים, פרמטרים סודיים בודקים אם קיימים ב-Cloud Secret Manager ושולחים באופן אינטראקטיבי את הערך של סוד חדש במהלך הפריסה.

פרמטרים סודיים שמוגדרים כך חייבים להיות מקושרים לפונקציות נפרדות שצריכה להיות להן גישה אליהם:

Node.js

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

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

Python

from firebase_functions import https_fn
from firebase_functions.params import SecretParam

DISCORD_API_KEY = SecretParam('DISCORD_API_KEY')

@https_fn.on_request(secrets=[DISCORD_API_KEY])
def post_to_discord(req):
    api_key = DISCORD_API_KEY.value

ערכי הסודות מוסתרים עד להרצת הפונקציה, ולכן אי אפשר להשתמש בהם בזמן הגדרת הפונקציה.

משתני סביבה

Cloud Functions for Firebase תומך בפורמט הקובץ dotenv לטעינת משתני סביבה שצוינו בקובץ .env בסביבת זמן הריצה של האפליקציה. אחרי הפריסה, אפשר לקרוא את משתני הסביבה דרך הממשק process.env (בפרויקטים שמבוססים על Node.js) או os.environ (בפרויקטים שמבוססים על Python).

כדי להגדיר את הסביבה כך, יוצרים קובץ .env בפרויקט, מוסיפים את המשתנים הרצויים ופורסים:

  1. יוצרים קובץ .env בספרייה functions/:

    # 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.
    # ...
    

אחרי הפריסה של משתני הסביבה המותאמים אישית, קוד הפונקציה יכול לגשת אליהם:

Node.js

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

Python

import os

@https_fn.on_request()
def hello(req):
    return https_fn.Response(
        f"Hello {os.environ.get('PLANET')} and {os.environ.get('AUDIENCE')}"
    )

פריסה של מספר קבוצות של משתני סביבה

אם אתם צריכים קבוצה חלופית של משתני סביבה לפרויקטים שלכם ב-Firebase (למשל, סביבה ל-Staging לעומת סביבה לייצור), תוכלו ליצור קובץ .env.<project or alias> ולכתוב בו את משתני הסביבה הספציפיים לפרויקט. משתני הסביבה מ-.env ומקובצי .env ספציפיים לפרויקט (אם הם קיימים) ייכללו בכל הפונקציות שנפרסו.

לדוגמה, פרויקט יכול לכלול את שלושת הקבצים האלה, שמכילים ערכים שונים במקצת לפיתוח ולייצור:

.env .env.dev .env.prod
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

בהתאם לערכים בקובצי ה-env הנפרדים, קבוצת משתני הסביבה שנפרסים עם הפונקציות תשתנה בהתאם לפרויקט היעד:

$ 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
  • ENTRY_POINT
  • 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
  • PORT
  • K_CONFIGURATION

אחסון מידע רגיש של הגדרות אישיות וגישה אליו

אפשר להשתמש במשתני סביבה ששמורים בקובצי .env כדי להגדיר פונקציות, אבל הם לא נחשבים לדרך מאובטחת לאחסון מידע רגיש כמו פרטי כניסה למסד נתונים או מפתחות API. חשוב במיוחד לעשות זאת אם אתם מעבירים את קובצי ה-.env לבקרת הגרסאות.

כדי לעזור לכם לאחסן מידע רגיש של הגדרות, Cloud Functions for Firebase משתלב עם Google Cloud Secret Manager. השירות המוצפן הזה מאחסן את ערכי ההגדרות בצורה מאובטחת, ועדיין מאפשר גישה קלה מהפונקציות שלכם במקרה הצורך.

יצירה של סוד ושימוש בו

כדי ליצור סוד, משתמשים ב-CLI של Firebase.

כדי ליצור סוד ולהשתמש בו:

  1. מריצים את הפקודה הבאה מהשורש של ספריית הפרויקט המקומית:

    firebase functions:secrets:set SECRET_NAME

  2. צריך להזין ערך בשדה SECRET_NAME.

    ב-CLI תוצג הודעה על הצלחה, ויצוין שצריך לפרוס פונקציות כדי שהשינוי ייכנס לתוקף.

  3. לפני הפריסה, חשוב לוודא שקוד הפונקציות מאפשר לפונקציה לגשת לסוד באמצעות הפרמטר runWith:

    Node.js

    const { onRequest } = require('firebase-functions/v2/https');
    
    exports.processPayment = onRequest(
      { secrets: ["SECRET_NAME"] },
      (req, res) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      }
    );

    Python

    import os
    from firebase_functions import https_fn
    
    @https_fn.on_request(secrets=["SECRET_NAME"])
    def process_payment(req):
        myBillingService = initialize_billing(key=os.environ.get('SECRET_NAME'))
        # Process the payment
        ...
    
  4. פורסים את Cloud Functions:

    firebase deploy --only functions

    עכשיו תוכלו לגשת אליו כמו לכל משתנה סביבה אחר. לעומת זאת, אם פונקציה אחרת שלא מציינת את הסוד ב-runWith תנסה לגשת אליו, היא תקבל ערך לא מוגדר:

    Node.js

    exports.anotherEndpoint = 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
    });
    

    Python

    @https_fn.on_request()
    def another_endpoint(req):
        return https_fn.Response(f"The secret API key is {os.environ.get("SECRET_NAME")}")
        # Responds with "The secret API key is None" because the `secrets` parameter is missing.
    

אחרי שפורסים את הפונקציה, תהיה לה גישה לערך הסודי. רק פונקציות שכוללות באופן ספציפי סוד בפרמטרים שלהן runWith תהיה גישה לסוד הזה כמשתנה סביבה. כך תוכלו לוודא שערכים סודיים יהיו זמינים רק במקומות שבהם הם נדרשים, וכך לצמצם את הסיכון לדליפת סוד בטעות.

ניהול סודות

משתמשים בממשק CLI של Firebase כדי לנהל את הסודות. כשמנהלים סודות בדרך הזו, חשוב לזכור שחלק מהשינויים ב-CLI מחייבים לשנות או לפרוס מחדש את הפונקציות המשויכות. באופן ספציפי:

  • בכל פעם שמגדירים ערך חדש לסוד, צריך לפרוס מחדש את כל הפונקציות שמפנות לסוד הזה כדי שהן יקבלו את הערך העדכני.
  • אם מוחקים סוד, צריך לוודא שאף אחת מהפונקציות שנפרסו לא מפנה לסוד הזה. פונקציות שמשתמשות בערך סודי שנמחק ייכשלו ללא הודעה.

סיכום של פקודות ה-CLI של Firebase לניהול סודות:

# 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

בפקודות access ו-destroy, אפשר לציין את הפרמטר האופציונלי version כדי לנהל גרסה מסוימת. לדוגמה:

functions:secrets:access SECRET_NAME[@VERSION]

למידע נוסף על הפעולות האלו, מעבירים את -h עם הפקודה כדי להציג את העזרה בנושא CLI.

איך מתבצע החיוב על סודות

ב-Secret Manager אפשר לשמור 6 גרסאות סודיות פעילות ללא עלות. המשמעות היא שתוכלו לשמור 6 סודות בחודש בפרויקט Firebase ללא עלות.

כברירת מחדל, ה-CLI של Firebase מנסה להשמיד באופן אוטומטי גרסאות סוד שלא בשימוש במקרים הרלוונטיים, למשל כשפורסים פונקציות עם גרסה חדשה של הסוד. בנוסף, אפשר לנקות באופן פעיל סודות שלא בשימוש באמצעות functions:secrets:destroy ו-functions:secrets:prune.

השירות Secret Manager מאפשר לבצע 10,000 פעולות גישה חודשיות שלא חויבו בסוד. מכונות של פונקציות קוראות רק את הסודות שצוינו בפרמטר runWith בכל פעם שהן מופעלות במצב התחלתי (cold start). אם יש לכם הרבה מכונות של פונקציות שקוראות הרבה סודות, יכול להיות שהפרויקט שלכם יחרוג מההרשאה הזו. במקרה כזה, תחויבו ב-0.03 $לכל 10,000 פעולות גישה.

מידע נוסף זמין במאמר תמחור Secret Manager.

תמיכה באמולטור

הגדרת הסביבה באמצעות dotenv נועדה לפעול באופן הדדי עם אמולטור Cloud Functions מקומי.

כשמשתמשים באמולטור Cloud Functions מקומי, אפשר לשנות את משתני הסביבה בפרויקט על ידי הגדרת קובץ .env.local. התוכן של .env.local מקבל קדימות על פני .env ועל קובץ .env הספציפי לפרויקט.

לדוגמה, פרויקט יכול לכלול את שלושת הקבצים האלה, שמכילים ערכים שונים במקצת לפיתוח ולבדיקה מקומית:

.env .env.dev .env.local
PLANET=Earth

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Local Humans

כשהמכונה הווירטואלית מופעלת בהקשר המקומי, היא טוענת את משתני הסביבה באופן הבא:

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

סודות ופרטי כניסה באמולטור Cloud Functions

האמולטור Cloud Functions תומך בשימוש בסודות כדי לאחסן ולגשת למידע רגיש של הגדרות. כברירת מחדל, הסימולטור ינסה לגשת לסודות הייצור באמצעות Application Default Credentials. במצבים מסוימים כמו סביבות CI, יכול להיות שהאמולטור לא יוכל לגשת לערכים הסודיים בגלל הגבלות של הרשאות.

בדומה לתמיכה של המהדר של Cloud Functions במשתני סביבה, אפשר לבטל את ערכי הסודות על ידי הגדרת קובץ .secret.local. כך קל לבדוק את הפונקציות באופן מקומי, במיוחד אם אין לכם גישה לערך הסודי.

מעבר מהגדרות הסביבה

אם השתמשתם בהגדרות סביבה עם functions.config, תוכלו להעביר את ההגדרות הקיימות כמשתני סביבה (בפורמט dotenv). ב-CLI של Firebase יש פקודת ייצוא שמפיקה את ההגדרות של כל כינוי או פרויקט שמפורטים בקובץ .firebaserc בספרייה (בדוגמה הבאה, local,‏ dev ו-prod) כקובצי .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 במקום זאת, כפי שמתואר בקטע משתני סביבה.