Testa le regole di sicurezza di Cloud Firestore

Durante lo sviluppo dell'app, potrebbe essere opportuno bloccare l'accesso ai tuoi Cloud Firestore database. Tuttavia, prima del lancio, avrai bisogno di informazioni Cloud Firestore Security Rules. Con l'emulatore Cloud Firestore, oltre a creare prototipi e testare le funzionalità e il comportamento generali della tua app, puoi scrivere test di unità che controllano il comportamento del tuo Cloud Firestore Security Rules.

Guida rapida

Per alcuni casi di test di base con regole semplici, prova l'esempio di avvio rapido.

Informazioni su Cloud Firestore Security Rules

Implementa Firebase Authentication e Cloud Firestore Security Rules per l'autenticazione, l'autorizzazione e la convalida dei dati serverless quando utilizzi le librerie client web e per dispositivi mobili.

Cloud Firestore Security Rules sono costituiti da due parti:

  1. Un'istruzione match che identifica i documenti nel database.
  2. Un'espressione allow che controlla l'accesso a questi documenti.

Firebase Authentication verifica l'identità credenziali e fornisce le basi sistemi di accesso basati su utenti e ruoli.

Ogni richiesta di database da una libreria client mobile/web Cloud Firestore viene valutato in base alle regole di sicurezza prima di leggere o scrivere dati. Se le regole negano l'accesso a uno qualsiasi dei percorsi dei documenti specificati, l'intera non va a buon fine.

Scopri di più su Cloud Firestore Security Rules in Iniziare a utilizzare Cloud Firestore Security Rules.

Installa l'emulatore

Per installare l'emulatore Cloud Firestore, utilizza Firebase CLI ed esegui questo comando:

firebase setup:emulators:firestore

Esegui l'emulatore

Inizia inizializzando un progetto Firebase nella directory di lavoro. Si tratta di un primo passaggio comune quando utilizzi l'interfaccia a riga di comando di Firebase.

firebase init

Avvia l'emulatore utilizzando il seguente comando. L'emulatore eseguirà finché il processo non termina:

firebase emulators:start --only firestore

In molti casi si desidera avviare l'emulatore, eseguire una suite di test e quindi chiudere l'emulatore dopo l'esecuzione dei test. Puoi farlo facilmente utilizzando Comando emulators:exec:

firebase emulators:exec --only firestore "./my-test-script.sh"

All'avvio, l'emulatore tenterà di funzionare su una porta predefinita (8080). Puoi cambia la porta dell'emulatore modificando la sezione "emulators" del tuo firebase.json file:

{
  // ...
  "emulators": {
    "firestore": {
      "port": "YOUR_PORT"
    }
  }
}

Prima di eseguire l'emulatore

Prima di iniziare a utilizzare l'emulatore, tieni presente quanto segue:

  • L'emulatore caricherà inizialmente le regole specificate nel campo firestore.rules campo del tuo file firebase.json. Aspetta il nome di un file locale contenente il tuo Cloud Firestore Security Rules e applica queste regole a tutti i progetti. Se non fornisci il percorso file locale o utilizzi il comando loadFirestoreRules come descritto di seguito, l'emulatore tratta tutti progetti con regole aperte.
  • Anche se la maggior parte degli SDK di Firebase funziona direttamente con gli emulatori, solo la libreria @firebase/rules-unit-testing supporta la simulazione di auth nelle regole di sicurezza, semplificando notevolmente i test di unità. Inoltre, la libreria supporta alcune funzioni specifiche dell'emulatore, come la cancellazione di tutti i dati, come indicato di seguito.
  • Gli emulatori accetteranno anche i token di autenticazione Firebase di produzione forniti tramite SDK client e valutano di conseguenza le regole, il che consente la connessione la tua applicazione direttamente agli emulatori nei test di integrazione e manuali.

Esecuzione dei test delle unità locali

Esecuzione dei test delle unità locali con l'SDK JavaScript v9

Firebase distribuisce una libreria di test delle unità di Regole di sicurezza sia con la relativa versione SDK JavaScript 9 e versione 8 dell'SDK. Le API della libreria sono significativamente diverso. Consigliamo la libreria di test v9, che è più semplice e richiede meno configurazione per connettersi agli emulatori e quindi evita all'uso delle risorse di produzione. Per garantire la compatibilità con le versioni precedenti, la libreria di test v8 disponibile.

Usa il modulo @firebase/rules-unit-testing per interagire con l'emulatore eseguito in locale. Se visualizzi timeout o ECONNREFUSED errori, ricontrolla che l'emulatore è effettivamente in esecuzione.

Ti consigliamo vivamente di utilizzare una versione recente di Node.js in modo da poter utilizzare Notazione async/await. Quasi tutti i comportamenti che potresti voler testare richiedono funzioni asincrone e il modulo di test è progettato per funzionare con il codice basato su promesse.

La libreria di test delle unità delle regole v9 è sempre a conoscenza degli emulatori e non le risorse di produzione.

Puoi importare la libreria utilizzando le istruzioni di importazione modulari v9. Ad esempio:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment
} from "@firebase/rules-unit-testing"

// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.

Dopo l'importazione, l'implementazione dei test delle unità comporta:

  • Creazione e configurazione di un RulesTestEnvironment con una chiamata a initializeTestEnvironment.
  • Configurare i dati di test senza attivare le regole, per praticità che ti consente di ignorarli temporaneamente, RulesTestEnvironment.withSecurityRulesDisabled.
  • Configurazione di suite di test e hook prima/dopo per test con chiamate per pulizia dei dati e dell'ambiente di test, ad esempio RulesTestEnvironment.cleanup() o RulesTestEnvironment.clearFirestore().
  • Implementazione di scenari di test che imitano gli stati di autenticazione utilizzando RulesTestEnvironment.authenticatedContext e RulesTestEnvironment.unauthenticatedContext.
di Gemini Advanced.

Metodi comuni e funzioni di utilità

Vedi anche i metodi di test specifici dell'emulatore nell'SDK v9.

initializeTestEnvironment() => RulesTestEnvironment

Questa funzione inizializza un ambiente di test per il test delle unità di regole. Chiama per la configurazione di test. Per una corretta esecuzione è necessario che gli emulatori in esecuzione.

La funzione accetta un oggetto facoltativo che definisce un valore TestEnvironmentConfig, che può essere composto da un ID progetto e dalle impostazioni di configurazione dell'emulatore.

let testEnv = await initializeTestEnvironment({
  projectId: "demo-project-1234",
  firestore: {
    rules: fs.readFileSync("firestore.rules", "utf8"),
  },
});

RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext

Questo metodo crea un RulesTestContext, che si comporta come un utente autenticato Utente autenticazione. Le richieste create tramite il contesto restituito avranno una simulazione Token di autenticazione collegato. Se vuoi, passa un oggetto che definisce rivendicazioni personalizzate per i payload dei token di autenticazione.

Utilizza l'oggetto contesto test restituito nei test per accedere a eventuali istanze di emulatore configurate, incluse quelle configurate con initializeTestEnvironment.

// Assuming a Firestore app and the Firestore emulator for this example
import { setDoc } from "firebase/firestore";

const alice = testEnv.authenticatedContext("alice", {  });
// Use the Firestore instance associated with this context
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

RulesTestEnvironment.unauthenticatedContext() => RulesTestContext

Questo metodo crea un RulesTestContext, che si comporta come un client che non hanno effettuato l'accesso tramite Authentication. Le richieste create tramite il contesto restituito collegati dei token di autenticazione Firebase.

Utilizza l'oggetto contesto test restituito nei test per accedere a eventuali istanze di emulatore configurate, incluse quelle configurate con initializeTestEnvironment.

// Assuming a Cloud Storage app and the Storage emulator for this example
import { getStorage, ref, deleteObject } from "firebase/storage";

const alice = testEnv.unauthenticatedContext();

// Use the Cloud Storage instance associated with this context
const desertRef = ref(alice.storage(), 'images/desert.jpg');
await assertSucceeds(deleteObject(desertRef));

RulesTestEnvironment.withSecurityRulesDisabled()

Esegui una funzione di configurazione di test con un contesto che si comporti come se le regole di sicurezza fossero disattivata.

Questo metodo accetta una funzione di callback, che accetta il contesto di aggiramento delle regole di sicurezza e restituisce una promessa. Il contesto verrà distrutto una volta che la promessa risolve / rifiuta.

RulesTestEnvironment.cleanup()

Questo metodo elimina tutti i RulesTestContexts creati nell'ambiente di test e pulizia delle risorse sottostanti, consentendo un'uscita pulita.

Questo metodo non modifica in alcun modo lo stato degli emulatori. Per reimpostare i dati tra i test, usa il metodo dei dati in chiaro specifico dell'emulatore di applicazioni.

assertSucceeds(pr: Promise<any>)) => Promise<any>

Questa è una funzione di utilità per i casi di test.

La funzione asserisce che la Promise fornita che aggrega un'operazione dell'emulatore verrà risolta senza violazioni delle regole di sicurezza.

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

Questa è una funzione di utilità per i casi di test.

La funzione asserisce che la Promise fornita che aggrega un'operazione dell'emulatore verranno rifiutate con una violazione delle Regole di sicurezza.

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

Metodi specifici dell'emulatore

Consulta anche i metodi di test e le funzioni di utilità comuni nell'SDK versione 9.

RulesTestEnvironment.clearFirestore() => Promise<void>

Questo metodo cancella i dati nel database Firestore che appartiene al projectId configurato per l'emulatore Firestore.

RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;

Questo metodo ottiene un'istanza Firestore per il contesto di test. L'oggetto restituito L'istanza SDK client JS di Firebase può essere utilizzata con le API SDK client (v9 modulare o v9).

Visualizzare le valutazioni delle regole

L'emulatore Cloud Firestore ti consente di visualizzare le richieste del client l'interfaccia utente di Emulator Suite, con il tracciamento della valutazione per le regole di sicurezza di Firebase.

Apri Firestore > Richieste per visualizzare la valutazione dettagliata una sequenza per ogni richiesta.

Monitor delle richieste dell&#39;emulatore Firestore che mostra le valutazioni delle regole di sicurezza

Genera report sui test

Dopo aver eseguito una suite di test, puoi accedere e report sulla copertura che mostrano come è stata valutata ciascuna delle tue regole di sicurezza.

Per ottenere i report, esegui una query su un endpoint esposto sull'emulatore sia in esecuzione. Per una versione ottimizzata per il browser, utilizza il seguente URL:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html

In questo modo, le regole vengono suddivise in espressioni e sottoespressioni su cui puoi eseguire il passaggio del mouse per visualizzare ulteriori informazioni, tra cui il numero di valutazioni e i valori restituiti. Per la versione JSON non elaborata di questi dati, includi il seguente URL nella tua query:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage

Differenze tra emulatore e produzione

  1. Non è necessario creare esplicitamente un progetto Cloud Firestore. L'emulatore crea automaticamente qualsiasi istanza a cui viene eseguito l'accesso.
  2. L'emulatore Cloud Firestore non funziona con il normale flusso Firebase Authentication. Nell'SDK Firebase Test abbiamo invece fornito il metodo initializeTestApp() nella rules-unit-testing, che richiede un campo auth. L'handle Firebase è stato creato questo metodo si comporterà come se l'autenticazione sia riuscita indipendentemente dall'entità che fornisci. Se lo superi in null, si comporterà come un utente non autenticato (ad esempio, auth != null regole non andranno a buon fine).

Risolvere i problemi noti

Quando utilizzi l'emulatore Cloud Firestore, potresti riscontrare quanto segue che le applicazioni presentino problemi di prestazioni. Segui le indicazioni riportate di seguito per risolvere i tuoi comportamenti irregolari in cui ti trovi. Queste note sono scritte con il test dell'unità Regole di sicurezza ma gli approcci generali sono applicabili a qualsiasi SDK Firebase.

Il comportamento del test non è coerente

Se occasionalmente i test non vanno a buon fine, anche senza alcuna modifica alle potrebbe essere necessario verificare che siano sequenziati correttamente. La maggior parte delle interazioni con l'emulatore è asincrona, quindi verifica che tutte il codice asincrono sia sequenziato correttamente. Puoi correggere la sequenzialità concatenando le promesse o utilizzando liberamente la notazione await.

In particolare, esamina le seguenti operazioni asincrone:

  • Impostazione di regole di sicurezza, con, ad esempio, initializeTestEnvironment.
  • Lettura e scrittura di dati, ad esempio con db.collection("users").doc("alice").get().
  • Affermazioni operative, tra cui assertSucceeds e assertFails.

I test passano solo la prima volta che carichi l'emulatore

L'emulatore è stateful. Tutti i dati scritti vengono memorizzati in memoria, ogni volta che l'emulatore si arresta vengono persi i dati. Se esegui più test sullo stesso ID progetto, ogni test può produrre dati che potrebbero influire sui test successivi. Per ignora questo comportamento:

  • Utilizza ID progetto univoci per ogni test. Tieni presente che, se scegli questa opzione, dovrà chiamare initializeTestEnvironment nell'ambito di ogni test; regole vengono caricati automaticamente solo per l'ID progetto predefinito.
  • Ristruttura i test in modo che non interagiscano con dati scritti in precedenza (ad esempio, utilizza una raccolta diversa per ogni test).
  • Elimina tutti i dati scritti durante un test.

La configurazione del test è molto complicata

Quando configuri il test, potresti voler modificare i dati in un modo che Cloud Firestore Security Rules non consente. Se le regole eseguono la configurazione di prova complesso, prova a usare RulesTestEnvironment.withSecurityRulesDisabled nella configurazione passaggi, quindi le operazioni di lettura e scrittura non attiveranno PERMISSION_DENIED errori.

In seguito, il test potrà eseguire operazioni come autenticazione utente che utilizza RulesTestEnvironment.authenticatedContext e unauthenticatedContext rispettivamente. In questo modo puoi verificare che Cloud Firestore Security Rules consenta o rifiuti casi diversi.