Configura tu entorno


A menudo necesitarás una configuración adicional para tus funciones, como claves API de terceros o configuraciones ajustables. El SDK de Firebase para Cloud Functions ofrece una configuración de entorno integrada para facilitar el almacenamiento y la recuperación de este tipo de datos para su proyecto.

Puedes elegir entre tres opciones:

  • Configuración parametrizada (recomendada para la mayoría de escenarios). Esto proporciona una configuración de entorno fuertemente tipada con parámetros que se validan en el momento de la implementación, lo que evita errores y simplifica la depuración.
  • Configuración basada en archivos de variables de entorno . Con este enfoque, crea manualmente un archivo dotenv para cargar variables de entorno.
  • Configuración del entorno de ejecución con Firebase CLI y functions.config (solo Cloud Functions (1.ª generación)).

Para la mayoría de los casos de uso, se recomienda la configuración parametrizada. Este enfoque hace que los valores de configuración estén disponibles tanto en tiempo de ejecución como en tiempo de implementación, y la implementación se bloquea a menos que todos los parámetros tengan un valor válido. Por el contrario, la configuración con variables de entorno no está disponible en el momento de la implementación.

Configuración parametrizada

Cloud Functions para Firebase proporciona una interfaz para definir parámetros de configuración de forma declarativa dentro de su código base. El valor de estos parámetros está disponible tanto durante la implementación de la función, al configurar las opciones de implementación y tiempo de ejecución, como durante la ejecución. Esto significa que la CLI bloqueará la implementación a menos que todos los parámetros tengan un valor válido.

Para definir parámetros en su código, siga este modelo:

const functions = require('firebase-functions');
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.`);
  }
);

Al implementar una función con variables de configuración parametrizadas, Firebase CLI primero intenta cargar sus valores desde archivos .env locales. Si no están presentes en esos archivos y no se establece ningún valor default , la CLI solicitará los valores durante la implementación y luego guardará automáticamente sus valores en un archivo .env llamado .env.<project_ID> en su directorio 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

Dependiendo de su flujo de trabajo de desarrollo, puede resultar útil agregar el archivo .env.<project_ID> generado al control de versiones.

Configurar el comportamiento de la CLI

Los parámetros se pueden configurar con un objeto Options que controla cómo la CLI solicitará valores. El siguiente ejemplo establece opciones para validar el formato de un número de teléfono, proporcionar una opción de selección simple y completar una opción de selección automáticamente desde el proyecto de 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"})

Tipos de parámetros

La configuración parametrizada proporciona una escritura segura para los valores de los parámetros y también admite secretos de Cloud Secret Manager. Los tipos admitidos son:

  • Secreto
  • Cadena
  • Booleano
  • Entero
  • Flotar

Valores de parámetros y expresiones.

Firebase evalúa sus parámetros tanto en el momento de la implementación como mientras se ejecuta su función. Debido a estos entornos duales, se debe tener especial cuidado al comparar los valores de los parámetros y al usarlos para configurar las opciones de tiempo de ejecución para sus funciones.

Para pasar un parámetro a su función como una opción de tiempo de ejecución, páselo directamente:

const functions = require('firebase-functions');
const { defineInt} = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');

export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
  (req, res) => {
    //…

Además, si necesita comparar con un parámetro para saber qué opción elegir, deberá usar comparadores integrados en lugar de verificar el valor:

const functions = require('firebase-functions');
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) => {
    //…

Se puede acceder a los parámetros y expresiones de parámetros que solo se usan en tiempo de ejecución con su función value :

const functions = require('firebase-functions');
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.`);
  }
);

Parámetros incorporados

El SDK de Cloud Functions ofrece tres parámetros predefinidos, disponibles en el subpaquete firebase-functions/params :

  • projectID : el proyecto de nube en el que se ejecuta la función.
  • databaseURL : la URL de la instancia de Realtime Database asociada con la función (si está habilitada en el proyecto de Firebase).
  • storageBucket : el depósito de Cloud Storage asociado con la función (si está habilitado en el proyecto de Firebase).

Estos funcionan como parámetros de cadena definidos por el usuario en todos los aspectos, excepto que, dado que Firebase CLI siempre conoce sus valores, sus valores nunca se solicitarán durante la implementación ni se guardarán en archivos .env .

Parámetros secretos

Los parámetros de tipo Secret , definidos mediante defineSecret() , representan parámetros de cadena que tienen un valor almacenado en Cloud Secret Manager. En lugar de compararlo con un archivo .env local y escribir un nuevo valor en el archivo si falta, los parámetros secretos verifican su existencia en Cloud Secret Manager y solicitan interactivamente el valor de un nuevo secreto durante la implementación.

Los parámetros secretos definidos de esta manera deben estar vinculados a funciones individuales que deberían tener acceso a ellos:

const functions = require('firebase-functions');
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();
    //…

Debido a que los valores de los secretos están ocultos hasta la ejecución de la función, no puede usarlos mientras configura su función.

Variables de entorno

Cloud Functions para Firebase admite el formato de archivo dotenv para cargar variables de entorno especificadas en un archivo .env en el tiempo de ejecución de su aplicación. Una vez implementadas, las variables de entorno se pueden leer a través de la interfaz process.env .

Para configurar su entorno de esta manera, cree un archivo .env en su proyecto, agregue las variables deseadas e implemente:

  1. Cree un archivo .env en su directorio functions/ :

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Abra el archivo .env para editarlo y agregue las claves deseadas. Por ejemplo:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Implemente funciones y verifique que se hayan cargado las variables de entorno:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

Una vez que se implementan sus variables de entorno personalizadas, su código de función puede acceder a ellas con la sintaxis 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}`);
});

Implementar múltiples conjuntos de variables de entorno

Si necesita un conjunto alternativo de variables de entorno para sus proyectos de Firebase (como ensayo o producción), cree un .env. <project or alias > y escriba allí las variables de entorno específicas del proyecto. Las variables de entorno de .env archivos .env y específicos del proyecto (si existen) se incluirán en todas las funciones implementadas.

Por ejemplo, un proyecto podría incluir estos tres archivos que contienen valores ligeramente diferentes para desarrollo y producción:

.env .env.dev .env.prod
PLANETA=Tierra

AUDIENCIA=Humanos

AUDIENCIA=Desarrolladores humanos AUDIENCIA=Prod humanos

Dados los valores en esos archivos separados, el conjunto de variables de entorno implementadas con sus funciones variará según su proyecto de destino:

$ 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

Variables de entorno reservadas

Algunas claves de variables de entorno están reservadas para uso interno. No utilice ninguna de estas claves en sus archivos .env :

  • Todas las claves que comienzan con X_GOOGLE_
  • Todas las claves que comienzan con EXT_
  • Todas las claves que comienzan con FIREBASE_
  • Cualquier clave de la siguiente lista:
  • NUBE_RUNTIME_CONFIG
  • PUNTO DE ENTRADA
  • GCP_PROJECT
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • NOMBRE DE LA FUNCIÓN
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCIÓN_IDENTIDAD
  • FUNCTION_REGION
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICIO
  • K_REVISION
  • PUERTO
  • K_CONFIGURACIÓN

Almacene y acceda a información de configuración confidencial

Las variables de entorno almacenadas en archivos .env se pueden utilizar para la configuración de funciones, pero no debe considerarlas una forma segura de almacenar información confidencial, como credenciales de bases de datos o claves API. Esto es especialmente importante si verifica sus archivos .env en el control de fuente.

Para ayudarlo a almacenar información de configuración confidencial, Cloud Functions para Firebase se integra con Google Cloud Secret Manager . Este servicio cifrado almacena los valores de configuración de forma segura y, al mismo tiempo, permite un fácil acceso desde sus funciones cuando sea necesario.

Crear y usar un secreto

Para crear un secreto, use Firebase CLI.

Para crear y utilizar un secreto:

  1. Desde la raíz del directorio de su proyecto local, ejecute el siguiente comando:

    firebase functions:secrets:set SECRET_NAME

  2. Introduzca un valor para SECRET_NAME .

    La CLI muestra un mensaje de éxito y advierte que debe implementar funciones para que el cambio surta efecto.

  3. Antes de implementar, asegúrese de que su código de funciones permita que la función acceda al secreto utilizando el parámetro 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
      });
  4. Implementar funciones en la nube:

    firebase deploy --only functions

Ahora podrá acceder a él como a cualquier otra variable de entorno. Por el contrario, si otra función que no especifica el secreto en runWith intenta acceder al secreto, recibe un valor indefinido:

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

Una vez implementada su función, tendrá acceso al valor secreto. Sólo las funciones que incluyen específicamente un secreto en su parámetro runWith tendrán acceso a ese secreto como variable de entorno. Esto le ayuda a asegurarse de que los valores secretos solo estén disponibles cuando sean necesarios, lo que reduce el riesgo de filtrar un secreto accidentalmente.

Manejando secretos

Utilice Firebase CLI para administrar sus secretos. Al administrar secretos de esta manera, tenga en cuenta que algunos cambios de CLI requieren que modifique y/o vuelva a implementar funciones asociadas. Específicamente:

  • Siempre que establezca un nuevo valor para un secreto, debe volver a implementar todas las funciones que hacen referencia a ese secreto para que recojan el valor más reciente.
  • Si elimina un secreto, asegúrese de que ninguna de las funciones implementadas haga referencia a ese secreto. Las funciones que utilizan un valor secreto que se ha eliminado fallarán silenciosamente.

A continuación se muestra un resumen de los comandos de Firebase CLI para la administración de secretos:

# 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

Para los comandos access y destroy , puede proporcionar el parámetro de versión opcional para administrar una versión particular. Por ejemplo:

functions:secrets:access SECRET_NAME[@VERSION]

Para obtener más información sobre estas operaciones, pase -h con el comando para ver la ayuda de CLI.

Cómo se facturan los secretos

Secret Manager permite 6 versiones secretas activas sin costo. Esto significa que puedes tener 6 secretos por mes en un proyecto de Firebase sin costo alguno.

De forma predeterminada, Firebase CLI intenta destruir automáticamente las versiones secretas no utilizadas cuando corresponde, como cuando implementas funciones con una nueva versión del secreto. Además, puede limpiar activamente los secretos no utilizados utilizando functions:secrets:destroy y functions:secrets:prune .

Secret Manager permite 10.000 operaciones de acceso mensuales no facturadas a un secreto. Las instancias de función leen solo los secretos especificados en su parámetro runWith cada vez que se inician en frío. Si tiene muchas instancias de funciones que leen muchos secretos, su proyecto puede exceder esta asignación, momento en el que se le cobrarán $0,03 por cada 10 000 operaciones de acceso.

Para obtener más información, consulte Precios de Secret Manager .

Soporte de emulador

La configuración del entorno con dotenv está diseñada para interoperar con un emulador local de Cloud Functions .

Cuando utiliza un emulador local de Cloud Functions, puede anular las variables de entorno de su proyecto configurando un archivo .env.local . El contenido de .env.local tiene prioridad sobre .env y el archivo .env específico del proyecto.

Por ejemplo, un proyecto podría incluir estos tres archivos que contienen valores ligeramente diferentes para el desarrollo y las pruebas locales:

.env .env.dev .env.local
PLANETA=Tierra

AUDIENCIA=Humanos

AUDIENCIA=Desarrolladores humanos AUDIENCIA = Humanos locales

Cuando se inicia en el contexto local, el emulador carga las variables de entorno como se muestra:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

Secretos y credenciales en el emulador de Cloud Functions

El emulador de Cloud Functions admite el uso de secretos para almacenar y acceder a información de configuración confidencial . De forma predeterminada, el emulador intentará acceder a sus secretos de producción utilizando las credenciales predeterminadas de la aplicación . En determinadas situaciones, como entornos de CI, es posible que el emulador no pueda acceder a valores secretos debido a restricciones de permisos.

De manera similar a la compatibilidad del emulador de Cloud Functions con variables de entorno, puede anular los valores secretos configurando un archivo .secret.local . Esto le facilita probar sus funciones localmente, especialmente si no tiene acceso al valor secreto.

Migrar desde la configuración del entorno

Si ha estado utilizando la configuración del entorno con functions.config , puede migrar su configuración existente como variables de entorno (en formato dotenv ). Firebase CLI proporciona un comando de exportación que genera la configuración de cada alias o proyecto enumerado en el archivo .firebaserc de su directorio (en el siguiente ejemplo, local , dev y prod ) como archivos .env .

Para migrar, exporte las configuraciones de su entorno existente usando el comando 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

Tenga en cuenta que, en algunos casos, se le pedirá que ingrese un prefijo para cambiar el nombre de las claves de las variables de entorno exportadas. Esto se debe a que no todas las configuraciones se pueden transformar automáticamente, ya que pueden no ser válidas o pueden ser una clave de variable de entorno reservada .

Le recomendamos que revise cuidadosamente el contenido de los archivos .env generados antes de implementar sus funciones o verificar los archivos .env en el control de código fuente. Si algún valor es confidencial y no debe filtrarse, elimínelo de sus archivos .env y guárdelo de forma segura en Secret Manager .

También necesitarás actualizar tu código de funciones. Cualquier función que use functions.config ahora deberá usar process.env en su lugar, como se muestra en Actualizar a 2.ª generación .

Configuración del entorno

Antes de que se lanzara la compatibilidad con variables de entorno en firebase-functions v3.18.0 , usar functions.config() era el enfoque recomendado para la configuración del entorno. Este enfoque todavía es compatible, pero recomendamos que todos los proyectos nuevos utilicen variables de entorno, ya que son más sencillas de usar y mejoran la portabilidad de su código.

Establecer la configuración del entorno con la CLI

Para almacenar datos del entorno, puede usar el comando firebase functions:config:set en Firebase CLI . Cada clave puede tener un espacio de nombres utilizando puntos para agrupar la configuración relacionada. Tenga en cuenta que en las claves sólo se aceptan caracteres en minúscula ; No se permiten caracteres en mayúsculas.

Por ejemplo, para almacenar el ID de cliente y la clave API para "Algunos servicios", puede ejecutar:

firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"

Recuperar la configuración del entorno actual

Para inspeccionar lo que está actualmente almacenado en la configuración del entorno de su proyecto, puede usar firebase functions:config:get . Generará JSON algo como esto:

{
  "someservice": {
    "key":"THE API KEY",
    "id":"THE CLIENT ID"
  }
}

Esta funcionalidad se basa en la API de configuración de Google Cloud Runtime .

Utilice functions.config para acceder a la configuración del entorno en una función

Algunas configuraciones se proporcionan automáticamente en el espacio de nombres reservado firebase . La configuración del entorno está disponible dentro de su función en ejecución a través de functions.config() . Para utilizar la configuración anterior, su código podría verse así:

const functions = require('firebase-functions');
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}
  });
});

Utilice la configuración del entorno para inicializar un módulo

Algunos módulos de Node están listos sin ninguna configuración. Otros módulos necesitan configuración adicional para inicializarse correctamente. Le recomendamos almacenar esta configuración en variables de configuración del entorno en lugar de codificarla. Esto le ayuda a mantener su código mucho más portátil, lo que le permite abrir el código fuente de su aplicación o cambiar fácilmente entre las versiones de producción y de prueba.

Por ejemplo, para utilizar el módulo SDK de Slack Node , puedes escribir esto:

const functions = require('firebase-functions');
const IncomingWebhook = require('@slack/client').IncomingWebhook;
const webhook = new IncomingWebhook(functions.config().slack.url);

Antes de la implementación, configure la variable de configuración de entorno slack.url :

firebase functions:config:set slack.url=https://hooks.slack.com/services/XXX

Comandos ambientales adicionales

  • firebase functions:config:unset key1 key2 elimina las claves especificadas de la configuración
  • firebase functions:config:clone --from <fromProject> clona el entorno de otro proyecto en el proyecto actualmente activo.

Variables de entorno completadas automáticamente

Hay variables de entorno que se completan automáticamente en el tiempo de ejecución de funciones y en funciones emuladas localmente. Estos incluyen aquellos completados por Google Cloud , así como una variable de entorno específica de Firebase:

process.env.FIREBASE_CONFIG : proporciona la siguiente información de configuración del proyecto Firebase:

{
  databaseURL: 'https://databaseName.firebaseio.com',
  storageBucket: 'projectId.appspot.com',
  projectId: 'projectId'
}

Esta configuración se aplica automáticamente cuando inicializas el SDK de Firebase Admin sin argumentos. Si está escribiendo funciones en JavaScript, inicialícelas así:

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

Si está escribiendo funciones en TypeScript, inicialícelas así:

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

Si necesita inicializar el SDK de administración con la configuración predeterminada del proyecto usando las credenciales de la cuenta de servicio, puede cargar las credenciales desde un archivo y agregarlas a FIREBASE_CONFIG de esta manera:

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

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