Configura il tuo ambiente


Spesso è necessaria una configurazione aggiuntiva per le funzioni, ad esempio chiavi API di terze parti o impostazioni regolabili. L'SDK Firebase per Cloud Functions offre integrata per semplificare l'archiviazione e il recupero tipo di dati per il tuo progetto.

Puoi scegliere tra le seguenti opzioni:

  • Configurazione con parametri (consigliata per la maggior parte degli scenari). In questo modo viene fornita una configurazione dell'ambiente fortemente tipizzata con parametri convalidati al momento del deployment, il che impedisce errori e semplifica il debug.
  • Configurazione basata su file delle variabili di ambiente. Con questo approccio, crei manualmente un file dotenv per il caricamento delle variabili di ambiente.

Per la maggior parte dei casi d'uso, è consigliata la configurazione parametrizzata. Questo approccio rende disponibili i valori di configurazione sia in fase di runtime che di deployment e quest'ultimo viene bloccato a meno che tutti i parametri non abbiano un valore valido. Al contrario, la configurazione con le variabili di ambiente non è disponibile al momento del deployment nel tempo.

Configurazione con parametri

Cloud Functions for Firebase fornisce un'interfaccia per definire la configurazione in modo dichiarativo all'interno del codebase. Il valore di questi parametri è disponibili sia durante il deployment delle funzioni, sia quando si impostano deployment e runtime e durante l'esecuzione. Ciò significa che la CLI bloccherà il deployment a meno che tutti i parametri non abbiano un valore valido.

Per definire i parametri nel codice, segui questo modello:

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

Quando esegui il deployment di una funzione con variabili di configurazione parametrizzate, l'interfaccia a riga di comando di Firebase tenta innanzitutto di caricarne i valori dai file .env locali. Se non sono presenti in questi file e non è impostato default, la CLI chiederà i valori durante il deployment e li salverà automaticamente in un file .env denominato .env.<project_ID> nella directory 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

A seconda del flusso di lavoro di sviluppo, potrebbe essere utile aggiungere al controllo della versione il file .env.<project_ID> generato.

Utilizzo dei parametri a livello globale

Durante il deployment, il codice delle funzioni viene caricato e ispezionato prima hanno valori effettivi. Ciò significa che il recupero dei valori dei parametri durante l'ambito globale comporta un errore di deployment. Nei casi in cui vuoi utilizzare per inizializzare un valore globale, usa il callback di inizializzazione onInit(). Questo callback viene eseguito prima dell'esecuzione di qualsiasi funzione in produzione, ma non viene chiamato durante il deployment, pertanto è un luogo sicuro per accedere al valore di un parametro.

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

Configurare il comportamento della CLI

I parametri possono essere configurati con un oggetto Options che controlla il modo in cui l'interfaccia a riga di comando richiede valori. L'esempio seguente imposta le opzioni per convalidare il formato di un numero di telefono, per fornire un'opzione di selezione semplice e per compilare automaticamente un'opzione di selezione dal progetto 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 Projects
storage buckets"})

Tipi di parametri

La configurazione con parametri fornisce un tipo sicuro per i valori dei parametri e supporta anche i secret di Cloud Secret Manager. I tipi supportati sono:

  • Secret
  • Stringa
  • Booleano
  • Numero intero
  • In virgola mobile

Valori ed espressioni dei parametri

Firebase valuta i parametri sia al momento del deployment sia durante l'esecuzione della funzione. A causa di questi due ambienti, è necessario prestare particolare attenzione quando confrontare i valori dei parametri e utilizzarli per impostare le opzioni di runtime funzioni.

Per passare un parametro alla funzione come opzione di runtime, trasmettilo direttamente:

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

Inoltre, se devi eseguire un confronto con un parametro per sapere quale opzione scegliere, dovrai utilizzare i comparatori integrati anziché controllare il valore:

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

I parametri e le espressioni di parametro utilizzati solo in fase di esecuzione possono essere accessi con la relativa funzione 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.`);
  }
);

Parametri integrati

L'SDK di Cloud Functions offre tre parametri predefiniti, disponibili da il sottopacchetto firebase-functions/params:

  • projectID: il progetto Cloud in cui è in esecuzione la funzione.
  • databaseURL: l'URL dell'istanza di Realtime Database associata alla funzione (se abilitata nel progetto Firebase).
  • storageBucket: il bucket Cloud Storage associato alla funzione (se abilitata nel progetto Firebase).

Questi parametri funzionano come parametri di stringa definiti dall'utente sotto tutti gli aspetti, tranne per il fatto che, poiché i relativi valori sono sempre noti a Firebase CLI, non verrà mai richiesto di inserirli durante il deployment né verranno salvati nei file .env.

Parametri secret

I parametri di tipo Secret, definiti utilizzando defineSecret(), rappresentano una stringa che hanno un valore archiviato in Cloud Secret Manager. Invece di eseguire il controllo rispetto a un file .env locale e scrivere un nuovo valore nel file se mancante, i parametri secret controllano l'esistenza in Cloud Secret Manager e richiedono in modo interattivo il valore di un nuovo secret durante il deployment.

I parametri secret così definiti devono essere associati a singole funzioni che dovrebbero potervi accedere:

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

Poiché i valori dei secret sono nascosti fino all'esecuzione della funzione, non puoi utilizzarli durante la configurazione della funzione.

Variabili di ambiente

Cloud Functions for Firebase supporta dotenv per caricare le variabili di ambiente specificate in un file .env nel tuo il runtime dell'applicazione. Dopo il deployment, le variabili di ambiente possono essere lette tramite process.env a riga di comando.

Per configurare l'ambiente in questo modo, crea un file .env nel progetto, aggiungi le variabili desiderate ed esegui il deployment:

  1. Crea un file .env nella directory functions/:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Apri il file .env per la modifica e aggiungi le chiavi desiderate. Ad esempio:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Esegui il deployment delle funzioni e verifica che le variabili di ambiente siano state caricate:

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

Una volta eseguito il deployment delle variabili di ambiente personalizzate, il codice della funzione può accedervi process.env sintassi:

// Responds with "Hello Earth and Humans"
exports.hello = functions.https.onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

Deployment di più insiemi di variabili di ambiente

Se hai bisogno di un insieme alternativo di variabili di ambiente per i tuoi progetti Firebase (ad esempio gestione temporanea e produzione), crea un file .env.<project or alias> e scrivi al suo interno le variabili di ambiente specifiche del progetto. Le variabili di ambiente .env e file .env specifici del progetto (se presenti) verrà incluso in tutte le funzioni di cui è stato eseguito il deployment.

Ad esempio, un progetto potrebbe includere questi tre file contenenti diversi valori per lo sviluppo e la produzione:

.env .env.dev .env.prod
PLANET=Earth

SEGMENTO DI PUBBLICO=umani

AUDIENCE=Dev Humans AUDIENCE=Produzione umana

Dati i valori in questi file separati, l'insieme di variabili di ambiente il deployment con le tue funzioni varierà a seconda del progetto di destinazione:

$ 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

Variabili di ambiente riservate

Alcune chiavi delle variabili di ambiente sono riservate per uso interno. Non utilizzare nessuno di queste chiavi nei tuoi file .env:

  • Tutte le chiavi che iniziano con X_GOOGLE_
  • Tutte le chiavi a partire da EXT_
  • Tutte le chiavi che iniziano con FIREBASE_
  • Qualsiasi chiave del seguente elenco:
  • CLOUD_RUNTIME_CONFIG
  • ENTRY_POINT
  • PROGETTO_Google Cloud
  • GCLOUD_PROJECT
  • PROGETTO_CLOUD_CLOUD
  • FUNCTION_TRIGGER_TYPE
  • NOME_FUNZIONE
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • ID_FUNZIONE
  • REGIONE_FUNZIONE
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICE
  • REVISIONE_K
  • PORT
  • K_CONFIGURATION

Archiviare e accedere a informazioni di configurazione sensibili

Le variabili di ambiente archiviate in file .env possono essere utilizzate per la funzione ma non dovresti considerarli un modo sicuro per archiviare i dati informazioni come le credenziali del database o le chiavi API. Ciò è particolarmente importante se controlli i file .env nel controllo del codice sorgente.

Per aiutarti ad archiviare informazioni sensibili di configurazione, Cloud Functions for Firebase si integra con Google Cloud Secret Manager Questo servizio criptato memorizza i valori di configurazione in modo sicuro, consentendo al contempo un facile accesso dalle funzioni, se necessario.

Creare e utilizzare un secret

Per creare un secret, utilizza la CLI Firebase.

Per creare e utilizzare un secret:

  1. Dalla directory principale del progetto locale, esegui il seguente comando:

    firebase functions:secrets:set SECRET_NAME

  2. Inserisci un valore per SECRET_NAME.

    L'interfaccia a riga di comando restituisce un messaggio di successo e ti avvisa che devi eseguire il deployment delle funzioni per applicare la modifica.

  3. Prima di eseguire il deployment, assicurati che il codice delle funzioni consenta alla funzione di accedere al secret utilizzando il parametro 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. Esegui il deployment di Cloud Functions:

    firebase deploy --only functions

Ora potrai accedervi come qualsiasi altra variabile di ambiente. Al contrario, se un'altra funzione che non specifica il segreto in runWith tenta di accedervi, riceve un valore non definito:

  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 volta eseguito il deployment, la funzione avrà accesso al valore del secret. Solo che includono in modo specifico un secret nel parametro runWith hanno accesso al secret come variabile di ambiente. In questo modo puoi assicurarti che i valori dei secret siano disponibili solo dove sono necessari, riducendo il rischio di divulgare accidentalmente un secret.

Gestione dei secret

Utilizza l'interfaccia a riga di comando Firebase per gestire i tuoi secret. Mentre gestisco i secret in questo modo, tieni presente che alcune modifiche dell'interfaccia a riga di comando richiedono la modifica e/o il nuovo deployment funzioni associate. Nello specifico:

  • Ogni volta che imposti un nuovo valore per un secret, devi eseguire nuovamente il deployment di tutte le funzioni che fanno riferimento a quel secret affinché acquisiscano il valore più recente.
  • Se elimini un secret, assicurati che nessuna delle funzioni di cui hai eseguito il deployment fa riferimento a quel secret. Le funzioni che utilizzano un valore segreto che è stato eliminato non genereranno alcun errore.

Ecco un riepilogo dei comandi dell'interfaccia a riga di comando Firebase per la gestione dei secret:

# 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

Per i comandi access e destroy, puoi fornire il parametro facoltativo version per gestire una determinata versione. Ad esempio:

functions:secrets:access SECRET_NAME[@VERSION]

Per maggiori informazioni su queste operazioni, passa -h con il comando a visualizza la guida dell'interfaccia a riga di comando.

Come vengono fatturati i secret

Secret Manager consente 6 versioni di secret attive senza costi. Ciò significa che puoi avere 6 secret al mese in un account Firebase progetto senza costi aggiuntivi.

Per impostazione predefinita, l'interfaccia a riga di comando Firebase tenta di eliminare automaticamente il secret inutilizzato ove appropriato, ad esempio quando esegui il deployment di funzioni con una nuova versione del secret. Inoltre, puoi eliminare attivamente i secret inutilizzati utilizzando functions:secrets:destroy e functions:secrets:prune.

Secret Manager consente 10.000 operazioni di accesso mensili non fatturate su un secret. Le istanze di funzione leggono solo i secret specificati nel parametro runWith ogni volta che vengono avviate a freddo. Se hai molte istanze di funzione che leggono molti secret, il tuo progetto potrebbe superare questa autorizzazione, nel qual caso ti verrà addebitato 0,03 $ per 10.000 operazioni di accesso.

Per ulteriori informazioni, consulta la sezione Secret Manager Prezzi.

Supporto dell'emulatore

La configurazione dell'ambiente con Dotenv è progettata per interagire con un emulatore Cloud Functions locale.

Quando utilizzi un emulatore Cloud Functions locale, puoi eseguire l'override dell'ambiente per il tuo progetto configurando un file .env.local. I contenuti di .env.local hanno la precedenza su .env e sul file .env specifico del progetto.

Ad esempio, un progetto potrebbe includere questi tre file contenenti valori leggermente diversi per lo sviluppo e i test locali:

.env .env.dev .env.local
PLANET=Earth

SEGMENTO DI PUBBLICO=umani

AUDIENCE=Dev Humans AUDIENCE=Persone locali

Quando viene avviato nel contesto locale, l'emulatore carica le variabili di ambiente come mostrato di seguito:

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

Secret e credenziali nell'emulatore Cloud Functions

L'emulatore Cloud Functions supporta l'utilizzo di secret per archiviare e accedere a informazioni di configurazione sensibili. Per impostazione predefinita, l'emulatore tenta di accedere ai secret di produzione utilizzando credenziali predefinite dell'applicazione. In determinate situazioni come gli ambienti CI, l'emulatore potrebbe non riuscire ad accedere valori secret a causa di restrizioni di autorizzazione.

Come per il supporto dell'emulatore Cloud Functions per le variabili di ambiente, puoi: esegui l'override dei valori dei secret configurando un file .secret.local. Ciò rende è facile testare le funzioni localmente, soprattutto se non disponi dell'accesso al valore del secret.

Migrazione dalla configurazione dell'ambiente

Se utilizzavi la configurazione dell'ambiente con functions.config, puoi eseguire la migrazione della configurazione esistente come variabili di ambiente (in dotenv). L'interfaccia a riga di comando Firebase fornisce un comando di esportazione che restituisce la configurazione di ciascun alias o progetto elencato nel file .firebaserc della directory (nell'esempio riportato di seguito, local, dev e prod) come file .env.

Per eseguire la migrazione, esporta le configurazioni dell'ambiente esistenti utilizzando il 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

Tieni presente che, in alcuni casi, ti verrà chiesto di inserire un prefisso per rinominare le chiavi delle variabili di ambiente esportate. Questo perché non tutte le configurazioni possono essere trasformate automaticamente, in quanto potrebbero non essere valide o essere una chiave della variabile di ambiente riservata.

Ti consigliamo di esaminare attentamente i contenuti dei file .env generati prima di eseguire il deployment delle funzioni o verifica i file .env nel controllo del codice sorgente. Se Tutti i valori sono sensibili e non devono essere divulgati. Rimuovili da .env e archiviarli in modo sicuro Secret Manager.

Dovrai anche aggiornare il codice delle funzioni. Tutte le funzioni che utilizzano functions.config ora dovranno utilizzare process.env, come mostrato in Eseguire l'upgrade alla 2ª gen..

Configurazione dell'ambiente

Impostare la configurazione dell'ambiente con l'interfaccia a riga di comando

Per archiviare i dati dell'ambiente, puoi utilizzare il comando firebase functions:config:set nella CLI Firebase. Ogni chiave può avere uno spazio dei nomi usando i punti per raggruppare configurazione. Tieni presente che solo i caratteri minuscoli vengono accettati nelle chiavi; non sono ammessi caratteri maiuscoli.

Ad esempio, per memorizzare l'ID client e la chiave API per "Un servizio", puoi eseguire:

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

Recupera la configurazione attuale dell'ambiente

Per controllare cosa è attualmente memorizzato nella configurazione dell'ambiente per il tuo progetto, puoi utilizzare firebase functions:config:get. L'output JSON sarà simile a questo:

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

Questa funzionalità si basa sul API Google Cloud Runtime Configuration.

Usa functions.config per accedere alla configurazione dell'ambiente in una funzione

Alcune configurazioni vengono fornite automaticamente nell'ambito delle firebase riservate nello spazio dei nomi. La configurazione dell'ambiente è disponibile durante l'esecuzione tramite functions.config(). Per utilizzare la configurazione precedente, il codice potrebbe avere il seguente aspetto:

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

Utilizzare la configurazione dell'ambiente per inizializzare un modulo

Alcuni moduli Node sono pronti per l'uso senza alcuna configurazione. Altri moduli richiedono configurazione iniziale per inizializzare correttamente. Ti consigliamo di archiviare questa configurazione nelle variabili di configurazione dell'ambiente anziché come hardcoded. In questo modo, il codice sarà molto più portabile, il che ti consente di rendere open source la tua applicazione o di passare facilmente dalle versioni di produzione a quelle di gestione temporanea.

Ad esempio, per utilizzare il modulo SDK Slack Node, potresti scrivere questo:

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

Prima di eseguire il deployment, imposta la variabile di configurazione dell'ambiente slack.url:

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

Comandi di ambiente aggiuntivi

  • firebase functions:config:unset key1 key2 rimuove le chiavi specificate dalla configurazione
  • firebase functions:config:clone --from <fromProject> clona l'ambiente di un altro progetto in il progetto attualmente attivo.

Variabili di ambiente compilate automaticamente

Esistono variabili di ambiente che vengono completate automaticamente nel runtime delle funzioni e nelle funzioni emulate localmente. Sono incluse quelle compilate da Google Cloud, nonché una variabile di ambiente specifica di Firebase:

process.env.FIREBASE_CONFIG: fornisce le seguenti informazioni di configurazione del progetto Firebase:

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

Questa configurazione viene applicata automaticamente all'inizializzazione di Firebase SDK Admin senza argomenti. Se scrivi funzioni in JavaScript, inizializza come segue:

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

Se stai scrivendo funzioni in TypeScript, inizializzalo in questo modo:

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

Se devi inizializzare SDK Admin con la configurazione predefinita del progetto utilizzando le credenziali dell'account di servizio, puoi caricare le credenziali da un file aggiungilo a FIREBASE_CONFIG in questo modo:

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

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