Часто для ваших функций требуется дополнительная настройка, например, сторонние API-ключи или настраиваемые параметры. Firebase SDK для Cloud Functions предлагает встроенную настройку среды, упрощающую хранение и извлечение таких данных для вашего проекта.
Вы можете выбрать один из следующих вариантов:
- Параметризованная конфигурация (рекомендуется для большинства сценариев). Она обеспечивает строго типизированную конфигурацию среды с параметрами, которые проверяются при развертывании, что предотвращает ошибки и упрощает отладку.
- Файловая конфигурация переменных окружения . При таком подходе вы вручную создаёте файл dotenv для загрузки переменных окружения.
В большинстве случаев рекомендуется параметризованная конфигурация. Такой подход делает значения конфигурации доступными как во время выполнения, так и во время развёртывания, и развёртывание блокируется, если все параметры не имеют допустимых значений. Напротив, конфигурация с переменными окружения недоступна во время развёртывания.
Параметризованная конфигурация
Cloud Functions for Firebase предоставляет интерфейс для декларативного определения параметров конфигурации внутри кодовой базы. Значения этих параметров доступны как во время развёртывания функции, так и при настройке параметров развёртывания и выполнения, а также во время выполнения. Это означает, что CLI заблокирует развёртывание, если все параметры не имеют допустимых значений.
Чтобы определить параметры в вашем коде, следуйте этой модели:
const functions = require('firebase-functions/v1');
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 = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
res.send(`${welcomeMessage.value()}! I am a function.`);
}
);
При развёртывании функции с параметризованными переменными конфигурации Firebase CLI сначала пытается загрузить их значения из локальных файлов .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()
. Этот обратный вызов выполняется до запуска любых функций в рабочей среде, но не вызывается во время развёртывания, поэтому он является безопасным способом доступа к значению параметра.
const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v1');
const apiKey = defineSecret('GOOGLE_API_KEY');
let genAI;
onInit(() => {
genAI = new GoogleGenerativeAI(apiKey.value());
})
Настроить поведение CLI
Параметры можно настроить с помощью объекта Options
, который управляет тем, как CLI будет запрашивать значения. В следующем примере задаются параметры для проверки формата номера телефона, предоставления простого варианта выбора и автоматического заполнения варианта выбора из проекта Firebase:
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: {select: {options:
[{value: "odd"}, {value: "even"}]}}})
const storageBucket = defineString('BUCKET', {input: {resource: {type:
"storage.googleapis.com/Bucket"}}, description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets"})
Типы параметров
Параметризованная конфигурация обеспечивает строгую типизацию значений параметров, а также поддерживает секреты из Cloud Secret Manager. Поддерживаются следующие типы:
- Секрет
- Нить
- Булевое значение
- Целое число
- Плавать
Значения параметров и выражения
Firebase оценивает ваши параметры как во время развёртывания, так и во время выполнения функции. В связи с наличием этих двух сред необходимо соблюдать особую осторожность при сравнении значений параметров и их использовании для настройки параметров времени выполнения функций.
Чтобы передать параметр вашей функции как параметр времени выполнения, передайте его напрямую:
const functions = require('firebase-functions/v1');
const { defineInt} = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
//…
Кроме того, если вам нужно сравнить с параметром, чтобы узнать, какой вариант выбрать, вам нужно будет использовать встроенные компараторы вместо проверки значения:
const functions = require('firebase-functions/v1');
const { defineBool } = require('firebase-functions/params');
const environment = params.defineString(‘ENVIRONMENT’, {default: ‘dev’});
// use built-in comparators
const minInstancesConfig =environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
(req, res) => {
//…
Доступ к параметрам и выражениям параметров, которые используются только во время выполнения, можно получить с помощью их функции value
:
const functions = require('firebase-functions/v1');
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 = functions.https.onRequest(
(req, res) => {
res.send(`${welcomeMessage.value()}! I am a function.`);
}
);
Встроенные параметры
Cloud Functions SDK предлагает три предопределенных параметра, доступных из подпакета firebase-functions/params
:
-
projectID
— облачный проект, в котором запущена функция. -
databaseURL
— URL-адрес экземпляра базы данных реального времени, связанного с функцией (если включено в проекте Firebase). -
storageBucket
— контейнер облачного хранилища, связанный с функцией (если включен в проекте Firebase).
Они функционируют во всех отношениях как определяемые пользователем строковые параметры, за исключением того, что, поскольку их значения всегда известны Firebase CLI, их значения никогда не будут запрашиваться при развертывании или сохраняться в файлах .env
.
Секретные параметры
Параметры типа Secret
, определяемые с помощью defineSecret()
, представляют собой строковые параметры, значение которых хранится в Cloud Secret Manager. Вместо проверки по локальному файлу .env
и записи в него нового значения в случае его отсутствия, параметры Secret проверяются на наличие в Cloud Secret Manager и интерактивно запрашивают значение нового секрета во время развертывания.
Определенные таким образом секретные параметры должны быть привязаны к отдельным функциям, которые должны иметь к ним доступ:
const functions = require('firebase-functions/v1');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');
export const postToDiscord = functions.runWith({ secrets: [discordApiKey] }).https.onRequest(
(req, res) => {
const apiKey = discordApiKey.value();
//…
Поскольку значения секретов скрыты до выполнения функции, вы не можете использовать их при настройке функции.
Переменные среды
Cloud Functions for Firebase поддерживает формат файла dotenv для загрузки переменных окружения, указанных в файле .env
, в среду выполнения приложения. После развертывания переменные окружения можно читать через интерфейс process.env
.
Чтобы настроить среду таким образом, создайте файл .env
в своем проекте, добавьте необходимые переменные и выполните развертывание:
Создайте файл
.env
в каталогеfunctions/
:# Directory layout: # my-project/ # firebase.json # functions/ # .env # package.json # index.js
Откройте файл
.env
для редактирования и добавьте необходимые ключи. Например:PLANET=Earth AUDIENCE=Humans
Разверните функции и проверьте, что переменные среды загружены:
firebase deploy --only functions # ... # i functions: Loaded environment variables from .env. # ...
После развертывания ваших пользовательских переменных среды ваш код функции сможет получить к ним доступ с помощью синтаксиса process.env
:
// Responds with "Hello Earth and Humans"
exports.hello = functions.https.onRequest((request, response) => {
response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});
Развертывание нескольких наборов переменных среды
Если вам нужен альтернативный набор переменных окружения для ваших проектов Firebase (например, для стейджинга и производства), создайте файл .env. <project or alias >
и запишите в него переменные окружения, специфичные для проекта. Переменные окружения из файлов .env
и специфичных для проекта файлов .env
(если они есть) будут включены во все развёртываемые функции.
Например, проект может включать следующие три файла, содержащие немного разные значения для разработки и производства:
.env | .env.dev | .env.prod |
ПЛАНЕТА=Земля АУДИТОРИЯ=Люди | АУДИТОРИЯ=Разработчики | АУДИТОРИЯ=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_TARGET
- ТИП_ПОДПИСИ_ФУНКЦИИ
- K_SERVICE
- K_REVISION
- ПОРТ
- K_КОНФИГУРАЦИЯ
Хранить и получать доступ к конфиденциальной информации о конфигурации
Переменные среды, хранящиеся в файлах .env
можно использовать для настройки функций, но не следует считать их безопасным способом хранения конфиденциальной информации, такой как учётные данные базы данных или ключи API. Это особенно важно, если вы добавляете файлы .env
в систему контроля версий.
Для хранения конфиденциальной информации о конфигурации Cloud Functions for Firebase интегрируется с Google Cloud Secret Manager . Этот зашифрованный сервис безопасно хранит значения конфигурации, обеспечивая при этом лёгкий доступ к функциям при необходимости.
Создайте и используйте секрет
Чтобы создать секрет, используйте Firebase CLI.
Чтобы создать и использовать секрет:
Из корня локального каталога проекта выполните следующую команду:
firebase functions:secrets:set SECRET_NAME
Введите значение SECRET_NAME .
CLI выводит сообщение об успешном выполнении и предупреждает о необходимости развернуть функции, чтобы изменения вступили в силу.
Перед развертыванием убедитесь, что код вашей функции позволяет функции получать доступ к секрету с помощью параметра
runWith
:exports.processPayment = functions // Make the secret available to this function .runWith({ secrets: ["SECRET_NAME"] }) .onCall((data, context) => { const myBillingService = initializeBillingService( // reference the secret value process.env.SECRET_NAME ); // Process the payment });
Развертывание Cloud Functions :
firebase deploy --only functions
Теперь вы сможете получить к нему доступ, как к любой другой переменной окружения. И наоборот, если другая функция, не указывающая секрет в runWith
, попытается получить к нему доступ, она получит неопределённое значение:
exports.anotherEndpoint = functions.https.onRequest((request, response) => {
response.send(`The secret API key is ${process.env.SECRET_NAME}`);
// responds with "The secret API key is undefined" because the `runWith` parameter is missing
});
После развёртывания вашей функции она получит доступ к секретному значению. Только функции, которые специально включают секретное значение в параметр runWith
будут иметь доступ к этому секретному значению как к переменной окружения. Это поможет вам гарантировать, что секретные значения будут доступны только там, где они необходимы, и снизить риск случайной утечки секретного значения.
Управление секретами
Используйте Firebase CLI для управления секретами. При таком управлении секретами помните, что некоторые изменения в CLI требуют изменения и/или повторного развертывания связанных функций. В частности:
- Всякий раз, когда вы задаете новое значение для секрета, вы должны повторно развернуть все функции, которые ссылаются на этот секрет, чтобы они использовали последнее значение.
- Если вы удаляете секрет, убедитесь, что ни одна из развёрнутых функций не ссылается на него. Функции, использующие удалённое значение секрета, завершится сбоем без предупреждения.
Ниже приведен список команд Firebase CLI для управления секретами:
# Change the value of an existing secret firebase functions:secrets:set SECRET_NAME # View the value of a secret functions:secrets:access SECRET_NAME # Destroy a secret functions:secrets:destroy SECRET_NAME # View all secret versions and their state functions:secrets:get SECRET_NAME # Automatically clean up all secrets that aren't referenced by any of your functions functions:secrets:prune
Для команд access
и destroy
можно указать необязательный параметр версии для управления конкретной версией. Например:
functions:secrets:access SECRET_NAME[@VERSION]
Для получения дополнительных сведений об этих операциях передайте -h
команде для просмотра справки CLI.
Как выставляются счета за секреты
Secret Manager позволяет бесплатно поддерживать 6 активных версий секретов. Это означает, что вы можете бесплатно иметь 6 версий секретов в месяц в проекте Firebase.
По умолчанию Firebase CLI пытается автоматически удалять неиспользуемые версии секретов при необходимости, например, при развертывании функций с новой версией секрета. Кроме того, вы можете активно удалять неиспользуемые версии секретов с помощью functions:secrets:destroy
и functions:secrets:prune
.
Secret Manager допускает 10 000 ежемесячных неоплачиваемых операций доступа к секрету. Экземпляры функций считывают только те секреты, которые указаны в параметре runWith
при каждом холодном запуске. Если у вас много экземпляров функций, считывающих большое количество секретов, ваш проект может превысить это ограничение, и в этом случае с вас будет взиматься плата в размере 0,03 доллара США за 10 000 операций доступа.
Более подробную информацию можно найти в разделе Цены Secret Manager .
Поддержка эмулятора
Конфигурация среды с помощью dotenv предназначена для взаимодействия с локальным эмулятором Cloud Functions .
При использовании локального эмулятора Cloud Functions вы можете переопределить переменные окружения для своего проекта, настроив файл .env.local
. Содержимое .env.local
имеет приоритет над .env
и файлом .env
, специфичным для проекта.
Например, проект может включать эти три файла, содержащие немного разные значения для разработки и локального тестирования:
.env | .env.dev | .env.local |
ПЛАНЕТА=Земля АУДИТОРИЯ=Люди | АУДИТОРИЯ=Разработчики | АУДИТОРИЯ=Местные жители |
При запуске в локальном контексте эмулятор загружает переменные среды, как показано:
$ 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
, вы можете перенести существующую конфигурацию в виде переменных окружения (в формате dotenv ). Firebase CLI предоставляет команду экспорта, которая выводит конфигурацию каждого псевдонима или проекта, указанного в файле .firebaserc
вашего каталога (в примере ниже — local
, dev
и prod
), в виде файлов .env
.
Для миграции экспортируйте существующие конфигурации среды с помощью команды firebase functions:config:export
:
firebase functions:config:export i Importing configs from projects: [project-0, project-1] ⚠ The following configs keys could not be exported as environment variables: ⚠ project-0 (dev): 1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.) Enter a PREFIX to rename invalid environment variable keys: CONFIG\_ ✔ Wrote functions/.env.prod ✔ Wrote functions/.env.dev ✔ Wrote functions/.env.local ✔ Wrote functions/.env
Обратите внимание, что в некоторых случаях вам будет предложено ввести префикс для переименования экспортированных ключей переменных среды. Это связано с тем, что не все конфигурации могут быть преобразованы автоматически, поскольку они могут быть недействительными или представлять собой зарезервированный ключ переменной среды .
Мы рекомендуем внимательно проверять содержимое сгенерированных .env
файлов перед развертыванием функций или добавлением .env
файлов в систему контроля версий. Если какие-либо значения конфиденциальны и не должны быть раскрыты, удалите их из .env
файлов и сохраните в безопасном месте в Secret Manager .
Вам также потребуется обновить код функций. Теперь все функции, использующие functions.config
должны будут использовать process.env
, как показано в разделе «Обновление до версии 2-го поколения» .
Конфигурация среды
Настройка конфигурации среды с помощью CLI
Для хранения данных об окружении можно использовать команду firebase functions:config:set
в Firebase CLI . Для каждого ключа можно задать пространство имён, используя точки, чтобы сгруппировать связанные конфигурации. Имейте в виду, что в ключах допускаются только строчные символы ; заглавные символы не допускаются.
Например, чтобы сохранить идентификатор клиента и ключ API для «Some Service», вы можете выполнить:
firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"
Получить текущую конфигурацию среды
Чтобы проверить, что в данный момент хранится в конфигурации окружения вашего проекта, используйте firebase functions:config:get
. Она выведет JSON-код примерно такого вида:
{
"someservice": {
"key":"THE API KEY",
"id":"THE CLIENT ID"
}
}
Эта функциональность основана на API конфигурации Google Cloud Runtime .
Используйте functions.config
для доступа к конфигурации среды в функции
Часть конфигурации автоматически предоставляется в зарезервированном пространстве имён firebase
. Конфигурация среды доступна внутри вашей работающей функции через functions.config()
. Чтобы использовать указанную выше конфигурацию, ваш код может выглядеть следующим образом:
const functions = require('firebase-functions/v1');
const request = require('request-promise');
exports.userCreated = functions.database.ref('/users/{id}').onWrite(event => {
let email = event.data.child('email').val();
return request({
url: 'https://someservice.com/api/some/call',
headers: {
'X-Client-ID': functions.config().someservice.id,
'Authorization': `Bearer ${functions.config().someservice.key}`
},
body: {email: email}
});
});
Используйте конфигурацию среды для инициализации модуля
Некоторые модули Node готовы к использованию без какой-либо настройки. Другим модулям требуется дополнительная настройка для корректной инициализации. Мы рекомендуем хранить эту конфигурацию в переменных конфигурации среды, а не задавать её жёстко. Это помогает сделать код гораздо более портативным, что позволяет открывать исходный код приложения или легко переключаться между рабочей и тестовой версиями.
Например, чтобы использовать модуль Slack Node SDK , вы можете написать следующее:
const functions = require('firebase-functions/v1');
const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(functions.config().slack.url);
Перед развертыванием настройте переменную конфигурации среды slack.url
:
firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX
Дополнительные команды среды
-
firebase functions:config:unset key1 key2
удаляет указанные ключи из конфигурации -
firebase functions:config:clone --from <fromProject>
клонирует среду другого проекта в текущий активный проект.
Автоматически заполненные переменные среды
Существуют переменные окружения, которые автоматически заполняются в среде выполнения функций и в локально эмулируемых функциях. К ним относятся переменные, заполняемые 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);