הגדרת הסביבה


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

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

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

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

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

Cloud Functions for Firebase מספק ממשק להגדרת פרמטרים של תצורה באופן הצהרתי בתוך ה-codebase. הערך של הפרמטרים האלה זמין גם במהלך פריסת הפונקציה, כשמגדירים את אפשרויות הפריסה והזמן הריצה, וגם במהלך ההפעלה. כלומר, ה-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> שנוצר לבקרת גרסאות.

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

במהלך הפריסה, קוד הפונקציות נטען ונבדק לפני שהפרמטרים מקבלים ערכים בפועל. המשמעות היא שאחזור ערכי פרמטרים במהלך היקף גלובלי גורם לכשל בפריסה. אם רוצים להשתמש בפרמטר כדי לאתחל ערך גלובלי, צריך להשתמש בפונקציית הקריאה החוזרת לאתחול 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. הסוגים הנתמכים הם:

  • סודי
  • מחרוזת
  • בוליאני
  • מספר שלם
  • 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!')

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

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

Node.js

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

Python

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

הפונקציות האלה דומות לפרמטרים של מחרוזות שהוגדרו על ידי המשתמש בכל ההיבטים, מלבד העובדה שהערכים שלהן תמיד ידועים לממשק Firebase CLI, ולכן לא תהיה בקשה להזין את הערכים שלהן במהלך הפריסה והן לא יישמרו בקובצי .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 לעומת Production), אתם יכולים ליצור קובץ .env.<project or alias> ולכתוב בו את משתני הסביבה הספציפיים לפרויקט. משתני הסביבה מהקבצים .env ו-.env הספציפיים לפרויקט (אם הם קיימים) ייכללו בכל הפונקציות שנפרסו.

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

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

קהל=בני אדם

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

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

$ 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. השירות המוצפן הזה מאחסן ערכי הגדרה בצורה מאובטחת, ועדיין מאפשר גישה קלה מהפונקציות שלכם כשצריך.

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

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

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

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

    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 שלהן יוכלו לגשת לסוד הזה כמשתנה סביבה. כך תוכלו לוודא שערכי הסודות זמינים רק במקומות שבהם הם נדרשים, ולהפחית את הסיכון לדליפת סוד בטעות.

ניהול סודות

אפשר להשתמש ב-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

בפקודות 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 בכל פעם שהם מופעלים מחדש. אם יש לכם הרבה מופעים של פונקציות שקוראים הרבה סודות, יכול להיות שהפרויקט שלכם יחרוג מהמכסה הזו, ובמקרה כזה תחויבו ב-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=Dev Humans קהל=אנשים מקומיים

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

  $ 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 של הספרייה (בדוגמה שלמטה, 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 במקום זאת, כמו שמוצג במשתני סביבה.