Catch up on everthing we announced at this year's Firebase Summit. Learn more

Testa le regole di sicurezza di Cloud Firestore

Durante la creazione della tua app, potresti voler bloccare l'accesso al tuo database Cloud Firestore. Tuttavia, prima di avviare, avrai bisogno di regole di sicurezza Cloud Firestore più sfumate. Con l'emulatore Nuvola FireStore, oltre a prototipazione e test del vostro app caratteristiche generali e il comportamento , è possibile scrivere unit test che controllano il comportamento dei vostri Firestore Regole di sicurezza cloud.

Avvio veloce

Per un paio di casi di test di base con regole semplici, provare l' esempio delle Guide rapide .

Comprendi le regole di sicurezza di Cloud Firestore

Implementare Firebase autenticazione e Firestore Regole di sicurezza cloud per l'autenticazione senza server, l'autorizzazione e convalida dei dati quando si utilizzano le librerie client mobile e web.

Le regole di sicurezza di Cloud Firestore includono due parti:

  1. Una match dichiarazione che identifica i documenti nel database.
  2. Un allow espressione che controlla l'accesso a tali documenti.

L'autenticazione Firebase verifica le credenziali degli utenti e fornisce le basi per i sistemi di accesso basati su utenti e ruoli.

Ogni richiesta di database da una libreria client mobile/web di Cloud Firestore viene valutata rispetto alle tue regole di sicurezza prima di leggere o scrivere qualsiasi dato. Se le regole negano l'accesso a uno qualsiasi dei percorsi di documenti specificati, l'intera richiesta ha esito negativo.

Scopri di più su cloud Regole Firestore sicurezza in Inizia con la nube Firestore Regole di sicurezza .

Installa l'emulatore

Per installare l'emulatore cloud FireStore, utilizzare la Firebase CLI ed eseguire il seguente comando:

firebase setup:emulators:firestore

Esegui l'emulatore

Inizia inizializzando un progetto Firebase nella tua directory di lavoro. Questo è un primo passo comune quando utilizza il Firebase CLI .

firebase init

Avvia l'emulatore usando il seguente comando. L'emulatore verrà eseguito fino a quando non interrompi il processo:

firebase emulators:start --only firestore

In molti casi si desidera avviare l'emulatore, eseguire una suite di test e quindi spegnere l'emulatore dopo l'esecuzione dei test. Lo si può fare facilmente utilizzando i emulators:exec comando:

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

Una volta avviato, l'emulatore tenterà di funzionare su una porta predefinita (8080). È possibile modificare la porta emulatore modificando il "emulators" sezione del firebase.json di file:

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

Prima di eseguire l'emulatore

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

  • L'emulatore inizialmente caricare le regole specificate nel firestore.rules campo del vostro firebase.json file. Si aspetta il nome di un file locale contenente le regole di sicurezza di Cloud Firestore e applica tali regole a tutti i progetti. Se non si fornisce il percorso di file locale o utilizzare il loadFirestoreRules metodo descritto qui di seguito, l'emulatore tratta tutti i progetti come avere regole aperte.
  • Mentre la maggior parte Firebase SDK lavoro con gli emulatori direttamente, solo il @firebase/rules-unit-testing supporti biblioteca beffardi auth nelle regole di sicurezza, facendo unit test molto più facile. Inoltre, la libreria supporta alcune funzionalità specifiche dell'emulatore come la cancellazione di tutti i dati, come elencato di seguito.
  • Gli emulatori accetteranno anche i token di autenticazione Firebase di produzione forniti tramite Client SDK e valuteranno le regole di conseguenza, il che consente di connettere l'applicazione direttamente agli emulatori nei test di integrazione e manuali.

Esegui test di unità locali

Esegui test di unità locali con JavaScript SDK v9

Firebase distribuisce una libreria di unit test delle regole di sicurezza sia con l'SDK JavaScript versione 9 che con l'SDK versione 8. Le API della libreria sono significativamente diverse. Consigliamo la libreria di test v9, che è più snella e richiede meno configurazione per connettersi agli emulatori e quindi evitare in modo sicuro l'uso accidentale delle risorse di produzione. Per la compatibilità a ritroso, continuiamo a fare la libreria di test v8 disponibili .

Utilizzare l' @firebase/rules-unit-testing del modulo di interagire con l'emulatore che corre a livello locale. Se si ottiene timeout o ECONNREFUSED errori, controllare che l'emulatore è effettivamente in esecuzione.

Si consiglia vivamente di utilizzare una versione recente di Node.js modo da poter utilizzare async/await la notazione. Quasi tutto il comportamento che potresti voler testare coinvolge funzioni asincrone e il modulo di test è progettato per funzionare con codice basato su Promise.

La libreria v9 Rules Unit Testing è sempre a conoscenza degli emulatori e non tocca mai le tue risorse di produzione.

Importi la libreria utilizzando istruzioni di importazione modulare v9. Per esempio:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
  RulesTestEnvironment,
} 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.

Una volta importati, l'implementazione degli unit test comporta:

  • Creazione e configurazione di un RulesTestEnvironment con una chiamata a initializeTestEnvironment .
  • Impostazione di dati di test senza attivare regole, utilizzando un metodo comodo che permette di by-pass temporaneo loro, RulesTestEnvironment.withSecurityRulesDisabled .
  • Impostazione di suite di test e per-test prima / dopo ganci con le chiamate per ripulire i dati di prova e l'ambiente, come RulesTestEnvironment.cleanup() o RulesTestEnvironment.clearFirestore() .
  • Implementazione di casi di test che simulano gli stati di autenticazione utilizzando RulesTestEnvironment.authenticatedContext e RulesTestEnvironment.unauthenticatedContext .

Metodi comuni e funzioni di utilità

Vedere anche i metodi di prova specifici per emulatore nel SDK v9 .

initializeTestEnvironment() => RulesTestEnvironment

Questa funzione inizializza un ambiente di test per l'unità di test delle regole. Chiamare prima questa funzione per l'impostazione del test. L'esecuzione corretta richiede che gli emulatori siano in esecuzione.

La funzione accetta un oggetto opzionale definente una TestEnvironmentConfig , che può essere costituito da un ID progetto e emulatore impostazioni di configurazione.

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 di autenticazione. Le richieste create tramite il contesto restituito avranno un token di autenticazione fittizio allegato. Facoltativamente, passare un oggetto che definisce attestazioni personalizzate o sostituzioni per i payload del token di autenticazione.

Utilizzare l'oggetto contesto di misura restituiti nei test per accedere a qualsiasi istanze dell'emulatore configurate, compresi quelli configurati 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 è connesso in via di autenticazione. Le richieste create tramite il contesto restituito non avranno token di autenticazione Firebase allegati.

Utilizzare l'oggetto contesto di misura restituiti nei test per accedere a qualsiasi istanze dell'emulatore configurate, compresi quelli configurati 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()

Eseguire una funzione di configurazione di prova con un contesto che si comporta come se le regole di sicurezza fossero disabilitate.

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

RulesTestEnvironment.cleanup()

Questo metodo distrugge tutti RulesTestContexts creati in ambiente di prova e pulisce le risorse di base, permettendo un'uscita pulita.

Questo metodo non modifica in alcun modo lo stato degli emulatori. Per ripristinare i dati tra i test, utilizzare il metodo di cancellazione dei dati specifico dell'emulatore dell'applicazione.

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

Questa è una funzione di utilità del caso di test.

La funzione afferma che il Promise fornito che avvolge un'operazione dell'emulatore verrà risolto senza violazioni delle regole di sicurezza.

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

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

Questa è una funzione di utilità del caso di test.

La funzione afferma che il Promise fornito che avvolge un'operazione dell'emulatore verrà rifiutato con una violazione delle regole di sicurezza.

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

Metodi specifici dell'emulatore

Vedere anche i metodi di prova comune e funzioni di utilità nel SDK v9 .

RulesTestEnvironment.clearFirestore() => Promise<void>

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

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

Questo metodo ottiene un'istanza Firestore per questo contesto di test. L'istanza di Firebase JS Client SDK restituita può essere utilizzata con le API dell'SDK client (v9 modular o v9 compat).

Visualizza le valutazioni delle regole

L'emulatore Cloud Firestore ti consente di visualizzare le richieste dei client nell'interfaccia utente di Emulator Suite, inclusa la traccia della valutazione per le regole di sicurezza Firebase.

Aprire la> scheda Richieste FireStore per visualizzare la sequenza di valutazione dettagliata per ogni richiesta.

Monitoraggio delle richieste dell'emulatore Firestore che mostra le valutazioni delle regole di sicurezza

Genera rapporti di prova

Dopo aver eseguito una serie di test, puoi accedere ai rapporti sulla copertura dei test che mostrano come è stata valutata ciascuna delle tue regole di sicurezza.

Per ottenere i report, eseguire una query su un endpoint esposto sull'emulatore mentre è in esecuzione. Per una versione compatibile con il browser, utilizzare il seguente URL:

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

Ciò suddivide le regole in espressioni e sottoespressioni su cui è possibile passare il mouse per ulteriori informazioni, incluso il numero di valutazioni e valori restituiti. Per la versione JSON non elaborata di questi dati, includi il seguente URL nella query:

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

Differenze tra l'emulatore e la produzione

  1. Non è necessario creare esplicitamente un progetto Cloud Firestore. L'emulatore crea automaticamente qualsiasi istanza a cui si accede.
  2. L'emulatore Cloud Firestore non funziona con il normale flusso di autenticazione Firebase. Invece, nel Firebase prova SDK, abbiamo predisposto initializeTestApp() metodo nella rules-unit-testing biblioteca, che prende un auth campo. L'handle Firebase creato utilizzando questo metodo si comporterà come se fosse stato autenticato correttamente come qualsiasi entità fornita. Se si passa a null , si comporterà come un utente non autenticato ( auth != null regole non riuscirà, per esempio).

Risolvere i problemi noti

Quando utilizzi l'emulatore Cloud Firestore, potresti riscontrare i seguenti problemi noti. Segui le indicazioni di seguito per risolvere eventuali comportamenti irregolari che stai riscontrando. Queste note sono scritte tenendo presente la libreria di unit test delle regole di sicurezza, ma gli approcci generali sono applicabili a qualsiasi Firebase SDK.

Il comportamento del test è incoerente

Se i tuoi test occasionalmente passano e falliscono, anche senza alcuna modifica ai test stessi, potrebbe essere necessario verificare che siano correttamente sequenziati. La maggior parte delle interazioni con l'emulatore sono asincrone, quindi ricontrolla che tutto il codice asincrono sia sequenziato correttamente. È possibile correggere la sequenza con il concatenamento o promesse, o utilizzando await la notazione liberalmente.

In particolare, esaminare le seguenti operazioni asincrone:

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

I test vengono superati solo la prima volta che si carica l'emulatore

L'emulatore è stateful. Memorizza tutti i dati scritti su di esso in memoria, quindi tutti i dati vengono persi ogni volta che l'emulatore si spegne. Se stai eseguendo più test sullo stesso ID progetto, ogni test può produrre dati che potrebbero influenzare i test successivi. È possibile utilizzare uno dei seguenti metodi per ignorare questo comportamento:

  • Utilizza ID progetto univoci per ogni test. Si noti che se si sceglie di fare questo è necessario chiamare initializeTestEnvironment come parte di ogni prova; le regole vengono caricate automaticamente solo per l'ID progetto predefinito.
  • Ristruttura i tuoi test in modo che non interagiscano con i dati scritti in precedenza (ad esempio, usa 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 le regole di sicurezza di Cloud Firestore non consentono effettivamente. Se le regole stanno facendo complessa configurazione di prova, provare a utilizzare RulesTestEnvironment.withSecurityRulesDisabled nelle fasi di configurazione, in modo da letture e scritture non attivano PERMISSION_DENIED errori.

Dopo di che, il test può eseguire operazioni come un utente autenticato o non autenticato utilizzando RulesTestEnvironment.authenticatedContext e unauthenticatedContext rispettivamente. Ciò ti consente di convalidare che le regole di sicurezza di Cloud Firestore consentano/rifiutino correttamente diversi casi.