Configurer votre environnement


Vos fonctions nécessitent souvent une configuration supplémentaire, telle que des clés API tierces ou des paramètres ajustables. Le SDK Firebase pour Cloud Functions offre une configuration d'environnement intégrée pour faciliter le stockage et la récupération de ce type de données pour votre projet.

Vous avez le choix entre trois options:

  • Configuration paramétrée (recommandée dans la plupart des scénarios). Vous obtenez ainsi une configuration d'environnement très typée avec des paramètres validés au moment du déploiement, ce qui évite les erreurs et simplifie le débogage.
  • Configuration basée sur les fichiers de variables d'environnement. Avec cette approche, vous créez manuellement un fichier dotenv pour charger des variables d'environnement.
  • Configuration de l'environnement d'exécution avec la CLI Firebase et functions.config (Cloud Functions (1re génération) uniquement).

Dans la plupart des cas d'utilisation, une configuration paramétrée est recommandée. Avec cette approche, les valeurs de configuration sont disponibles à la fois au moment de l'exécution et du déploiement. Le déploiement est bloqué, sauf si tous les paramètres ont une valeur valide. À l'inverse, la configuration avec des variables d'environnement n'est pas disponible au moment du déploiement.

Configuration paramétrée

Cloud Functions for Firebase fournit une interface permettant de définir des paramètres de configuration de manière déclarative dans votre codebase. La valeur de ces paramètres est disponible pendant le déploiement de la fonction, lors de la définition des options de déploiement et d'exécution, et pendant l'exécution. Cela signifie que la CLI bloquera le déploiement sauf si tous les paramètres ont une valeur valide.

Pour définir des paramètres dans votre code, procédez comme suit:

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

Lors du déploiement d'une fonction avec des variables de configuration paramétrées, la CLI Firebase tente d'abord de charger ses valeurs à partir des fichiers .env locaux. Si elles ne sont pas présentes dans ces fichiers et qu'aucun default n'est défini, la CLI vous demandera les valeurs lors du déploiement, puis les enregistrera automatiquement dans un fichier .env nommé .env.<project_ID> du répertoire 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

En fonction de votre workflow de développement, il peut être utile d'ajouter le fichier .env.<project_ID> généré au contrôle des versions.

Configurer le comportement de la CLI

Les paramètres peuvent être configurés avec un objet Options qui contrôle la manière dont la CLI demandera les valeurs. L'exemple suivant définit des options pour valider le format d'un numéro de téléphone, fournir une option de sélection simple et renseigner automatiquement une option de sélection à partir du projet 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"})

Types de paramètre

La configuration paramétrée fournit un typage fort pour les valeurs de paramètre et est également compatible avec les secrets de Cloud Secret Manager. Les types compatibles sont les suivants:

  • Secret
  • Chaîne
  • Booléen
  • Entier
  • Nombre à virgule flottante

Valeurs et expressions de paramètres

Firebase évalue vos paramètres au moment du déploiement et pendant l'exécution de votre fonction. En raison de ces environnements doubles, une attention particulière doit être portée lorsque vous comparez les valeurs de paramètres et lorsque vous les utilisez pour définir des options d'exécution pour vos fonctions.

Pour transmettre un paramètre à votre fonction en tant qu'option d'exécution, transmettez-le directement:

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) => {
    //…

En outre, si vous devez effectuer une comparaison avec un paramètre pour savoir quelle option choisir, vous devez utiliser des comparateurs intégrés au lieu de vérifier la valeur:

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) => {
    //…

Les paramètres et expressions de paramètres utilisés uniquement au moment de l'exécution sont accessibles avec leur fonction 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.`);
  }
);

Paramètres intégrés

Le SDK Cloud Functions propose trois paramètres prédéfinis, disponibles dans le sous-package firebase-functions/params:

  • projectID : projet Cloud dans lequel la fonction s'exécute.
  • databaseURL : URL de l'instance Realtime Database associée à la fonction (si elle est activée dans le projet Firebase).
  • storageBucket : bucket Cloud Storage associé à la fonction (si cette option est activée sur le projet Firebase).

Ils fonctionnent comme des paramètres de chaîne définis par l'utilisateur à tous égards, sauf que, comme leurs valeurs sont toujours connues de la CLI Firebase, leurs valeurs ne seront jamais invitées lors du déploiement ni enregistrées dans des fichiers .env.

Paramètres de secret

Les paramètres de type Secret, définis à l'aide de defineSecret(), représentent des paramètres de chaîne ayant une valeur stockée dans Cloud Secret Manager. Au lieu de vérifier par rapport à un fichier .env local et d'écrire une nouvelle valeur dans le fichier en cas d'absence, les paramètres de secret vérifient l'existence de Cloud Secret Manager et invitent de manière interactive la valeur d'un nouveau secret lors du déploiement.

Les paramètres de secret définis de cette manière doivent être liés à des fonctions individuelles qui doivent y avoir accès:

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

Étant donné que les valeurs des secrets sont masquées jusqu'à l'exécution de la fonction, vous ne pouvez pas les utiliser lors de la configuration de votre fonction.

Variables d'environnement

Cloud Functions for Firebase accepte le format de fichier dotenv pour charger les variables d'environnement spécifiées dans un fichier .env dans l'environnement d'exécution de votre application. Une fois déployées, les variables d'environnement peuvent être lues via l'interface process.env.

Pour configurer votre environnement de cette manière, créez un fichier .env dans votre projet, ajoutez les variables souhaitées, puis déployez:

  1. Créez un fichier .env dans le répertoire functions/:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Ouvrez le fichier .env pour le modifier et ajoutez les clés souhaitées. Exemple :

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Déployez les fonctions et vérifiez que les variables d'environnement ont bien été chargées:

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

Une fois vos variables d'environnement personnalisées déployées, le code de votre fonction peut y accéder avec la syntaxe 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}`);
});

Déployer plusieurs ensembles de variables d'environnement

Si vous avez besoin d'un autre ensemble de variables d'environnement pour vos projets Firebase (par exemple, préproduction ou production), créez un fichier .env.<project or alias> et écrivez-y les variables d'environnement spécifiques au projet. Les variables d'environnement des fichiers .env et des fichiers .env spécifiques au projet (le cas échéant) seront incluses dans toutes les fonctions déployées.

Par exemple, un projet peut inclure ces trois fichiers contenant des valeurs légèrement différentes pour le développement et la production:

.env .env.dev .env.prod
PLANÈTE=Terre

AUDIENCE=Humaniers

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

Compte tenu des valeurs de ces fichiers distincts, l'ensemble des variables d'environnement déployées avec vos fonctions varie en fonction de votre projet cible:

$ 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 d'environnement réservées

Certaines clés de variables d'environnement sont réservées à un usage interne. N'utilisez aucune des clés suivantes dans vos fichiers .env:

  • Toutes les clés commençant par X_GOOGLE_
  • Toutes les clés à partir de EXT_
  • Toutes les clés commençant par FIREBASE_
  • N'importe quelle clé de la liste suivante:
  • 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
  • PORT
  • K_CONFIGURATION

Stocker des informations de configuration sensibles et y accéder

Les variables d'environnement stockées dans des fichiers .env peuvent être utilisées pour configurer une fonction, mais elles ne constituent pas un moyen sécurisé de stocker des informations sensibles telles que des identifiants de base de données ou des clés API. C'est particulièrement important si vous vérifiez vos fichiers .env dans le contrôle de la source.

Pour vous aider à stocker des informations de configuration sensibles, Cloud Functions for Firebase s'intègre à Secret Manager de Google Cloud. Ce service chiffré stocke les valeurs de configuration de manière sécurisée, tout en permettant un accès facile à partir de vos fonctions en cas de besoin.

Créer et utiliser un secret

Pour créer un secret, utilisez la CLI Firebase.

Pour créer et utiliser un secret:

  1. Depuis la racine du répertoire de votre projet local, exécutez la commande suivante :

    firebase functions:secrets:set SECRET_NAME

  2. Saisissez une valeur pour SECRET_NAME.

    La CLI renvoie un message de réussite et vous avertit que vous devez déployer des fonctions pour que la modification soit prise en compte.

  3. Avant le déploiement, assurez-vous que le code de votre fonction lui permet d'accéder au secret à l'aide du paramètre 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. Déployez des fonctions Cloud:

    firebase deploy --only functions

Vous pouvez maintenant y accéder comme n'importe quelle autre variable d'environnement. À l'inverse, si une autre fonction qui ne spécifie pas le secret dans runWith tente d'accéder au secret, elle reçoit une valeur non définie:

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

Une fois votre fonction déployée, elle aura accès à la valeur du secret. Seules les fonctions qui incluent spécifiquement un secret dans leur paramètre runWith auront accès à ce secret en tant que variable d'environnement. Cela vous permet de vous assurer que les valeurs des secrets ne sont disponibles que lorsqu'elles sont nécessaires, réduisant ainsi le risque de fuite accidentelle d'un secret.

Gérer les secrets

Utilisez la CLI Firebase pour gérer vos secrets. Lorsque vous gérez les secrets de cette manière, gardez à l'esprit que certaines modifications de la CLI nécessitent de modifier et/ou de redéployer les fonctions associées. Plus spécifiquement :

  • Chaque fois que vous définissez une nouvelle valeur pour un secret, vous devez redéployer toutes les fonctions qui font référence à ce secret pour qu'elles récupèrent la dernière valeur.
  • Si vous supprimez un secret, assurez-vous qu'aucune de vos fonctions déployées ne le référence. Les fonctions qui utilisent une valeur de secret qui a été supprimée échouent silencieusement.

Voici un résumé des commandes de la CLI Firebase pour la gestion des secrets:

# 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

Pour les commandes access et destroy, vous pouvez fournir le paramètre de version facultatif permettant de gérer une version particulière. Exemple :

functions:secrets:access SECRET_NAME[@VERSION]

Pour en savoir plus sur ces opérations, transmettez -h avec la commande permettant d'afficher l'aide de la CLI.

Facturation des secrets

Secret Manager autorise 6 versions actives sans frais. Cela signifie que vous pouvez disposer sans frais de six secrets par mois dans un projet Firebase.

Par défaut, la CLI Firebase tente de détruire automatiquement les versions de secret inutilisées le cas échéant, par exemple lorsque vous déployez des fonctions avec une nouvelle version du secret. Vous pouvez également nettoyer activement les secrets inutilisés à l'aide de functions:secrets:destroy et functions:secrets:prune.

Secret Manager autorise 10 000 opérations d'accès mensuelles non facturées sur un secret. Les instances de fonction ne lisent que les secrets spécifiés dans leur paramètre runWith à chaque démarrage à froid. Si de nombreuses instances de fonction lisent beaucoup de secrets, votre projet peut dépasser ce quota, auquel cas vous serez facturé 0,03 $pour 10 000 opérations d'accès.

Pour en savoir plus, consultez la section Tarifs de Secret Manager.

Prise en charge des émulateurs

La configuration de l'environnement avec dotenv est conçue pour interagir avec un émulateur Cloud Functions local.

Lorsque vous utilisez un émulateur Cloud Functions local, vous pouvez remplacer les variables d'environnement de votre projet en configurant un fichier .env.local. Le contenu de .env.local prévaut sur .env et le fichier .env spécifique au projet.

Par exemple, un projet peut inclure ces trois fichiers contenant des valeurs légèrement différentes pour le développement et les tests en local:

.env .env.dev .env.local
PLANÈTE=Terre

AUDIENCE=Humaniers

AUDIENCE=Dev Humans AUDIENCE=humains locaux

Lorsqu'il est démarré en contexte local, l'émulateur charge les variables d'environnement comme indiqué ci-dessous:

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

Secrets et identifiants dans l'émulateur Cloud Functions

L'émulateur Cloud Functions prend en charge l'utilisation de secrets pour stocker des informations de configuration sensibles et y accéder. Par défaut, l'émulateur tente d'accéder à vos codes secrets de production à l'aide des identifiants par défaut de l'application. Dans certaines situations telles que les environnements CI, l'émulateur peut ne pas accéder aux valeurs secrètes en raison de restrictions d'autorisation.

Comme pour la compatibilité de l'émulateur Cloud Functions avec les variables d'environnement, vous pouvez remplacer les valeurs des secrets en configurant un fichier .secret.local. Cela vous permet de tester facilement vos fonctions localement, en particulier si vous n'avez pas accès à la valeur du secret.

Migrer depuis la configuration de l'environnement

Si vous utilisiez la configuration d'environnement avec functions.config, vous pouvez migrer votre configuration existante en tant que variables d'environnement (au format dotenv). La CLI Firebase fournit une commande d'exportation qui génère la configuration de chaque alias ou projet répertorié dans le fichier .firebaserc de votre répertoire (local, dev et prod dans l'exemple ci-dessous) sous forme de fichiers .env.

Pour effectuer la migration, exportez vos configurations d'environnement existantes à l'aide de la commande 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

Notez que, dans certains cas, vous serez invité à saisir un préfixe pour renommer les clés de variables d'environnement exportées. En effet, toutes les configurations ne peuvent pas être automatiquement transformées, car elles peuvent être non valides ou il peut s'agir d'une clé de variable d'environnement réservée.

Nous vous recommandons d'examiner attentivement le contenu des fichiers .env générés avant de déployer vos fonctions ou de vérifier les fichiers .env dans le contrôle du code source. Si des valeurs sont sensibles et ne doivent pas être divulguées, supprimez-les de vos fichiers .env et stockez-les de manière sécurisée dans Secret Manager.

Vous devez également mettre à jour le code de vos fonctions. Toutes les fonctions qui utilisent functions.config devront désormais utiliser process.env, comme indiqué dans la section Passer à la 2e génération.

Configuration de l'environnement

Avant la prise en charge des variables d'environnement dans firebase-functions v3.18.0, il était recommandé d'utiliser functions.config() pour configurer l'environnement. Cette approche est toujours acceptée, mais nous vous recommandons d'utiliser des variables d'environnement pour tous les nouveaux projets, car elles sont plus simples à utiliser et améliorent la portabilité de votre code.

Définir la configuration de l'environnement à l'aide de la CLI

Pour stocker des données d'environnement, vous pouvez utiliser la commande firebase functions:config:set dans la CLI Firebase. Chaque clé peut être associée à un espace de noms à l'aide de points pour regrouper les configurations associées. N'oubliez pas que seuls les caractères minuscules sont acceptés dans les clés ; les majuscules ne sont pas autorisées.

Par exemple, pour stocker l'ID client et la clé API pour "Certains services", vous pouvez exécuter la commande suivante:

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

Récupérer la configuration de l'environnement actuel

Pour inspecter les éléments actuellement stockés dans la configuration de l'environnement de votre projet, vous pouvez utiliser firebase functions:config:get. Le résultat JSON ressemblera à ceci:

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

Cette fonctionnalité est basée sur l'API Google Cloud Runtime Configuration.

Utiliser functions.config pour accéder à la configuration de l'environnement dans une fonction

Certaines configurations sont automatiquement fournies dans l'espace de noms firebase réservé. La configuration de l'environnement est disponible dans la fonction en cours d'exécution via functions.config(). Pour utiliser la configuration ci-dessus, votre code peut se présenter comme suit:

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

Utiliser la configuration de l'environnement pour initialiser un module

Certains modules Node sont prêts sans aucune configuration. D'autres modules nécessitent une configuration supplémentaire pour s'initialiser correctement. Nous vous recommandons de stocker cette configuration dans des variables de configuration d'environnement plutôt que de la coder en dur. Cela vous permet de garder votre code beaucoup plus portable, ce qui vous permet d'Open Source votre application ou de basculer facilement entre les versions de production et de préproduction.

Par exemple, pour utiliser le module SDK Slack Node, vous pouvez écrire ceci:

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

Avant le déploiement, définissez la variable de configuration d'environnement slack.url:

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

Autres commandes d'environnement

  • firebase functions:config:unset key1 key2 supprime les clés spécifiées de la configuration.
  • firebase functions:config:clone --from <fromProject> clone l'environnement d'un autre projet dans le projet actuellement actif.

Variables d'environnement renseignées automatiquement

Des variables d'environnement sont automatiquement renseignées dans l'environnement d'exécution des fonctions et dans les fonctions émulées localement. Ceux-ci incluent ceux renseignés par Google Cloud, ainsi que d'une variable d'environnement spécifique à Firebase:

process.env.FIREBASE_CONFIG: fournit les informations de configuration du projet Firebase suivantes:

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

Cette configuration est appliquée automatiquement lorsque vous initialisez le SDK Admin Firebase sans argument. Si vous écrivez des fonctions en JavaScript, initialisez-les comme suit:

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

Si vous écrivez des fonctions en TypeScript, initialisez-les comme suit:

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

Si vous devez initialiser le SDK Admin avec la configuration de projet par défaut à l'aide des identifiants du compte de service, vous pouvez charger les identifiants à partir d'un fichier et les ajouter à FIREBASE_CONFIG comme ceci:

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

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