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

اغلب برای توابع خود به پیکربندی اضافی نیاز خواهید داشت، مانند کلیدهای API شخص ثالث یا تنظیمات قابل تنظیم. Firebase SDK for 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» ابتدا تلاش می‌کند مقادیر آن‌ها را از فایل‌های .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());
})

پایتون

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

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

کیت توسعه نرم‌افزار Cloud Functions سه پارامتر ازپیش تعریف‌شده ارائه می‌دهد که از زیربسته 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 شناخته‌شده است، مقادیر آن‌ها هرگز در زمان استقرار درخواست نمی‌شود و در فایل‌های .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 داشته باشد.

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

مثال:

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
PLANET=Earth

AUDIENCE=Humans

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
  • درگاه
  • 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 برای مدیریت اطلاعات محرمانه استفاده کنید. هنگام مدیریت اسرار به این روش، به‌خاطر داشته باشید که برخی‌از تغییرات CLI مستلزم آن است که توابع مرتبط را اصلاح و/یا دوباره مستقر کنید. به‌طور خاص:

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

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

# 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 امکان استفاده از ۶ نسخه فعال از Secret را بدون هزینه فراهم می‌کند. این یعنی می‌توانید در هر ماه ۶ راز در پروژه 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

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 از استفاده از اطلاعات محرمانه برای ذخیره و دسترسی به اطلاعات پیکربندی حساس پشتیبانی می‌کند. به‌طور پیش‌فرض، شبیه‌ساز سعی می‌کند بااستفاده از اعتبارنامه‌های پیش‌فرض برنامه به اطلاعات محرمانه تولید شما دسترسی پیدا کند. در برخی شرایط مانند محیط‌های CI، شبیه‌ساز ممکن است به‌دلیل محدودیت‌های مجوز نتواند به مقادیر محرمانه دسترسی پیدا کند.

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

انتقال از پیکربندی زمان اجرا

‫functions.config API منسوخ شده است و در مارس ۲۰۲۷ از رده خارج خواهد شد. پس‌از آن تاریخ، استقرار با functions.config ناموفق خواهد بود.

برای جلوگیری از شکست استقرار، پیکربندی‌تان را بااستفاده از رابط خط فرمان Firebase به 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. Deploy Functions

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

    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 SDK را بدون هیچ آرگومانی مقداردهی اولیه می‌کنید، این پیکربندی به‌طور خودکار اعمال می‌شود. اگر توابع را در جاوا اسکریپت می‌نویسید، به این صورت مقداردهی اولیه کنید:

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