Mengonfigurasi lingkungan Anda

Sering kali fungsi Anda memerlukan konfigurasi tambahan, seperti kunci API pihak ketiga atau setelan yang dapat disesuaikan. Firebase SDK untuk Cloud Functions menawarkan dua pendekatan konfigurasi lingkungan untuk memudahkan penyimpanan dan pengambilan jenis data ini untuk project Anda:

  • Konfigurasi berparameter. Opsi ini menyediakan konfigurasi lingkungan strongly-typed dengan parameter yang divalidasi pada waktu deployment, sehingga dapat mencegah error dan menyederhanakan proses debug.
  • Variabel lingkungan. Dengan pendekatan ini, Anda akan membuat file dotenv secara manual untuk memuat variabel lingkungan.

Untuk sebagian besar kasus penggunaan, konfigurasi berparameter direkomendasikan. Dengan pendekatan ini, nilai konfigurasi tersedia baik saat runtime maupun deployment, dan deployment akan diblokir kecuali jika semua parameter memiliki nilai yang valid. Sebaliknya, konfigurasi dengan variabel lingkungan tidak tersedia pada waktu deployment.

Konfigurasi berparameter

Cloud Functions for Firebase menyediakan antarmuka untuk menetapkan parameter konfigurasi secara deklaratif di dalam codebase Anda. Nilai parameter ini tersedia selama deployment fungsi, saat menetapkan opsi deployment dan runtime, serta selama eksekusi. Hal ini berarti bahwa CLI akan memblokir deployment kecuali jika semua parameter memiliki nilai yang valid.

Untuk menentukan parameter dalam kode Anda, ikuti model ini:

const { onRequest } = require('firebase-functions/v2/https');
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 = onRequest(
  { minInstances: minInstancesConfig },
 (req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Saat men-deploy fungsi dengan variabel konfigurasi berparameter, mula-mula Firebase CLI akan mencoba memuat nilai variabel tersebut dari file .env lokal. Jika nilai tersebut tidak ditemukan dan tidak ada default yang ditetapkan, CLI akan meminta nilai ini selama deployment, lalu otomatis menyimpannya ke file .env bernama .env.<project_ID> di direktori functions/ Anda:

$ 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

Bergantung pada alur kerja pengembangan Anda, sebaiknya tambahkan file .env.<project_ID> yang dihasilkan ke kontrol versi.

Mengonfigurasi perilaku CLI

Parameter dapat dikonfigurasi dengan objek Options yang mengontrol cara CLI meminta nilai. Contoh berikut menetapkan opsi untuk memvalidasi format nomor telepon, memberikan opsi pemilihan sederhana, dan mengisi opsi pemilihan secara otomatis dari project 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"})

Jenis-jenis parameter

Konfigurasi berparameter menyediakan strong typing untuk parameter value, dan juga mendukung secret dari Cloud Secret Manager. Jenis yang didukung adalah:

  • Secret
  • String
  • Boolean
  • Bilangan bulat
  • Float

Nilai dan ekspresi parameter

Firebase mengevaluasi parameter pada waktu deployment dan saat fungsi dieksekusi. Karena adanya lingkungan ganda ini, Anda harus cermat saat membandingkan parameter value, dan saat menggunakannya untuk menetapkan opsi runtime bagi fungsi Anda.

Untuk meneruskan parameter ke fungsi Anda sebagai opsi runtime, teruskan secara langsung:

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

export const helloworld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Selain itu, jika Anda perlu membandingkan parameter untuk mengetahui opsi yang sebaiknya dipilih, Anda harus menggunakan komparator bawaan, bukan memeriksa nilai:

const { onRequest } = require('firebase-functions/v2/https');
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 = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Parameter dan ekspresi parameter yang hanya digunakan saat runtime dapat diakses dengan fungsi value-nya:

const { onRequest } = require('firebase-functions/v2/https');
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 = onRequest(
 (req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Parameter bawaan

Cloud Functions SDK menawarkan tiga parameter yang telah ditetapkan, yang tersedia dari sub-paket firebase-functions/params:

  • projectId — project Cloud tempat fungsi dijalankan.
  • databaseUrl — URL instance Realtime Database yang terkait dengan fungsi tersebut (jika diaktifkan di project Firebase).
  • storageBucket — bucket Cloud Storage yang terkait dengan fungsi tersebut (jika diaktifkan di project Firebase).

Dalam semua hal, parameter ini berfungsi seperti parameter string yang ditentukan pengguna. Namun, karena nilainya selalu diketahui oleh Firebase CLI, nilai tersebut tidak akan pernah diminta saat deployment atau disimpan ke file .env.

Parameter secret

Parameter jenis Secret, yang ditentukan menggunakan defineSecret(), mewakili parameter string yang memiliki nilai yang disimpan di Cloud Secret Manager. Alih-alih memeriksa file .env lokal dan menulis nilai baru ke file ini jika nilai tersebut tidak ada, parameter secret memeriksa keberadaan nilai di Cloud Secret Manager, dan secara interaktif meminta nilai secret baru selama deployment.

Parameter secret yang ditentukan dengan cara ini harus terikat dengan fungsi individual yang harus memiliki akses ke parameter tersebut:

const { onRequest } = require("functions/v2/https");
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');

export const posttodiscord = onRequest(
  { secrets: [discordApiKey] },
  (req, res) => {
    const apiKey = discordApiKey.value();
    //…

Karena nilai secret ini tersembunyi hingga fungsi dieksekusi, Anda tidak dapat menggunakannya saat mengonfigurasi fungsi.

Variabel lingkungan

Cloud Functions for Firebase mendukung format file dotenv untuk memuat variabel lingkungan yang ditentukan dalam file .env ke runtime aplikasi Anda. Setelah di-deploy, variabel lingkungan dapat dibaca melalui antarmuka process.env.

Untuk mengonfigurasi lingkungan dengan cara ini, buat file .env di project Anda, tambahkan variabel yang diinginkan, dan deploy:

  1. Buat file .env di direktori functions/ Anda:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. Buka file .env untuk mengedit, lalu tambahkan kunci yang diinginkan. Contoh:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. Deploy fungsi dan pastikan variabel lingkungan telah dimuat:

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

Setelah variabel lingkungan kustom di-deploy, kode fungsi Anda dapat mengaksesnya dengan sintaksis process.env:

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

Men-deploy beberapa kumpulan variabel lingkungan

Jika Anda memerlukan kumpulan variabel lingkungan alternatif untuk project Firebase (seperti staging vs. produksi), buat file .env.<project or alias> dan tulis variabel lingkungan khusus project di sana. Variabel lingkungan dari .env dan file .env khusus project (jika ada) akan disertakan dalam semua fungsi yang di-deploy.

Misalnya, project dapat menyertakan tiga file ini yang berisi nilai yang sedikit berbeda untuk pengembangan dan produksi:

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

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

Mengingat nilai dalam file terpisah tersebut, kumpulan variabel lingkungan yang di-deploy dengan fungsi Anda akan bervariasi, bergantung pada project target:

$ 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

Variabel lingkungan yang dicadangkan

Beberapa kunci variabel lingkungan dicadangkan untuk penggunaan internal. Jangan gunakan kunci berikut dalam file .env Anda:

  • Semua kunci yang dimulai dengan X_GOOGLE_
  • Semua kunci yang dimulai dengan EXT_
  • Semua kunci yang dimulai dengan FIREBASE_
  • Kunci apa pun dari daftar berikut:
  • 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

Menyimpan dan mengakses informasi konfigurasi yang sensitif

Variabel lingkungan yang disimpan dalam file .env dapat digunakan untuk konfigurasi fungsi, tetapi tidak boleh dianggap sebagai cara yang aman untuk menyimpan informasi sensitif seperti kredensial database atau kunci API. Hal ini penting jika Anda melakukan check in file .env ke dalam kontrol sumber.

Untuk membantu Anda menyimpan informasi konfigurasi yang sensitif, Cloud Functions for Firebase terintegrasi dengan Google Cloud Secret Manager. Layanan terenkripsi ini menyimpan nilai konfigurasi dengan aman, sekaligus mengizinkan akses mudah dari fungsi Anda saat diperlukan.

Membuat dan menggunakan secret

Untuk membuat secret, gunakan Firebase CLI.

Untuk membuat dan menggunakan secret:

  1. Dari root direktori project lokal, jalankan perintah berikut:

    firebase functions:secrets:set SECRET_NAME

  2. Masukkan nilai untuk SECRET_NAME.

    CLI akan menampilkan pesan berhasil dan memperingatkan bahwa Anda harus men-deploy fungsi agar perubahan diterapkan.

  3. Sebelum men-deploy, pastikan kode fungsi Anda mengizinkan fungsi tersebut mengakses secret menggunakan parameter runWith:

    const { onRequest } = require("functions/v2/https");
    
      exports.processpayment = onRequest(
        { secrets: ["SECRET_NAME"] },
        (data, context) => {
          const myBillingService = initializeBillingService(
            // reference the secret value
            process.env.SECRET_NAME
          );
          // Process the payment
        }
      );
  4. Deploy Cloud Functions:

    firebase deploy --only functions

Sekarang Anda dapat mengaksesnya seperti variabel lingkungan lainnya. Sebaliknya, jika fungsi lain yang tidak menentukan secret dalam runWith mencoba mengakses secret, fungsi tersebut akan menerima nilai yang tidak ditentukan:

exports.anotherendpoint = 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
});

Setelah di-deploy, fungsi tersebut akan memiliki akses ke nilai secret. Hanya fungsi yang secara khusus menyertakan secret dalam parameter runWith-nya yang akan memiliki akses ke secret tersebut sebagai variabel lingkungan. Cara ini membantu Anda memastikan bahwa nilai secret hanya tersedia di tempat yang diperlukan, sehingga mengurangi risiko kebocoran secret secara tidak sengaja.

Mengelola secret

Gunakan Firebase CLI untuk mengelola secret Anda. Saat mengelola secret dengan cara ini, perlu diingat bahwa beberapa perubahan CLI mengharuskan Anda untuk mengubah dan/atau men-deploy ulang fungsi-fungsi terkait. Secara khusus:

  • Setiap kali Anda menetapkan nilai baru untuk secret, Anda harus men-deploy ulang semua fungsi yang merujuk ke secret tersebut agar fungsi dapat mengambil nilai terbaru.
  • Jika Anda menghapus secret, pastikan tidak ada satu pun fungsi yang di-deploy merujuk ke secret tersebut. Fungsi yang menggunakan nilai secret yang telah dihapus akan gagal tanpa ada peringatan.

Berikut adalah ringkasan perintah Firebase CLI untuk pengelolaan 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

Untuk perintah access dan destroy, Anda dapat memberikan parameter versi opsional untuk mengelola versi tertentu. Contoh:

functions:secrets:access SECRET_NAME[@VERSION]

Untuk mengetahui informasi selengkapnya tentang operasi ini, teruskan -h dengan perintah untuk melihat bantuan CLI.

Cara penagihan secret

Secret Manager mengizinkan 6 versi secret aktif tanpa biaya. Artinya, Anda dapat memiliki 6 secret per bulan di project Firebase tanpa biaya.

Secara default, Firebase CLI berupaya secara otomatis menghancurkan versi secret yang tidak digunakan jika perlu, seperti ketika Anda men-deploy fungsi dengan versi secret baru. Selain itu, Anda dapat secara aktif membersihkan secret yang tidak digunakan menggunakan functions:secrets:destroy dan functions:secrets:prune.

Secret Manager mengizinkan 10.000 operasi akses bulanan yang tidak ditagih untuk sebuah secret. Instance fungsi hanya membaca secret yang ditentukan dalam parameter runWith-nya setiap kali cold start dilakukan padanya. Jika Anda memiliki banyak instance fungsi yang membaca banyak secret, project Anda dapat melebihi kuota ini, dan setelah itu Anda akan dikenai biaya $0,03 per 10.000 operasi akses.

Untuk mengetahui informasi selengkapnya, lihat Harga Secret Manager.

Dukungan emulator

Konfigurasi lingkungan dengan dotenv dirancang agar dapat saling beroperasi dengan emulator Cloud Functions lokal.

Saat menggunakan emulator Cloud Functions lokal, Anda dapat mengganti variabel lingkungan untuk project dengan menyiapkan file .env.local. Konten .env.local lebih diutamakan daripada .env dan file .env khusus project.

Misalnya, project dapat menyertakan tiga file ini yang berisi nilai yang sedikit berbeda untuk pengembangan dan pengujian lokal:

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

AUDIENCE=Humans

AUDIENCE=Dev Humans AUDIENCE=Local Humans

Saat dimulai dalam konteks lokal, emulator akan memuat variabel lingkungan seperti yang ditunjukkan berikut ini:

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

Secret dan kredensial di emulator Cloud Functions

Emulator Cloud Functions mendukung penggunaan secret untuk menyimpan dan mengakses informasi konfigurasi yang sensitif. Secara default, emulator akan mencoba mengakses secret produksi Anda menggunakan kredensial default aplikasi. Dalam situasi tertentu seperti lingkungan CI, emulator mungkin gagal mengakses nilai secret karena pembatasan izin.

Serupa dengan dukungan emulator Cloud Functions untuk variabel lingkungan, Anda dapat mengganti nilai secret dengan menyiapkan file .secret.local. Hal ini memudahkan Anda untuk menguji fungsi secara lokal, terutama jika Anda tidak memiliki akses ke nilai secret.