پیکربندی محیط

اغلب برای کارکردهای خود به پیکربندی اضافی نیاز دارید، مثلاً کلیدهای API طرف سوم یا تنظیمات قابل‌تنظیم. ‫Firebase SDK برای 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.`);
  }
);

پایتون

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!')

هنگام استقرار تابع با متغیرهای پیکربندی پارامتری، Firebase CLI ابتدا تلاش می‌کند مقادیر آن‌ها را از فایل‌های .env محلی بار کند. اگر در آن فایل‌ها وجود نداشته باشند و default تنظیم نشده باشد، «میانای خط فرمان» درطول استقرار مقادیر را درخواست می‌کند و سپس مقادیر را به‌طور خودکار در فایل .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());
})

پایتون

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

پایتون

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 پشتیبانی می‌کند. انواع پشتیبانی‌شده عبارت‌اند از:

  • راز
  • تار
  • بولی
  • عدد صحیح
  • شناور
  • فهرست (Node.js)
  • رمز JSON (Node.js)

برای اطلاعات درباره توابع تعریف پارامترها، به مرجع فضای نام params مراجعه کنید.

مقادیر و عبارات پارامتر

‫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) => {
    //…

پایتون

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) => {
    //…

پایتون

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

پایتون

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!')

پارامترهای داخلی

«کیت توسعه نرم‌افزار توابع ابری» سه پارامتر ازپیش تعریف‌شده ارائه می‌دهد که از زیربسته firebase-functions/params دردسترس است:

Node.js

  • projectID — پروژه Cloud که تابع در آن اجرا می‌شود.
  • databaseURL — نشانی وب نمونه «پایگاه داده بی‌درنگ» مرتبط با تابع (درصورت فعال بودن در پروژه Firebase).
  • storageBucket — مخزن Cloud Storage مرتبط با تابع (درصورت فعال بودن در پروژه Firebase).

پایتون

  • PROJECT_ID — پروژه Cloud که تابع در آن اجرا می‌شود.
  • DATABASE_URL — نشانی وب نمونه «پایگاه داده بی‌درنگ» مرتبط با تابع (درصورت فعال بودن در پروژه 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();
    //…

پایتون

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

ازآنجایی‌که مقادیر رمزها تا زمان اجرای تابع پنهان هستند، نمی‌توانید از آن‌ها هنگام پیکربندی تابع استفاده کنید.

اسرار ساختاریافته JSON

اگر چندین مقدار پیکربندی دارید که ازنظر منطقی مرتبط هستند (برای مثال، تنظیمات سرویس طرف سوم)، می‌توانید آن‌ها را بااستفاده از defineJsonSecret() در یک راز واحد به‌عنوان شیء JSON ساختاریافته ذخیره کنید. این رویکرد می‌تواند به سازمان‌دهی پیکربندی شما کمک کند و با ذخیره کردن گروهی از مقادیر پیکربندی مرتبط در یک راز، استفاده کارآمدتری از سطح رایگان Cloud Secret Manager داشته باشید.

مقدار ذخیره‌شده در «مدیر رمز» باید رشته JSON معتبر باشد. وقتی به .value() دسترسی پیدا می‌کنید، کیت توسعه نرم‌افزار به‌طور خودکار رشته JSON را به شیء JavaScript تجزیه می‌کند.

مثال:

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

// Define a single secret to hold all configuration for some API
const someApiConfig = defineJsonSecret('SOMEAPI_CONFIG');

exports.myApi = onRequest(
  { secrets: [someApiConfig] },
  (req, res) => {
    // someApiConfig.value() automatically parses the JSON secret
    const { apiKey, webhookSecret, clientId } = someApiConfig.value();

    // Now you can use apiKey, webhookSecret, clientId
    // ...
  }
);

برای ایجاد رمز SOMEAPI_CONFIG، مقدار آن را در «مدیر رمز» روی رشته JSON زیر تنظیم می‌کنید:

{
  "apiKey": "key_...",
  "webhookSecret": "secret_...",
  "clientId": "client_..."
}

اگر مقدار رمز JSON معتبر نباشد، دسترسی به someApiConfig.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}`);
});

پایتون

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 خود به مجموعه متفاوتی از متغیرهای محیطی نیاز دارید (مثلاً آماده‌سازی در مقابل تولید)، فایل .env.<project or alias> ایجاد کنید و متغیرهای محیطی مختص پروژه خود را در آن بنویسید. متغیرهای محیطی از .env و فایل‌های .env مختص پروژه (درصورت وجود) در همه توابع مستقرشده گنجانده خواهد شد.

برای مثال، یک پروژه می‌تواند شامل این سه فایل باشد که مقادیر کمی متفاوت برای توسعه و تولید دارند:

.env .env.dev .env.prod
سیاره=زمین

مخاطب=انسان‌ها

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
  • نقطه ورود
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • نام_تابع
  • 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. از ریشه فهرست راهنمای پروژه محلی‌تان، دستور زیر را اجرا کنید:

    firebase functions:secrets:set SECRET_NAME

  2. مقداری برای SECRET_NAME وارد کنید.

    «خط فرمان» پیام موفقیت را تکرار می‌کند و هشدار می‌دهد که باید کارکردها را برای اعمال تغییرات مستقر کنید.

  3. قبل‌از استقرار، مطمئن شوید که کد تابع شما به تابع اجازه می‌دهد بااستفاده از گزینه secrets به راز دسترسی پیدا کند:

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

    پایتون

    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

    اکنون می‌توانید مانند هر متغیر محیط دیگری به آن دسترسی داشته باشید. برعکس، اگر تابع دیگری که رمز را مشخص نمی‌کند سعی کند به رمز دسترسی پیدا کند، مقدار تعریف‌نشده‌ای دریافت می‌کند:

    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 `secrets` option is missing
    });
    

    پایتون

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

پس‌از استقرار تابع، به مقدار رمز دسترسی خواهد داشت. فقط کارکردهایی که به‌طور خاص شامل رمز در گزینه secrets خود هستند به آن رمز به‌عنوان متغیر محیطی دسترسی خواهند داشت. این کار به شما کمک می‌کند مطمئن شوید مقادیر رمز فقط در جایی که به آن‌ها نیاز است دردسترس باشند و خطر لو رفتن تصادفی رمز را کاهش می‌دهد.

مدیریت رمزها

از Firebase CLI برای مدیریت کردن رمزهایتان استفاده کنید. هنگام مدیریت رمزها به این روش، به‌خاطر داشته باشید که برخی‌از تغییرات «خط فرمان» نیازمند این است که توابع مرتبط را تغییر دهید و/یا دوباره مستقر کنید. به‌طور دقیق:

  • هرگاه مقدار جدیدی برای یک رمز تنظیم می‌کنید، باید همه توابعی را که به آن رمز ارجاع می‌دهند مجدداً مستقر کنید تا مقدار جدید را دریافت کنند.
  • اگر رمز را حذف می‌کنید، مطمئن شوید که هیچ‌کدام از توابع مستقر شما به آن رمز ارجاع نمی‌دهد. توابعی که از مقدار رمزی استفاده می‌کنند که حذف شده است، بدون اطلاع قبلی ازکار می‌افتند.

در اینجا خلاصه‌ای از فرمان‌های Firebase CLI برای مدیریت رمز ارائه شده است:

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

# Set secret from file
firebase functions:secrets:set SECRET_NAME --data-file file.json

# Validate secret value as json
cat file.json | firebase functions:secrets:set SECRET_NAME --format=json

# Pipe from stdin and set secret
cat file.json | firebase functions:secrets:set SECRET_NAME --format=json

# 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، می‌توانید پارامتر اختیاری نسخه را برای مدیریت نسخه خاصی ارائه دهید. برای مثال:

functions:secrets:access SECRET_NAME[@VERSION]

برای کسب اطلاعات بیشتر درباره این عملیات، -h را با فرمان ارسال کنید تا راهنمای «میانای خط فرمان» را ببینید.

نحوه صورت‌حساب زدن برای رمزها

‫Secret Manager اجازه می‌دهد ۶ نسخه فعال رمز بدون هزینه داشته باشید. این یعنی می‌توانید در هر ماه ۶ راز در پروژه Firebase بدون هزینه داشته باشید.

به‌طور پیش‌فرض، Firebase CLI تلاش می‌کند نسخه‌های محرمانه استفاده‌نشده را درصورت لزوم به‌طور خودکار ازبین ببرد، مثلاً وقتی توابع را با نسخه جدیدی از راز مستقر می‌کنید. همچنین می‌توانید بااستفاده از functions:secrets:destroy و functions:secrets:prune، رمزهای استفاده‌نشده را به‌طور فعال پاکسازی کنید.

‫Secret Manager به شما امکان می‌دهد در یک راز، ۱۰٬۰۰۰ عملیات دسترسی ماهانه بدون صورت‌حساب داشته باشید. نمونه‌های تابع هر بار که راه‌اندازی سرد می‌شوند، فقط رازهای مشخص‌شده در گزینه secrets خود را می‌خوانند. اگر نمونه‌های تابع زیادی دارید که تعداد زیادی رمز را می‌خوانند، ممکن است پروژه شما از این سهمیه فراتر رود، در این صورت برای هر ۱۰٬۰۰۰ عملیات دسترسی، ۰٫۰۳ دلار از شما کسر خواهد شد.

برای اطلاعات بیشتر، به Secret Manager قیمت‌گذاری مراجعه کنید.

پشتیبانی از شبیه‌ساز

پیکربندی محیط با dotenv برای تعامل با Cloud Functionsشبیه‌ساز محلی طراحی شده است.

هنگام استفاده از شبیه‌ساز محلی Cloud Functions، می‌توانید با راه‌اندازی فایل .env.local، متغیرهای محیطی پروژه خود را ملغی کنید. محتوای .env.local بر .env و فایل .env مختص پروژه اولویت دارد.

برای مثال، یک پروژه می‌تواند شامل این سه فایل باشد که مقادیر کمی متفاوت برای توسعه و آزمایش محلی دارند:

.env .env.dev .env.local
سیاره=زمین

مخاطب=انسان‌ها

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 API منسوخ شده است و در مارس ۲۰۲۷ از رده خارج خواهد شد. پس‌از آن تاریخ، استقرارها با functions.config ناموفق خواهد بود.

برای جلوگیری از خطاهای استقرار، پیکربندی‌تان را بااستفاده از Firebase CLI به Cloud Secret Manager انتقال دهید. این روش به‌عنوان کارآمدترین و ایمن‌ترین راه برای انتقال پیکربندی شما اکیداً توصیه می‌شود.

  1. صادر کردن پیکربندی با Firebase CLI

    از فرمان config export برای صادر کردن پیکربندی محیط موجود به راز جدید در Cloud Secret Manager استفاده کنید:

    $ firebase functions:config:export
    i  This command retrieves your Runtime Config values (accessed via functions.config())
       and exports them as a Secret Manager secret.
    
    i  Fetching your existing functions.config() from your project...  ✔
       Fetched your existing functions.config().
    
    i  Configuration to be exported:
    ⚠  This may contain sensitive data. Do not share this output.
    
    {
       ...
    }
    
    ✔ What would you like to name the new secret for your configuration? RUNTIME_CONFIG
    
    ✔  Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```
    
  2. به‌روز کردن کد تابع برای پیوند دادن اسرار

    برای استفاده از پیکربندی ذخیره‌شده در رمز جدید در Cloud Secret Manager، از defineJsonSecret API در منبع تابع خود استفاده کنید. همچنین مطمئن شوید که رمزها به همه توابعی که به آن‌ها نیاز دارند متصل شده باشند.

    قبل‌از

    const functions = require("firebase-functions/v1");
    
    exports.myFunction = functions.https.onRequest((req, res) => {
      const apiKey = functions.config().someapi.key;
      // ...
    });
    

    بعداز

    const { onRequest } = require("firebase-functions/v2/https");
    const { defineJsonSecret } = require("firebase-functions/params");
    
    const config = defineJsonSecret("RUNTIME_CONFIG");
    
    exports.myFunction = onRequest(
      // Bind secret to your function
      { secrets: [config] },
      (req, res) => {
        // Access secret values via .value()
        const apiKey = config.value().someapi.key;
        // ...
    });
    
  3. مستقر کردن توابع

    برای اعمال تغییرات و پیوند دادن اجازه‌های رمز، کارکردهای به‌روزشده‌تان را مستقر کنید.

    firebase deploy --only functions:<your-function-name>
    

متغیرهای محیطی که به‌طور خودکار تکمیل می‌شوند

متغیرهای محیطی وجود دارد که به‌طور خودکار در زمان اجرای توابع و در توابع شبیه‌سازی‌شده محلی تکمیل می‌شوند. این موارد شامل آن‌هایی است که توسط Google Cloud تکمیل شده‌اند، و همچنین متغیر محیطی ویژه Firebase:

‫process.env.FIREBASE_CONFIG: اطلاعات پیکربندی پروژه Firebase زیر را ارائه می‌دهد:

{
  databaseURL: 'https://DATABASE_NAME.firebaseio.com',
  storageBucket: 'PROJECT_ID.firebasestorage.app',
  projectId: 'PROJECT_ID'
}

توجه داشته باشید که مقادیر در پیکربندی واقعی Firebase شما ممکن است بسته به منابعی که در پروژه‌تان تدارک دیده‌اید متفاوت باشد.

این پیکربندی به‌طور خودکار زمانی اعمال می‌شود که «کیت توسعه نرم‌افزار Firebase Admin» را بدون آرگومان مقداردهی اولیه کنید. اگر در جاوا اسکریپت تابع می‌نویسید، به این صورت مقداردهی اولیه کنید:

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

اگر درحال نوشتن تابع در TypeScript هستید، به این صورت مقداردهی اولیه کنید:

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

اگر نیاز دارید «کیت توسعه نرم‌افزار سرپرست» را با پیکربندی پیش‌فرض پروژه بااستفاده از اطلاعات اعتباری حساب سرویس مقداردهی اولیه کنید، می‌توانید اطلاعات اعتباری را از فایلی بار کنید و آن‌ها را به FIREBASE_CONFIG اضافه کنید، مانند این:

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

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