Configure seu ambiente


Muitas vezes você precisará de configurações adicionais para suas funções, como chaves de API de terceiros ou configurações ajustáveis. O SDK do Firebase para Cloud Functions oferece configuração de ambiente integrada para facilitar o armazenamento e a recuperação desse tipo de dados para seu projeto.

Você pode escolher entre três opções:

  • Configuração parametrizada (recomendada para a maioria dos cenários). Isso fornece configuração de ambiente fortemente tipada com parâmetros que são validados no momento da implantação, o que evita erros e simplifica a depuração.
  • Configuração baseada em arquivo de variáveis ​​de ambiente . Com essa abordagem, você cria manualmente um arquivo dotenv para carregar variáveis ​​de ambiente.
  • Configuração do ambiente de execução com Firebase CLI e functions.config (somente Cloud Functions (1ª geração)).

Para a maioria dos casos de uso, a configuração parametrizada é recomendada. Essa abordagem disponibiliza valores de configuração em tempo de execução e de implantação, e a implantação é bloqueada, a menos que todos os parâmetros tenham um valor válido. Por outro lado, a configuração com variáveis ​​de ambiente não está disponível no momento da implantação.

Configuração parametrizada

O Cloud Functions para Firebase fornece uma interface para definir parâmetros de configuração de forma declarativa dentro da sua base de código. O valor desses parâmetros está disponível durante a implantação da função, ao definir opções de implantação e tempo de execução e durante a execução. Isso significa que a CLI bloqueará a implantação, a menos que todos os parâmetros tenham um valor válido.

Para definir parâmetros em seu 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.`);
  }
);

Ao implantar uma função com variáveis ​​de configuração parametrizadas, a CLI do Firebase primeiro tenta carregar seus valores de arquivos .env locais. Se eles não estiverem presentes nesses arquivos e nenhum default for definido, a CLI solicitará os valores durante a implantação e, em seguida, salvará automaticamente seus valores em um arquivo .env chamado .env.<project_ID> em seu diretório 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

Dependendo do seu fluxo de trabalho de desenvolvimento, pode ser útil adicionar o arquivo .env.<project_ID> gerado ao controle de versão.

Configurar o comportamento da CLI

Os parâmetros podem ser configurados com um objeto Options que controla como a CLI solicitará valores. O exemplo a seguir define opções para validar o formato de um número de telefone, fornecer uma opção de seleção simples e preencher uma opção de seleção automaticamente no projeto do 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

A configuração parametrizada fornece digitação forte para valores de parâmetros e também oferece suporte a segredos do Cloud Secret Manager. Os tipos suportados são:

  • Segredo
  • Corda
  • boleano
  • Inteiro
  • Flutuador

Valores e expressões de parâmetros

O Firebase avalia seus parâmetros no momento da implantação e durante a execução da função. Devido a esses ambientes duplos, alguns cuidados extras devem ser tomados ao comparar valores de parâmetros e ao usá-los para definir opções de tempo de execução para suas funções.

Para passar um parâmetro para sua função como uma opção de tempo de execução, passe-o diretamente:

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

Além disso, se precisar comparar com um parâmetro para saber qual opção escolher, você precisará usar comparadores integrados em vez de verificar o 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) => {
    //…

Parâmetros e expressões de parâmetros que são usados ​​apenas em tempo de execução podem ser acessados ​​com sua função 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 integrados

O SDK do Cloud Functions oferece três parâmetros predefinidos, disponíveis no subpacote firebase-functions/params :

  • projectID — o projeto do Cloud no qual a função está sendo executada.
  • databaseURL — o URL da instância do Realtime Database associada à função (se habilitado no projeto Firebase).
  • storageBucket — o bucket do Cloud Storage associado à função (se ativado no projeto do Firebase).

Eles funcionam como parâmetros de string definidos pelo usuário em todos os aspectos, exceto que, como seus valores são sempre conhecidos pela Firebase CLI, seus valores nunca serão solicitados na implantação nem salvos em arquivos .env .

Parâmetros secretos

Parâmetros do tipo Secret , definidos usando defineSecret() , representam parâmetros de string que possuem um valor armazenado no Cloud Secret Manager. Em vez de verificar um arquivo .env local e gravar um novo valor no arquivo, se estiver ausente, os parâmetros secretos verificam a existência no Cloud Secret Manager e solicitam interativamente o valor de um novo segredo durante a implantação.

Os parâmetros secretos definidos desta forma devem estar vinculados a funções individuais que devem ter acesso a eles:

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

Como os valores dos segredos ficam ocultos até a execução da função, você não pode usá-los ao configurar sua função.

Variáveis ​​ambientais

O Cloud Functions para Firebase oferece suporte ao formato de arquivo dotenv para carregar variáveis ​​de ambiente especificadas em um arquivo .env no ambiente de execução do aplicativo. Depois de implantadas, as variáveis ​​de ambiente podem ser lidas por meio da interface process.env .

Para configurar seu ambiente desta forma, crie um arquivo .env em seu projeto, adicione as variáveis ​​desejadas e implante:

  1. Crie um arquivo .env em seu diretório functions/ :

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Abra o arquivo .env para edição e adicione as chaves desejadas. Por exemplo:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Implante funções e verifique se as variáveis ​​de ambiente foram carregadas:

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

Depois que suas variáveis ​​de ambiente personalizadas forem implantadas, seu código de função poderá acessá-las com a sintaxe 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}`);
});

Implantando vários conjuntos de variáveis ​​de ambiente

Se você precisar de um conjunto alternativo de variáveis ​​de ambiente para seus projetos do Firebase (como preparação versus produção), crie um .env. <project or alias > e escreva nele as variáveis ​​de ambiente específicas do projeto. As variáveis ​​de ambiente dos arquivos .env e .env específicos do projeto (se existirem) serão incluídas em todas as funções implantadas.

Por exemplo, um projeto poderia incluir estes três arquivos contendo valores ligeiramente diferentes para desenvolvimento e produção:

.env .env.dev .env.prod
PLANETA=Terra

AUDIÊNCIA=Humanos

AUDIÊNCIA = Desenvolvedores Humanos AUDIÊNCIA=Prod Humanos

Dados os valores nesses arquivos separados, o conjunto de variáveis ​​de ambiente implantadas com suas funções irá variar dependendo do seu projeto 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

Variáveis ​​de ambiente reservadas

Algumas chaves de variáveis ​​de ambiente são reservadas para uso interno. Não use nenhuma dessas chaves em seus arquivos .env :

  • Todas as chaves começando com X_GOOGLE_
  • Todas as chaves começando com EXT_
  • Todas as chaves começando com FIREBASE_
  • Qualquer chave da lista a seguir:
  • CLOUD_RUNTIME_CONFIG
  • PONTO DE ENTRADA
  • 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_REVISÃO
  • PORTA
  • K_CONFIGURAÇÃO

Armazene e acesse informações de configuração confidenciais

Variáveis ​​de ambiente armazenadas em arquivos .env podem ser usadas para configuração de funções, mas você não deve considerá-las uma forma segura de armazenar informações confidenciais, como credenciais de banco de dados ou chaves de API. Isso é especialmente importante se você verificar seus arquivos .env no controle de origem.

Para ajudar você a armazenar informações confidenciais de configuração, o Cloud Functions for Firebase se integra ao Google Cloud Secret Manager . Este serviço criptografado armazena valores de configuração com segurança, ao mesmo tempo que permite fácil acesso a partir de suas funções quando necessário.

Crie e use um segredo

Para criar um segredo, use a CLI do Firebase.

Para criar e usar um segredo:

  1. Na raiz do diretório local do projeto, execute o seguinte comando:

    firebase functions:secrets:set SECRET_NAME

  2. Insira um valor para SECRET_NAME .

    A CLI ecoa uma mensagem de sucesso e avisa que você deve implementar funções para que a mudança entre em vigor.

  3. Antes de implantar, certifique-se de que seu código de funções permita que a função acesse o segredo usando o 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. Implante funções de nuvem:

    firebase deploy --only functions

Agora você poderá acessá-lo como qualquer outra variável de ambiente. Por outro lado, se outra função que não especifica o segredo em runWith tentar acessar o segredo, ela receberá um 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
  });

Assim que sua função for implantada, ela terá acesso ao valor secreto. Somente funções que incluam especificamente um segredo em seu parâmetro runWith terão acesso a esse segredo como uma variável de ambiente. Isso ajuda você a garantir que os valores secretos estejam disponíveis apenas onde forem necessários, reduzindo o risco de vazamento acidental de um segredo.

Gerenciando segredos

Use a CLI do Firebase para gerenciar seus segredos. Ao gerenciar segredos dessa maneira, lembre-se de que algumas alterações da CLI exigem que você modifique e/ou reimplante funções associadas. Especificamente:

  • Sempre que você definir um novo valor para um segredo, deverá reimplantar todas as funções que fazem referência a esse segredo para que elas obtenham o valor mais recente.
  • Se você excluir um segredo, certifique-se de que nenhuma das funções implantadas faça referência a esse segredo. As funções que usam um valor secreto que foi excluído falharão silenciosamente.

Aqui está um resumo dos comandos Firebase CLI para gerenciamento de segredos:

# 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 os comandos access e destroy , você pode fornecer o parâmetro opcional version para gerenciar uma versão específica. Por exemplo:

functions:secrets:access SECRET_NAME[@VERSION]

Para obter mais informações sobre essas operações, passe -h com o comando para visualizar a ajuda da CLI.

Como os segredos são cobrados

O Secret Manager permite 6 versões de segredos ativos sem nenhum custo. Isso significa que você pode ter 6 segredos por mês em um projeto do Firebase sem nenhum custo.

Por padrão, a CLI do Firebase tenta destruir automaticamente versões de segredo não utilizadas quando apropriado, como quando você implanta funções com uma nova versão do segredo. Além disso, você pode limpar ativamente segredos não utilizados usando functions:secrets:destroy e functions:secrets:prune .

O Secret Manager permite 10.000 operações de acesso mensais não faturadas em um segredo. As instâncias de função leem apenas os segredos especificados em seu parâmetro runWith sempre que são inicializadas a frio. Se você tiver muitas instâncias de função lendo muitos segredos, seu projeto poderá exceder esse limite e, nesse ponto, será cobrado US$ 0,03 por 10.000 operações de acesso.

Para obter mais informações, consulte Preços do Secret Manager .

Suporte ao emulador

A configuração do ambiente com dotenv foi projetada para interoperar com um emulador local do Cloud Functions .

Ao usar um emulador local do Cloud Functions, você pode substituir variáveis ​​de ambiente do seu projeto configurando um arquivo .env.local . O conteúdo de .env.local tem precedência sobre .env e o arquivo .env específico do projeto.

Por exemplo, um projeto poderia incluir estes três arquivos contendo valores ligeiramente diferentes para desenvolvimento e testes locais:

.env .env.dev .env.local
PLANETA=Terra

AUDIÊNCIA=Humanos

AUDIÊNCIA = Desenvolvedores Humanos AUDIÊNCIA=Humanos Locais

Quando iniciado no contexto local, o emulador carrega as variáveis ​​de ambiente conforme mostrado:

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

Segredos e credenciais no emulador do Cloud Functions

O emulador do Cloud Functions oferece suporte ao uso de segredos para armazenar e acessar informações confidenciais de configuração . Por padrão, o emulador tentará acessar seus segredos de produção usando credenciais padrão do aplicativo . Em determinadas situações, como ambientes de CI, o emulador pode falhar ao acessar valores secretos devido a restrições de permissão.

Semelhante ao suporte do emulador do Cloud Functions para variáveis ​​de ambiente, é possível substituir valores de segredos configurando um arquivo .secret.local . Isso facilita o teste de suas funções localmente, especialmente se você não tiver acesso ao valor secreto.

Migrando da configuração do ambiente

Se você estiver usando a configuração de ambiente com functions.config , poderá migrar sua configuração existente como variáveis ​​de ambiente (no formato dotenv ). A CLI do Firebase fornece um comando de exportação que gera a configuração de cada alias ou projeto listado no arquivo .firebaserc do seu diretório (no exemplo abaixo, local , dev e prod ) como arquivos .env .

Para migrar, exporte as configurações de ambiente existentes usando o 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

Observe que, em alguns casos, você será solicitado a inserir um prefixo para renomear chaves de variáveis ​​de ambiente exportadas. Isso ocorre porque nem todas as configurações podem ser transformadas automaticamente, pois podem ser inválidas ou podem ser uma chave de variável de ambiente reservada .

Recomendamos que você revise cuidadosamente o conteúdo dos arquivos .env gerados antes de implantar suas funções ou verificar os arquivos .env no controle do código-fonte. Se algum valor for confidencial e não deve vazar, remova-o dos arquivos .env e armazene-o com segurança no Secret Manager .

Você também precisará atualizar seu código de funções. Quaisquer funções que usem functions.config agora precisarão usar process.env , conforme mostrado em Upgrade to 2nd gen .

Configuração do ambiente

Antes do lançamento do suporte a variáveis ​​de ambiente no firebase-functions v3.18.0 , usar functions.config() era a abordagem recomendada para configuração do ambiente. Essa abordagem ainda é suportada, mas recomendamos que todos os novos projetos usem variáveis ​​de ambiente, pois são mais simples de usar e melhoram a portabilidade do seu código.

Defina a configuração do ambiente com a CLI

Para armazenar dados do ambiente, você pode usar o comando firebase functions:config:set na CLI do Firebase . Cada chave pode ter namespace usando pontos para agrupar configurações relacionadas. Lembre-se de que apenas caracteres minúsculos são aceitos nas chaves ; caracteres maiúsculos não são permitidos.

Por exemplo, para armazenar o ID do cliente e a chave de API de "Algum serviço", você pode executar:

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

Recuperar a configuração atual do ambiente

Para inspecionar o que está armazenado atualmente na configuração do ambiente do seu projeto, você pode usar firebase functions:config:get . A saída será JSON mais ou menos assim:

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

Essa funcionalidade é baseada na API de configuração do Google Cloud Runtime .

Use functions.config para acessar a configuração do ambiente em uma função

Algumas configurações são fornecidas automaticamente no namespace reservado firebase . A configuração do ambiente é disponibilizada dentro da sua função em execução por meio de functions.config() . Para usar a configuração acima, seu código pode ficar assim:

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

Use a configuração do ambiente para inicializar um módulo

Alguns módulos do Node estão prontos sem qualquer configuração. Outros módulos precisam de configuração extra para inicializar corretamente. Recomendamos que você armazene essa configuração em variáveis ​​de configuração de ambiente em vez de codificá-la. Isso ajuda a manter seu código muito mais portátil, o que permite abrir o código-fonte de seu aplicativo ou alternar facilmente entre as versões de produção e de teste.

Por exemplo, para usar o módulo SDK do Slack Node , você pode escrever isto:

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

Antes da implantação, defina a variável de configuração de ambiente slack.url :

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

Comandos de ambiente adicionais

  • firebase functions:config:unset key1 key2 remove as chaves especificadas da configuração
  • firebase functions:config:clone --from <fromProject> clona o ambiente de outro projeto no projeto atualmente ativo.

Variáveis ​​de ambiente preenchidas automaticamente

Existem variáveis ​​de ambiente que são preenchidas automaticamente no tempo de execução das funções e em funções emuladas localmente. Isso inclui aqueles preenchidos pelo Google Cloud , bem como uma variável de ambiente específica do Firebase:

process.env.FIREBASE_CONFIG : fornece as seguintes informações de configuração do projeto Firebase:

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

Essa configuração é aplicada automaticamente quando você inicializa o SDK Admin do Firebase sem argumentos. Se você estiver escrevendo funções em JavaScript, inicialize assim:

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

Se você estiver escrevendo funções em TypeScript, inicialize assim:

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

Se precisar inicializar o Admin SDK com a configuração padrão do projeto usando credenciais de conta de serviço, você pode carregar as credenciais de um arquivo e adicioná-las ao FIREBASE_CONFIG assim:

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

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