Testen Sie Ihre Cloud Firestore-Sicherheitsregeln

Während Sie Ihre App erstellen, möchten Sie möglicherweise den Zugriff auf Ihre Cloud Firestore-Datenbank sperren. Vor dem Start benötigen Sie jedoch differenziertere Cloud Firestore-Sicherheitsregeln. Mit dem Cloud Firestore - Emulator, zusätzlich zu Prototyping und Testen der App allgemeine Eigenschaften und das Verhaltens , können Sie Unit - Tests schreiben , die das Verhalten Ihrer Wolke Firestor Sicherheitsregeln überprüfen.

Schnellstart

Für ein paar grundlegenden Testfälle mit einfachen Regeln, versuchen , die aus quickstart Probe .

Informationen zu Cloud Firestore-Sicherheitsregeln

Implementieren Firebase - Authentifizierung und Cloud - Firestor Sicherheitsregeln für serverless Authentifizierung, Autorisierung und Datenvalidierung , wenn Sie die mobilen und Web - Client - Bibliotheken verwenden.

Cloud Firestore-Sicherheitsregeln umfassen zwei Teile:

  1. Ein match Aussage , dass identifiziert Dokumente in Ihrer Datenbank.
  2. Ein allow Ausdruck , dass die Kontrollen auf diese Dokumente zugreifen.

Firebase Authentication überprüft die Anmeldeinformationen der Benutzer und bietet die Grundlage für benutzer- und rollenbasierte Zugriffssysteme.

Jede Datenbankanfrage von einer Cloud Firestore-Mobil-/Webclientbibliothek wird anhand Ihrer Sicherheitsregeln bewertet, bevor Daten gelesen oder geschrieben werden. Wenn die Regeln den Zugriff auf einen der angegebenen Dokumentpfade verweigern, schlägt die gesamte Anforderung fehl.

Erfahren Sie mehr über Cloud - Firestor Sicherheitsregeln in Beginnen Sie mit Cloud - Firestor Sicherheitsregeln gestartet .

Installieren Sie den Emulator

Um die Wolke Firestore - Emulator zu installieren, die verwenden Firebase CLI und den Befehl ausführen unten:

firebase setup:emulators:firestore

Führen Sie den Emulator aus

Beginnen Sie mit der Initialisierung eines Firebase-Projekts in Ihrem Arbeitsverzeichnis. Dies ist ein gemeinsamer erster Schritt , wenn die CLI Firebase verwendet .

firebase init

Starten Sie den Emulator mit dem folgenden Befehl. Der Emulator wird ausgeführt, bis Sie den Prozess beenden:

firebase emulators:start --only firestore

In vielen Fällen möchten Sie den Emulator starten, eine Testsuite ausführen und den Emulator nach der Ausführung der Tests herunterfahren. Sie können dies leicht tun , um die Verwendung von emulators:exec - Befehl:

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

Beim Start versucht der Emulator, auf einem Standardport (8080) zu laufen. Sie können den Emulator - Port ändern , um die durch Modifizieren "emulators" Abschnitt Ihrer firebase.json - Datei:

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

Bevor Sie den Emulator ausführen

Beachten Sie Folgendes, bevor Sie den Emulator verwenden:

  • Der Emulator lädt zunächst die angegebenen Regeln im firestore.rules Feld Ihrer firebase.json Datei. Es erwartet den Namen einer lokalen Datei, die Ihre Cloud Firestore-Sicherheitsregeln enthält, und wendet diese Regeln auf alle Projekte an. Wenn Sie nicht über den lokalen Dateipfad bereitstellen oder verwenden Sie das loadFirestoreRules Verfahren , wie unten beschrieben, der Emulator behandelt alle Projekte als offene Regeln haben.
  • Während der meisten Firebase SDKs Arbeit mit den Emulatoren direkt nur die @firebase/rules-unit-testing Bibliothek unterstützt spöttische auth in Sicherheitsregeln, so dass Unit - Tests viel einfacher. Darüber hinaus unterstützt die Bibliothek einige emulatorspezifische Funktionen wie das Löschen aller Daten, wie unten aufgeführt.
  • Die Emulatoren akzeptieren auch über Client-SDKs bereitgestellte Firebase-Authentifizierungstokens für die Produktion und werten die Regeln entsprechend aus, sodass Ihre Anwendung bei Integrations- und manuellen Tests direkt mit den Emulatoren verbunden werden kann.

Führen Sie lokale Komponententests durch

Führen Sie lokale Komponententests mit dem v9 JavaScript SDK aus

Firebase vertreibt sowohl mit dem JavaScript-SDK der Version 9 als auch mit dem SDK der Version 8 eine Unit-Testing-Bibliothek für Sicherheitsregeln. Die Bibliotheks-APIs unterscheiden sich erheblich. Wir empfehlen die v9-Testbibliothek, die schlanker ist und weniger Setup erfordert, um eine Verbindung zu Emulatoren herzustellen und so die versehentliche Verwendung von Produktionsressourcen sicher zu vermeiden. Aus Gründen der Abwärtskompatibilität, fahren wir fort , die machen v8 Test Bibliothek zur Verfügung .

Verwenden Sie die @firebase/rules-unit-testing Modul interagieren mit dem Emulator, läuft lokal. Wenn Sie erhalten Timeouts oder ECONNREFUSED Fehler, überprüfen Sie, dass der Emulator tatsächlich ausgeführt wird .

Wir empfehlen dringend , eine aktuelle Version von Node.js verwenden , so dass Sie verwenden können , async/await Notation. Fast das gesamte Verhalten, das Sie möglicherweise testen möchten, umfasst asynchrone Funktionen, und das Testmodul wurde für die Arbeit mit Promise-basiertem Code entwickelt.

Die v9 Rules Unit Testing Library kennt die Emulatoren immer und greift niemals Ihre Produktionsressourcen an.

Sie importieren die Bibliothek mithilfe modularer Importanweisungen von v9. Zum Beispiel:

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.

Nach dem Import umfasst die Implementierung von Unit-Tests Folgendes:

  • Erstellen und Konfigurieren von RulesTestEnvironment mit einem Aufruf an initializeTestEnvironment .
  • Einrichten von Testdaten ohne Auslösung Regeln, eine bequeme Methode , die Sie vorübergehend Bypass ihnen erlaubt, RulesTestEnvironment.withSecurityRulesDisabled .
  • Einrichten von Testsuite und pro-Test vor / nach dem Haken mit Anruf Testdaten zu bereinigen und Umwelt, wie RulesTestEnvironment.cleanup() oder RulesTestEnvironment.clearFirestore() .
  • Die Implementierung von Testfällen , dass Mimik Authentifizierung Zustände mit RulesTestEnvironment.authenticatedContext und RulesTestEnvironment.unauthenticatedContext .

Gängige Methoden und Hilfsfunktionen

Siehe auch Emulator spezifische Testmethoden in der v9 SDK .

initializeTestEnvironment() => RulesTestEnvironment

Diese Funktion initialisiert eine Testumgebung für Regelkomponententests. Rufen Sie diese Funktion zuerst zum Testaufbau auf. Für eine erfolgreiche Ausführung müssen Emulatoren ausgeführt werden.

Die Funktion übernimmt ein optionales Objekt definiert eine TestEnvironmentConfig , die aus einem Projekt - ID und Emulators Konfigurationseinstellungen bestehen können.

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

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

Dieses Verfahren erzeugt eine RulesTestContext , die verhält sich wie ein Authentifizierungs Benutzer authentifiziert. Anforderungen, die über den zurückgegebenen Kontext erstellt werden, haben ein angehängtes Schein-Authentifizierungstoken. Übergeben Sie optional ein Objekt, das benutzerdefinierte Ansprüche oder Überschreibungen für Authentifizierungstoken-Nutzlasten definiert.

Benutzen Sie das zurückgegebene Testkontextobjekt in Ihren Tests für den Zugriff alle Emulator Instanzen konfiguriert, einschließlich derjenigen , konfiguriert mit 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

Dieses Verfahren erzeugt eine RulesTestContext , die verhält sich wie ein Client, der in über Authentifizierung nicht angemeldet ist. An Anfragen, die über den zurückgegebenen Kontext erstellt werden, werden keine Firebase Auth-Token angehängt.

Benutzen Sie das zurückgegebene Testkontextobjekt in Ihren Tests für den Zugriff alle Emulator Instanzen konfiguriert, einschließlich derjenigen , konfiguriert mit 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()

Führen Sie eine Test-Setup-Funktion mit einem Kontext aus, der sich so verhält, als ob Sicherheitsregeln deaktiviert wären.

Diese Methode verwendet eine Rückruffunktion, die den Kontext zur Umgehung von Sicherheitsregeln verwendet und eine Zusage zurückgibt. Der Kontext wird zerstört, sobald das Versprechen aufgelöst / abgelehnt wird.

RulesTestEnvironment.cleanup()

Dieses Verfahren zerstört alle RulesTestContexts in der Testumgebung erstellt und die zugrunde liegenden Ressourcen bereinigt, einen sauberen Ausgang ermöglicht.

Diese Methode ändert den Status von Emulatoren in keiner Weise. Verwenden Sie zum Zurücksetzen von Daten zwischen Tests die anwendungsemulatorspezifische Methode zum Löschen von Daten.

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

Dies ist eine Testfall-Hilfsfunktion.

Die Funktion bestätigt, dass das bereitgestellte Versprechen, das einen Emulatorvorgang umschließt, ohne Verletzungen der Sicherheitsregeln aufgelöst wird.

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

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

Dies ist eine Testfall-Hilfsfunktion.

Die Funktion bestätigt, dass das bereitgestellte Promise, das einen Emulatorvorgang umschließt, mit einer Verletzung der Sicherheitsregeln abgelehnt wird.

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

Emulatorspezifische Methoden

Siehe auch gemeinsame Testmethoden und Utility - Funktionen im v9 SDK .

RulesTestEnvironment.clearFirestore() => Promise<void>

Dieses Verfahren löscht Daten in der Datenbank , die Firestore zu dem gehört projectId konfiguriert für den Emulator Firestore.

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

Diese Methode ruft eine Firestore-Instanz für diesen Testkontext ab. Die zurückgegebene Firebase JS Client SDK-Instanz kann mit den Client-SDK-APIs (v9 modular oder v9 compat) verwendet werden.

Regelauswertungen visualisieren

Mit dem Cloud Firestore-Emulator können Sie Clientanfragen in der Emulator Suite-Benutzeroberfläche visualisieren, einschließlich Auswertungs-Tracing für Firebase-Sicherheitsregeln.

Öffnen Sie die Firestore> Gesuche Registerkarte der detaillierten Auswertung Sequenz für jede Anforderung anzuzeigen.

Firestore Emulator Requests Monitor mit Auswertungen zu Sicherheitsregeln

Testberichte erstellen

Nachdem Sie eine Reihe von Tests ausgeführt haben, können Sie auf Testabdeckungsberichte zugreifen, die zeigen, wie jede Ihrer Sicherheitsregeln bewertet wurde.

Um die Berichte abzurufen, fragen Sie einen verfügbar gemachten Endpunkt auf dem Emulator ab, während er ausgeführt wird. Verwenden Sie für eine browserfreundliche Version die folgende URL:

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

Dadurch werden Ihre Regeln in Ausdrücke und Unterausdrücke unterteilt, über die Sie mit der Maus bewegen können, um weitere Informationen zu erhalten, einschließlich der Anzahl der zurückgegebenen Auswertungen und Werte. Fügen Sie für die JSON-Rohversion dieser Daten die folgende URL in Ihre Abfrage ein:

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

Unterschiede zwischen Emulator und Produktion

  1. Sie müssen kein Cloud Firestore-Projekt explizit erstellen. Der Emulator erstellt automatisch jede Instanz, auf die zugegriffen wird.
  2. Der Cloud Firestore-Emulator funktioniert nicht mit dem normalen Firebase Authentication-Ablauf. Stattdessen wird in der Test - SDK Firebase haben wir die zur Verfügung gestellt initializeTestApp() Methode in der rules-unit-testing - Bibliothek, die eine nimmt auth Feld. Das mit dieser Methode erstellte Firebase-Handle verhält sich so, als ob es sich erfolgreich als jede von Ihnen bereitgestellte Entität authentifiziert hätte. Wenn Sie in geben null , wird es als nicht authentifizierter Benutzer verhalten ( auth != null Regeln werden fehlschlagen, zum Beispiel).

Beheben bekannter Probleme

Bei der Verwendung des Cloud Firestore-Emulators können die folgenden bekannten Probleme auftreten. Befolgen Sie die nachstehende Anleitung, um unregelmäßiges Verhalten zu beheben. Diese Hinweise wurden unter Berücksichtigung der Komponententestbibliothek für Sicherheitsregeln geschrieben, aber die allgemeinen Ansätze gelten für jedes Firebase SDK.

Testverhalten ist inkonsistent

Wenn Ihre Tests gelegentlich bestehen und fehlschlagen, müssen Sie möglicherweise auch ohne Änderungen an den Tests selbst überprüfen, ob sie richtig sequenziert sind. Die meisten Interaktionen mit dem Emulator sind asynchron, also überprüfen Sie noch einmal, ob der gesamte asynchrone Code richtig sequenziert ist. Sie können die Sequenzierung beheben , indem entweder Versprechungen oder mit Chaining await Notation liberal.

Überprüfen Sie insbesondere die folgenden asynchronen Vorgänge:

  • Festlegen von Sicherheitsregeln, mit zum Beispiel initializeTestEnvironment .
  • Das Lesen und Schreiben von Daten, mit zum Beispiel db.collection("users").doc("alice").get() .
  • Operative Behauptungen, einschließlich assertSucceeds und assertFails .

Tests bestehen nur beim ersten Laden des Emulators

Der Emulator ist zustandsbehaftet. Es speichert alle darauf geschriebenen Daten im Speicher, sodass alle Daten verloren gehen, wenn der Emulator heruntergefahren wird. Wenn Sie mehrere Tests für dieselbe Projekt-ID ausführen, kann jeder Test Daten erzeugen, die nachfolgende Tests beeinflussen können. Sie können dieses Verhalten mit einer der folgenden Methoden umgehen:

  • Verwenden Sie für jeden Test eindeutige Projekt-IDs. Beachten Sie , wenn Sie sich dazu entscheiden , dies zu tun Sie anrufen müssen initializeTestEnvironment als Teil jeden Test; Regeln werden nur für die Standardprojekt-ID automatisch geladen.
  • Strukturieren Sie Ihre Tests neu, damit sie nicht mit zuvor geschriebenen Daten interagieren (verwenden Sie beispielsweise für jeden Test eine andere Sammlung).
  • Löschen Sie alle während eines Tests geschriebenen Daten.

Testaufbau ist sehr kompliziert

Beim Einrichten Ihres Tests möchten Sie möglicherweise Daten so ändern, dass Ihre Cloud Firestore-Sicherheitsregeln dies nicht zulassen. Wenn Sie Ihre Regeln Testaufbau komplexer machen, versuchen Sie es mit RulesTestEnvironment.withSecurityRulesDisabled in Ihrem Setup - Schritte, so liest und schreibt nicht ausgelöst PERMISSION_DENIED Fehler.

Danach können Sie Ihre Testoperationen als authentifizierter oder nicht authentifizierte Benutzer unter Verwendung ausführen RulesTestEnvironment.authenticatedContext und unauthenticatedContext sind. Auf diese Weise können Sie überprüfen, ob Ihre Cloud Firestore-Sicherheitsregeln verschiedene Fälle korrekt zulassen/verweigern.