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

اغلب به پیکربندی اضافی برای توابع خود نیاز خواهید داشت، مانند کلیدهای 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> تولیدشده را به کنترل نسخه اضافه کنید.

استفاده از پارامترها در دامنه جهانی

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

پایتون

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 وارد کنید.

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

  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 نیاز به اصلاح و/یا استقرار مجدد دارند توابع مرتبط به‌طور خاص:

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

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

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

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