अपने एनवायरमेंट को कॉन्फ़िगर करना

अक्सर आपको अपने फ़ंक्शन के लिए अतिरिक्त कॉन्फ़िगरेशन की ज़रूरत होगी. जैसे, तीसरे पक्ष के एपीआई पासकोड या ट्यून की जा सकने वाली सेटिंग. Firebase के लिए Cloud Functions SDK टूल, पहले से मौजूद एनवायरमेंट कॉन्फ़िगरेशन की सुविधा देता है. इससे आपके प्रोजेक्ट के लिए, इस तरह के डेटा को सेव करना और वापस पाना आसान हो जाता है.

इनमें से कोई एक विकल्प चुना जा सकता है:

  • पैरामीटर वाला कॉन्फ़िगरेशन (ज़्यादातर मामलों में इसका सुझाव दिया जाता है). इससे, पैरामीटर के साथ स्ट्रॉन्गली-टाइप्ड एनवायरमेंट कॉन्फ़िगरेशन मिलता है. इन पैरामीटर की पुष्टि, डिप्लॉयमेंट के समय की जाती है. इससे गड़बड़ियों को रोकने और डीबग करने में मदद मिलती है.
  • एनवायरमेंट वैरिएबल का फ़ाइल-आधारित कॉन्फ़िगरेशन. इस तरीके में, एनवायरमेंट वैरिएबल लोड करने के लिए, मैन्युअल तरीके से dotenv फ़ाइल बनाई जाती है.

ज़्यादातर मामलों में, पैरामीटर वाले कॉन्फ़िगरेशन का इस्तेमाल करने का सुझाव दिया जाता है. इस तरीके से, कॉन्फ़िगरेशन वैल्यू रनटाइम और डिप्लॉयमेंट के समय, दोनों पर उपलब्ध होती हैं. साथ ही, जब तक सभी पैरामीटर के लिए कोई मान्य वैल्यू नहीं होती, तब तक डिप्लॉयमेंट को ब्लॉक कर दिया जाता है. इसके उलट, डिप्लॉयमेंट के समय एनवायरमेंट वैरिएबल के साथ कॉन्फ़िगरेशन उपलब्ध नहीं होता.

पैरामीटर वाला कॉन्फ़िगरेशन

Cloud Functions for Firebase, आपके कोड बेस में कॉन्फ़िगरेशन पैरामीटर को डिक्लेरेटिव तरीके से तय करने के लिए एक इंटरफ़ेस उपलब्ध कराता है. इन पैरामीटर की वैल्यू, फ़ंक्शन को डिप्लॉय करने के दौरान उपलब्ध होती है. ऐसा तब होता है, जब डिप्लॉयमेंट और रनटाइम के विकल्प सेट किए जाते हैं. साथ ही, फ़ंक्शन को एक्ज़ीक्यूट करने के दौरान भी यह वैल्यू उपलब्ध होती है. इसका मतलब है कि सीएलआई, डिप्लॉयमेंट को तब तक ब्लॉक करेगा, जब तक सभी पैरामीटर की वैल्यू मान्य न हो.

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

पैरामीटर वाले कॉन्फ़िगरेशन वैरिएबल के साथ किसी फ़ंक्शन को डिप्लॉय करते समय, Firebase CLI सबसे पहले लोकल .env फ़ाइलों से उनकी वैल्यू लोड करने की कोशिश करता है. अगर वे उन फ़ाइलों में मौजूद नहीं हैं और कोई default सेट नहीं है, तो सीएलआई, डिप्लॉयमेंट के दौरान वैल्यू के लिए प्रॉम्प्ट करेगा. इसके बाद, उनकी वैल्यू को आपकी functions/ डायरेक्ट्री में .env.<project_ID> नाम की .env फ़ाइल में अपने-आप सेव कर देगा:

$ 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() गलत है या नहीं.

सीएलआई के काम करने का तरीका कॉन्फ़िगर करना

पैरामीटर को Options ऑब्जेक्ट के साथ कॉन्फ़िगर किया जा सकता है. इससे यह कंट्रोल किया जाता है कि सीएलआई, वैल्यू के लिए कैसे प्रॉम्प्ट करेगा. यहां दिए गए उदाहरण में, फ़ोन नंबर के फ़ॉर्मैट की पुष्टि करने, चुनने का आसान विकल्प देने, और 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 से सीक्रेट भी इस्तेमाल किए जा सकते हैं. इन फ़ाइल टाइप का इस्तेमाल किया जा सकता है:

  • सीक्रेट
  • स्ट्रिंग
  • बूलियन
  • पूर्णांक
  • फ़्लोट
  • सूची (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) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

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

इसके अलावा, अगर आपको किसी पैरामीटर से तुलना करके यह जानना है कि कौनसा विकल्प चुनना है, तो वैल्यू की जांच करने के बजाय, पहले से मौजूद कंपैरेटर का इस्तेमाल करना होगा:

Node.js

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

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

Python

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

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

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

सिर्फ़ रनटाइम के दौरान इस्तेमाल किए जाने वाले पैरामीटर और पैरामीटर एक्सप्रेशन को उनके value फ़ंक्शन से ऐक्सेस किया जा सकता है:

Node.js

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

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import StringParam

WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

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

पहले से मौजूद पैरामीटर

Cloud Functions SDK में पहले से तय किए गए तीन पैरामीटर होते हैं. ये firebase-functions/params सबपैकेज में उपलब्ध होते हैं:

Node.js

  • projectID — वह क्लाउड प्रोजेक्ट जिसमें फ़ंक्शन चल रहा है.
  • databaseURL — फ़ंक्शन से जुड़े रीयलटाइम डेटाबेस इंस्टेंस का यूआरएल (अगर Firebase प्रोजेक्ट पर चालू है).
  • storageBucket — फ़ंक्शन से जुड़ी Cloud Storage बकेट (अगर Firebase प्रोजेक्ट पर चालू है).

Python

  • PROJECT_ID — वह क्लाउड प्रोजेक्ट जिसमें फ़ंक्शन चल रहा है.
  • DATABASE_URL — फ़ंक्शन से जुड़े रीयलटाइम डेटाबेस इंस्टेंस का यूआरएल (अगर Firebase प्रोजेक्ट पर चालू है).
  • STORAGE_BUCKET — फ़ंक्शन से जुड़ी Cloud Storage बकेट (अगर Firebase प्रोजेक्ट पर चालू है).

ये हर तरह से, उपयोगकर्ता की ओर से तय की गई स्ट्रिंग पैरामीटर की तरह काम करते हैं. हालांकि, इनकी वैल्यू Firebase CLI को हमेशा पता होती हैं. इसलिए, डिप्लॉयमेंट के दौरान इनकी वैल्यू के लिए कभी भी प्रॉम्प्ट नहीं किया जाएगा और न ही इन्हें .env फ़ाइलों में सेव किया जाएगा.

सीक्रेट पैरामीटर

Secret टाइप के पैरामीटर, defineSecret() का इस्तेमाल करके तय किए जाते हैं. ये स्ट्रिंग पैरामीटर दिखाते हैं, जिनकी वैल्यू Cloud Secret Manager में सेव होती है. सीक्रेट पैरामीटर, Cloud Secret Manager में मौजूद वैल्यू की जांच करते हैं. साथ ही, डिप्लॉयमेंट के दौरान नए सीक्रेट की वैल्यू के लिए इंटरैक्टिव तरीके से प्रॉम्प्ट करते हैं. ऐसा इसलिए, क्योंकि लोकल .env फ़ाइल में वैल्यू की जांच करने और वैल्यू मौजूद न होने पर, फ़ाइल में नई वैल्यू लिखने की ज़रूरत नहीं होती.

सीक्रेट पैरामीटर को उन अलग-अलग फ़ंक्शन से बाउंड किया जाना चाहिए जिनके पास उनका ऐक्सेस होना चाहिए:

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

सीक्रेट की वैल्यू, फ़ंक्शन के लागू होने तक छिपी रहती हैं. इसलिए, फ़ंक्शन को कॉन्फ़िगर करते समय उनका इस्तेमाल नहीं किया जा सकता.

स्ट्रक्चर्ड JSON सीक्रेट

अगर आपके पास कॉन्फ़िगरेशन की कई वैल्यू हैं जो लॉजिकल तौर पर एक-दूसरे से जुड़ी हैं (उदाहरण के लिए, तीसरे पक्ष की सेवा की सेटिंग), तो उन्हें defineJsonSecret() का इस्तेमाल करके, एक ही सीक्रेट में स्ट्रक्चर्ड JSON ऑब्जेक्ट के तौर पर एक साथ सेव किया जा सकता है. इस तरीके से, कॉन्फ़िगरेशन को व्यवस्थित करने में मदद मिल सकती है. साथ ही, Cloud Secret Manager के फ़्री टियर का ज़्यादा बेहतर तरीके से इस्तेमाल किया जा सकता है. इसके लिए, कॉन्फ़िगरेशन की मिलती-जुलती वैल्यू के ग्रुप को एक ही सीक्रेट में सेव करें.

Secret Manager में सेव की गई वैल्यू, मान्य JSON स्ट्रिंग होनी चाहिए. .value() को ऐक्सेस करने पर, SDK टूल अपने-आप 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 सीक्रेट बनाने के लिए, आपको Secret Manager में इसकी वैल्यू को 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. अपनी functions/ डायरेक्ट्री में .env फ़ाइल बनाएं:

    # 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 प्रोजेक्ट के लिए एनवायरमेंट वैरिएबल का कोई दूसरा सेट चाहिए (जैसे, स्टेजिंग बनाम प्रोडक्शन), तो .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 फ़ाइलों में सेव किए गए एनवायरमेंट वैरिएबल का इस्तेमाल, फ़ंक्शन कॉन्फ़िगरेशन के लिए किया जा सकता है. हालांकि, आपको इन्हें संवेदनशील जानकारी सेव करने का सुरक्षित तरीका नहीं मानना चाहिए. जैसे, डेटाबेस क्रेडेंशियल या एपीआई पासकोड. अगर आपको सोर्स कंट्रोल में अपनी .env फ़ाइलों की जांच करनी है, तो यह खास तौर पर ज़रूरी है.

संवेदनशील कॉन्फ़िगरेशन जानकारी को स्टोर करने में आपकी मदद करने के लिए, Cloud Functions for Firebase को Google Cloud Secret Manager के साथ इंटिग्रेट किया गया है. एन्क्रिप्ट यानी सुरक्षित की गई यह सेवा, कॉन्फ़िगरेशन वैल्यू को सुरक्षित तरीके से सेव करती है. साथ ही, ज़रूरत पड़ने पर आपके फ़ंक्शन से आसानी से ऐक्सेस करने की सुविधा देती है.

सीक्रेट बनाना और उसका इस्तेमाल करना

सीक्रेट बनाने के लिए, Firebase सीएलआई का इस्तेमाल करें.

सीक्रेट बनाने और उसका इस्तेमाल करने के लिए:

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

    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

    अब इसे किसी भी अन्य एनवायरमेंट वैरिएबल की तरह ऐक्सेस किया जा सकेगा. इसके उलट, अगर कोई दूसरा फ़ंक्शन सीक्रेट को ऐक्सेस करने की कोशिश करता है, तो उसे एक ऐसी वैल्यू मिलती है जो तय नहीं है:

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

    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.
    

फ़ंक्शन डिप्लॉय होने के बाद, उसके पास सीक्रेट वैल्यू का ऐक्सेस होगा. सिर्फ़ उन फ़ंक्शन के पास एनवायरमेंट वैरिएबल के तौर पर सीक्रेट का ऐक्सेस होगा जिनमें secrets विकल्प में सीक्रेट शामिल किया गया है. इससे आपको यह पक्का करने में मदद मिलती है कि सीक्रेट वैल्यू सिर्फ़ वहां उपलब्ध हों जहां उनकी ज़रूरत है. इससे, गलती से किसी सीक्रेट के लीक होने का जोखिम कम हो जाता है.

सीक्रेट मैनेज करना

अपने सीक्रेट मैनेज करने के लिए, Firebase सीएलआई का इस्तेमाल करें. इस तरह से सीक्रेट मैनेज करते समय, ध्यान रखें कि सीएलआई में किए गए कुछ बदलावों के लिए, आपको उनसे जुड़े फ़ंक्शन में बदलाव करना पड़ सकता है और/या उन्हें फिर से डिप्लॉय करना पड़ सकता है. खास तौर पर:

  • जब भी किसी सीक्रेट के लिए नई वैल्यू सेट की जाती है, तो आपको उन सभी फ़ंक्शन को फिर से डिप्लॉय करना होगा जो उस सीक्रेट का रेफ़रंस देते हैं. इससे वे फ़ंक्शन, नई वैल्यू को चुन पाएंगे.
  • अगर किसी सीक्रेट को मिटाया जाता है, तो पक्का करें कि डिप्लॉय किए गए किसी भी फ़ंक्शन में उस सीक्रेट का रेफ़रंस न हो. मिटाए गए सीक्रेट वैल्यू का इस्तेमाल करने वाले फ़ंक्शन, बिना किसी सूचना के काम करना बंद कर देंगे.

सीक्रेट मैनेज करने के लिए, 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 सीएलआई, इस्तेमाल नहीं किए जा रहे सीक्रेट वर्शन को अपने-आप मिटाने की कोशिश करता है. ऐसा तब होता है, जब सीक्रेट के नए वर्शन के साथ फ़ंक्शन डिप्लॉय किए जाते हैं. इसके अलावा, functions:secrets:destroy और functions:secrets:prune का इस्तेमाल करके, इस्तेमाल न किए गए सीक्रेट को मिटाया जा सकता है.

Secret Manager, किसी सीक्रेट पर हर महीने 10,000 बार बिना बिल वाले ऐक्सेस ऑपरेशन की अनुमति देता है. फ़ंक्शन इंस्टेंस, हर बार कोल्ड स्टार्ट होने पर सिर्फ़ उन सीक्रेट को पढ़ते हैं जो उनके secrets विकल्प में बताए गए हैं. अगर आपके पास कई फ़ंक्शन इंस्टेंस हैं, जो कई सीक्रेट को ऐक्सेस करते हैं, तो हो सकता है कि आपका प्रोजेक्ट इस सीमा को पार कर जाए. ऐसा होने पर, आपसे हर 10,000 ऐक्सेस ऑपरेशन के लिए 0.03 डॉलर लिए जाएंगे.

ज़्यादा जानकारी के लिए, 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 एम्युलेटर, सीक्रेट का इस्तेमाल करने की सुविधा देता है. इससे कॉन्फ़िगरेशन की संवेदनशील जानकारी को सेव और ऐक्सेस किया जा सकता है. डिफ़ॉल्ट रूप से, एम्युलेटर ऐप्लिकेशन के डिफ़ॉल्ट क्रेडेंशियल का इस्तेमाल करके, आपके प्रोडक्शन सीक्रेट को ऐक्सेस करने की कोशिश करेगा. सीआई एनवायरमेंट जैसी कुछ स्थितियों में, एम्युलेटर अनुमति से जुड़ी पाबंदियों की वजह से, सीक्रेट वैल्यू को ऐक्सेस नहीं कर पाता.

एनवायरमेंट वैरिएबल के लिए Cloud Functions एम्युलेटर की तरह ही, .secret.local फ़ाइल सेट अप करके सीक्रेट वैल्यू को बदला जा सकता है. इससे आपको अपने फ़ंक्शन को स्थानीय तौर पर टेस्ट करने में आसानी होती है. खास तौर पर, तब जब आपके पास सीक्रेट वैल्यू का ऐक्सेस न हो.

रनटाइम कॉन्फ़िगरेशन से माइग्रेट करना

functions.config API को बंद कर दिया गया है. इसे मार्च 2027 में पूरी तरह से बंद कर दिया जाएगा. इस तारीख के बाद, functions.config का इस्तेमाल करके डिप्लॉयमेंट नहीं किए जा सकेंगे.

डिप्लॉयमेंट में होने वाली गड़बड़ियों को रोकने के लिए, Firebase सीएलआई का इस्तेमाल करके अपने कॉन्फ़िगरेशन को Cloud Secret Manager पर माइग्रेट करें. हमारा सुझाव है कि आप इस तरीके का इस्तेमाल करें. यह आपके कॉन्फ़िगरेशन को माइग्रेट करने का सबसे असरदार और सुरक्षित तरीका है.

  1. Firebase सीएलआई की मदद से कॉन्फ़िगरेशन एक्सपोर्ट करना

    अपने मौजूदा एनवायरमेंट कॉन्फ़िगरेशन को Cloud Secret Manager में नए सीक्रेट के तौर पर एक्सपोर्ट करने के लिए, config export कमांड का इस्तेमाल करें:

    $ 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 एपीआई का इस्तेमाल करें. यह भी पक्का करें कि सीक्रेट, उन सभी फ़ंक्शन से जुड़े हों जिन्हें उनकी ज़रूरत है.

    पहले

    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 को बिना किसी आर्ग्युमेंट के शुरू किया जाता है. अगर JavaScript में फ़ंक्शन लिखे जा रहे हैं, तो इस तरह शुरू करें:

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

अगर आपको सेवा खाते के क्रेडेंशियल का इस्तेमाल करके, डिफ़ॉल्ट प्रोजेक्ट कॉन्फ़िगरेशन के साथ Admin SDK टूल को शुरू करना है, तो किसी फ़ाइल से क्रेडेंशियल लोड करके उन्हें FIREBASE_CONFIG में इस तरह जोड़ा जा सकता है:

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

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