अपने Cloud Firestore के सुरक्षा नियमों की जांच करें

ऐप्लिकेशन बनाते समय, हो सकता है कि आप अपने Cloud Firestore डेटाबेस के ऐक्सेस को लॉक करना चाहें. हालांकि, लॉन्च करने से पहले आपको ज़्यादा जानकारी इकट्ठा करनी होगी Cloud Firestore Security Rules. Cloud Firestore एम्युलेटर की मदद से, अपने ऐप्लिकेशन की सामान्य सुविधाओं और व्यवहार के प्रोटोटाइप बनाने और उन्हें टेस्ट करने के अलावा, आपके पास यूनिट टेस्ट करने का भी विकल्प होता है. इससे यह पता लगाया जा सकता है कि आपके Cloud Firestore Security Rules का व्यवहार कैसा है.

क्विकस्टार्ट

आसान नियमों वाले कुछ बुनियादी टेस्ट केस के लिए, क्विकस्टार्ट सैंपल आज़माएं.

Cloud Firestore Security Rules के बारे में जानें

मोबाइल और वेब क्लाइंट लाइब्रेरी का इस्तेमाल करते समय, सर्वर के बिना पुष्टि करने, अनुमति देने, और डेटा की पुष्टि करने के लिए, Firebase Authentication और Cloud Firestore Security Rules को लागू करें.

Cloud Firestore Security Rules में दो हिस्से शामिल हैं:

  1. match स्टेटमेंट, जो आपके डेटाबेस में मौजूद दस्तावेज़ों की पहचान करता है.
  2. उन दस्तावेज़ों का ऐक्सेस कंट्रोल करने वाला allow एक्सप्रेशन.

Firebase Authentication, उपयोगकर्ताओं के क्रेडेंशियल की पुष्टि करता है. साथ ही, उपयोगकर्ता और भूमिका के आधार पर ऐक्सेस देने वाले सिस्टम के लिए बुनियादी सुविधाएं उपलब्ध कराता है.

Cloud Firestore मोबाइल/वेब क्लाइंट लाइब्रेरी से किए गए हर डेटाबेस अनुरोध का आकलन, डेटा पढ़ने या उसमें डेटा लिखने से पहले, सुरक्षा से जुड़े आपके नियमों के हिसाब से किया जाता है. अगर नियमों के मुताबिक, दस्तावेज़ के किसी भी पाथ का ऐक्सेस नहीं दिया जाता है, तो पूरा अनुरोध अस्वीकार कर दिया जाता है.

Cloud Firestore Security Rules का इस्तेमाल शुरू करें में जाकर, Cloud Firestore Security Rules के बारे में ज़्यादा जानें.

एम्युलेटर को इंस्टॉल करें

Cloud Firestore एमुलेटर इंस्टॉल करने के लिए, Firebase सीएलआई का इस्तेमाल करें और नीचे दिया गया कमांड चलाएं:

firebase setup:emulators:firestore

एम्युलेटर चलाना

अपनी वर्किंग डायरेक्ट्री में Firebase प्रोजेक्ट शुरू करके शुरुआत करें. Firebase सीएलआई का इस्तेमाल करते समय, यह पहला चरण है.

firebase init

यहां दिए गए कमांड का इस्तेमाल करके, एमुलेटर शुरू करें. एमुलेटर तब तक चलता रहेगा, जब तक आपने प्रोसेस को बंद नहीं कर दिया:

firebase emulators:start --only firestore

कई मामलों में, आपको एम्युलेटर शुरू करके टेस्ट सुइट चलाना होता है. इसके बाद, टेस्ट पूरा होने के बाद एम्युलेटर को बंद करना होता है. emulators:exec निर्देश का इस्तेमाल करके, ऐसा आसानी से किया जा सकता है:

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

शुरू होने पर, एम्युलेटर डिफ़ॉल्ट पोर्ट (8080) पर चलने की कोशिश करेगा. अपनी firebase.json फ़ाइल के "emulators" सेक्शन में बदलाव करके, एम्युलेटर पोर्ट को बदला जा सकता है:

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

एमुलेटर चलाने से पहले

एम्युलेटर का इस्तेमाल शुरू करने से पहले, इन बातों का ध्यान रखें:

  • एम्युलेटर शुरू में आपकी firebase.json फ़ाइल के firestore.rules फ़ील्ड में बताए गए नियमों को लोड करेगा. इसे उस लोकल फ़ाइल का नाम चाहिए होगा जिसमें आपका Cloud Firestore Security Rules है. साथ ही, उन नियमों को सभी प्रोजेक्ट पर लागू करता है. अगर आपने लोकल फ़ाइल का पाथ नहीं दिया है या यहां बताए गए loadFirestoreRules तरीके का इस्तेमाल नहीं किया है, तो एमुलेटर सभी प्रोजेक्ट को ऐसे प्रोजेक्ट मानता है जिनमें ओपन नियम लागू होते हैं.
  • ज़्यादातर Firebase SDK टूल, एमुलेटर के साथ सीधे तौर पर काम करते हैं. हालांकि, सुरक्षा नियमों में सिर्फ़ @firebase/rules-unit-testing लाइब्रेरी, auth को मॉक करने की सुविधा देता है. इससे यूनिट टेस्ट करना बहुत आसान हो जाता है. इसके अलावा, लाइब्रेरी में एम्युलेटर की कुछ खास सुविधाओं का भी इस्तेमाल किया जा सकता है, जैसे कि सारा डेटा मिटाना. ये सुविधाएं नीचे दी गई हैं.
  • एमुलेटर, क्लाइंट SDK टूल के ज़रिए दिए गए प्रोडक्शन Firebase Auth टोकन भी स्वीकार करेंगे. साथ ही, नियमों का आकलन भी करेंगे. इससे इंटिग्रेशन और मैन्युअल टेस्ट में, अपने ऐप्लिकेशन को सीधे एमुलेटर से कनेक्ट करने की सुविधा मिलती है.

लोकल यूनिट टेस्ट चलाना

v9 JavaScript SDK टूल की मदद से, लोकल यूनिट टेस्ट चलाना

Firebase, अपने वर्शन 9 JavaScript SDK और वर्शन 8 SDK, दोनों के साथ सुरक्षा नियमों की यूनिट टेस्टिंग लाइब्रेरी उपलब्ध कराता है. लाइब्रेरी के एपीआई काफ़ी अलग होते हैं. हम v9 टेस्टिंग लाइब्रेरी का सुझाव देते हैं, जो ज़्यादा व्यवस्थित है. साथ ही, इसे एम्युलेटर से कनेक्ट करने के लिए कम सेटअप की ज़रूरत होती है. इस तरह, प्रोडक्शन संसाधनों के गलती से इस्तेमाल से बचा जा सकता है. पुराने सिस्टम के साथ काम करने की सुविधा के लिए, हम v8 टेस्टिंग लाइब्रेरी उपलब्ध कराते रहेंगे.

स्थानीय तौर पर चलने वाले एमुलेटर के साथ इंटरैक्ट करने के लिए, @firebase/rules-unit-testing मॉड्यूल का इस्तेमाल करें. अगर आपको टाइम आउट या ECONNREFUSED गड़बड़ियां मिलती हैं, तो दोबारा जांच लें कि एमुलेटर असल में चल रहा है या नहीं.

हमारा सुझाव है कि आप Node.js के नए वर्शन का इस्तेमाल करें, ताकि आप async/await नोटेशन का इस्तेमाल कर सकें. करीब-करीब हर उस व्यवहार की जांच होती है जिसकी आपको जांच करनी है. टेस्टिंग मॉड्यूल को इस तरह से डिज़ाइन किया गया है कि यह प्रॉमिस-आधारित कोड के साथ काम करता है.

v9 रूल यूनिट की टेस्टिंग लाइब्रेरी को एम्युलेटर के बारे में हमेशा जानकारी रहती है. साथ ही, यह आपके प्रोडक्शन के संसाधनों से जुड़ी जानकारी को भी छूता नहीं है.

आप v9 मॉड्यूलर इंपोर्ट स्टेटमेंट का इस्तेमाल करके लाइब्रेरी इंपोर्ट करते हैं. उदाहरण के लिए:

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.

इंपोर्ट होने के बाद, यूनिट टेस्ट लागू करने के लिए ये काम करने की ज़रूरत होती है:

  • initializeTestEnvironment पर कॉल करके, RulesTestEnvironment बनाना और कॉन्फ़िगर करना.
  • नियमों को ट्रिगर किए बिना, टेस्ट डेटा सेट अप करने के लिए, एक आसान तरीका इस्तेमाल करें. इससे, कुछ समय के लिए उन्हें बायपास किया जा सकता है, RulesTestEnvironment.withSecurityRulesDisabled.
  • टेस्ट सुइट और हर टेस्ट को सेट अप करने से, टेस्ट डेटा और एनवायरमेंट को साफ़ करने के लिए कहा जाता है, जैसे कि RulesTestEnvironment.cleanup() या RulesTestEnvironment.clearFirestore().
  • ऐसे टेस्ट केस लागू करना जो RulesTestEnvironment.authenticatedContext और RulesTestEnvironment.unauthenticatedContext का इस्तेमाल करके, पुष्टि की स्थितियों की नकल करते हैं.

सामान्य तरीके और यूटिलिटी फ़ंक्शन

SDK टूल के वर्शन 9 में, एमुलेटर के हिसाब से टेस्ट करने के तरीके भी देखें.

initializeTestEnvironment() => RulesTestEnvironment

यह फ़ंक्शन, नियमों की यूनिट की जांच करने के लिए, टेस्ट एनवायरमेंट को शुरू करता है. टेस्ट सेटअप के लिए, पहले इस फ़ंक्शन को कॉल करें. टास्क को पूरा करने के लिए, एम्युलेटर चालू होने चाहिए.

यह फ़ंक्शन, TestEnvironmentConfig के बारे में बताने वाले वैकल्पिक ऑब्जेक्ट को स्वीकार करता है. इसमें प्रोजेक्ट आईडी और एम्युलेटर कॉन्फ़िगरेशन की सेटिंग शामिल हो सकती हैं.

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

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

इस तरीके से एक RulesTestContext बनता है, जो पुष्टि किए गए उपयोगकर्ता की तरह काम करता है. दिखाए गए कॉन्टेक्स्ट की मदद से बनाए गए अनुरोधों में, पुष्टि करने वाला एक मॉक टोकन जुड़ा होगा. इसके अलावा, ज़रूरत के मुताबिक दावे तय करने वाला कोई ऑब्जेक्ट पास करें या पुष्टि करने वाले टोकन के पेलोड के लिए ओवरराइड करें.

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

इस तरीके से RulesTestContext बनता है, जो ऐसे क्लाइंट की तरह काम करता है जिसने पुष्टि करने के लिए लॉग इन नहीं किया है. दिखाए गए कॉन्टेक्स्ट की मदद से बनाए गए अनुरोधों में, Firebase Auth टोकन अटैच नहीं होंगे.

कॉन्फ़िगर किए गए किसी भी एमुलेटर इंस्टेंस को ऐक्सेस करने के लिए, अपने टेस्ट में दिखाए गए टेस्ट कॉन्टेक्स्ट ऑब्जेक्ट का इस्तेमाल करें. इनमें 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()

कॉन्टेक्स्ट के साथ टेस्ट सेटअप फ़ंक्शन चलाएं. यह फ़ंक्शन ऐसा काम करता है, जैसे कि सुरक्षा के नियम बंद किए गए हों.

इस तरीके में कॉलबैक फ़ंक्शन लिया जाता है, जो सुरक्षा के नियमों को बायपास करते हुए कॉन्टेक्स्ट लेता है और प्रॉमिस देता है. प्रॉमिस सुलझने / अस्वीकार होने के बाद, संदर्भ को मिटा दिया जाएगा.

RulesTestEnvironment.cleanup()

इस तरीके से, टेस्ट एनवायरमेंट में बनाए गए सभी RulesTestContexts को नष्ट कर दिया जाता है. साथ ही, इसमें मौजूद संसाधनों को भी मिटा दिया जाता है, ताकि सभी लोग बिना किसी रुकावट के बाहर निकल सकें.

इस तरीके से एम्युलेटर की स्थिति में किसी तरह का बदलाव नहीं होता. टेस्ट के बीच डेटा रीसेट करने के लिए, ऐप्लिकेशन एम्युलेटर के लिए खास तौर पर बनाए गए डेटा को हटाने के तरीके का इस्तेमाल करें.

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

यह एक टेस्ट केस यूटिलिटी फ़ंक्शन है.

फ़ंक्शन में दावा किया गया है कि एम्युलेटर ऑपरेशन के लिए उपलब्ध 'प्रॉमिस' में कोई गड़बड़ी नहीं है. इससे, सुरक्षा के नियमों का उल्लंघन नहीं किया जाएगा.

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

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

यह टेस्ट केस यूटिलिटी फ़ंक्शन है.

फ़ंक्शन में दावा किया गया है कि एम्युलेटर ऑपरेशन के लिए दिए गए 'प्रॉमिस' को सुरक्षा नियमों का उल्लंघन करने की वजह से अस्वीकार कर दिया जाएगा.

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

एम्युलेटर के लिए खास तरीके

SDK टूल के v9 वर्शन में, टेस्ट करने के सामान्य तरीके और काम के फ़ंक्शन भी देखें.

RulesTestEnvironment.clearFirestore() => Promise<void>

इस तरीके से, Firestore डेटाबेस में मौजूद वह डेटा मिट जाता है जो Firestore एमुलेटर के लिए कॉन्फ़िगर किए गए projectId से जुड़ा होता है.

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

जांच के इस कॉन्टेक्स्ट के लिए, इस तरीके को Firestore इंस्टेंस मिलता है. लौटाए गए Firebase JS क्लाइंट SDK इंस्टेंस का इस्तेमाल, क्लाइंट SDK API (v9 मॉड्यूलर या v9 कंपैट) के साथ किया जा सकता है.

नियमों के आकलन को विज़ुअलाइज़ करना

Cloud Firestore एमुलेटर की मदद से, एमुलेटर सुइट के यूज़र इंटरफ़ेस (यूआई) में क्लाइंट के अनुरोधों को विज़ुअलाइज़ किया जा सकता है. इसमें Firebase के सुरक्षा नियमों के लिए, आकलन की ट्रैकिंग भी शामिल है.

हर अनुरोध के लिए, आकलन का सिलसिलेवार तरीका देखने के लिए, Firestore > अनुरोध टैब खोलें.

Fire Emulator के अनुरोधों को मॉनिटर करने से, सुरक्षा नियमों का आकलन दिखाया जा रहा है

टेस्ट रिपोर्ट जनरेट करना

कई तरह की जांच करने के बाद, जांच के दायरे की रिपोर्ट ऐक्सेस की जा सकती हैं. इन रिपोर्ट से पता चलता है कि आपके हर सुरक्षा नियम का आकलन कैसे किया गया.

रिपोर्ट पाने के लिए, एमुलेटर के चलने के दौरान, किसी एक्सपोज़ किए गए एंडपॉइंट पर क्वेरी करें. ब्राउज़र के हिसाब से बने वर्शन के लिए, इस यूआरएल का इस्तेमाल करें:

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

इससे आपके नियम, एक्सप्रेशन और सब-एक्सप्रेशन में बंट जाते हैं. ज़्यादा जानकारी के लिए, इनका माउसओवर किया जा सकता है. इसमें आकलन और दिखाई गई वैल्यू की संख्या शामिल है. इस डेटा के रॉ JSON वर्शन के लिए, अपनी क्वेरी में यह यूआरएल शामिल करें:

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

एमुलेटर और प्रोडक्शन के बीच अंतर

  1. आपको साफ़ तौर पर Cloud Firestore प्रोजेक्ट बनाने की ज़रूरत नहीं है. एम्युलेटर, ऐक्सेस किया जाने वाला कोई भी इंस्टेंस अपने-आप बना देता है.
  2. Cloud Firestore एमुलेटर, सामान्य Firebase Authentication फ़्लो के साथ काम नहीं करता. इसके बजाय, हमने Firebase टेस्ट SDK टूल में rules-unit-testing लाइब्रेरी में initializeTestApp() तरीका दिया है. इसके लिए, auth फ़ील्ड की ज़रूरत होती है. इस तरीके का इस्तेमाल करके बनाया गया Firebase हैंडल, इस तरह काम करेगा जैसे आपने जो भी इकाई दी है उसकी पुष्टि हो गई है. null पास करने पर, यह पुष्टि न किए गए उपयोगकर्ता की तरह काम करेगा. उदाहरण के लिए, auth != null नियम काम नहीं करेंगे.

पहले से मौजूद समस्याओं को हल करना

Cloud Firestore एम्युलेटर का इस्तेमाल करने पर, आपको यहां बताई गई समस्याओं का सामना करना पड़ सकता है. अगर आपको कोई गड़बड़ी दिख रही है, तो उसे ठीक करने के लिए यहां दिए गए निर्देशों का पालन करें. ये नोट, सुरक्षा नियमों की यूनिट टेस्टिंग लाइब्रेरी को ध्यान में रखकर लिखे गए हैं. हालांकि, ये सामान्य तरीके किसी भी Firebase SDK टूल पर लागू होते हैं.

जांच करने का तरीका अलग-अलग है

अगर आपके टेस्ट कभी-कभी पास और कभी-कभी फ़ेल होते हैं, तो हो सकता है कि टेस्ट में कोई बदलाव किए बिना भी ऐसा हो. ऐसे में, आपको यह पुष्टि करनी होगी कि टेस्ट का क्रम सही है या नहीं. एम्युलेटर के साथ होने वाले ज़्यादातर इंटरैक्शन एसिंक्रोनस होते हैं, इसलिए दोबारा जांच लें कि सभी एक साथ काम नहीं करने वाले कोड सही से क्रम में लगाए गए हों. क्रम को ठीक करने के लिए, await नोटेशन का इस्तेमाल करें या await नोटेशन का इस्तेमाल करें.

खास तौर पर, इन असाइनमेंट की समीक्षा करें:

  • उदाहरण के लिए, initializeTestEnvironment के साथ सुरक्षा नियम सेट करना.
  • डेटा पढ़ना और उसमें बदलाव करना. उदाहरण के लिए, db.collection("users").doc("alice").get().
  • कार्रवाई से जुड़े दावे, जिनमें assertSucceeds और assertFails शामिल हैं.

एम्युलेटर को पहली बार लोड करने पर ही टेस्ट पास होते हैं

एम्युलेटर को स्टेटफ़ुल तरीके से दिखाया गया है. यह मेमोरी में, उसमें लिखा गया सारा डेटा सेव करता है. इसलिए, जब भी एमुलेटर बंद होता है, तो सारा डेटा मिट जाता है. अगर एक ही प्रोजेक्ट आईडी के लिए कई टेस्ट चलाए जा रहे हैं, तो हर टेस्ट से ऐसा डेटा मिल सकता है जिससे अगले टेस्ट पर असर पड़ सकता है. इस व्यवहार को बायपास करने के लिए, इनमें से किसी भी तरीके का इस्तेमाल किया जा सकता है:

  • हर जांच के लिए, यूनीक प्रोजेक्ट आईडी का इस्तेमाल करें. ध्यान दें कि ऐसा करने पर, आपको हर टेस्ट के तौर पर initializeTestEnvironment को कॉल करना होगा. नियम, सिर्फ़ डिफ़ॉल्ट प्रोजेक्ट आईडी के लिए अपने-आप लोड होते हैं.
  • अपने टेस्ट को फिर से व्यवस्थित करें, ताकि वे पहले लिखे गए डेटा से इंटरैक्ट न करें. उदाहरण के लिए, हर टेस्ट के लिए अलग कलेक्शन का इस्तेमाल करें.
  • टेस्ट के दौरान लिखा गया सारा डेटा मिटाएं.

टेस्ट सेटअप करना बहुत मुश्किल है

टेस्ट सेट अप करते समय, हो सकता है कि आप डेटा में ऐसे बदलाव करना चाहें जिनकी अनुमति आपके Cloud Firestore Security Rules में न हो. अगर आपके नियमों की वजह से टेस्ट सेटअप करना मुश्किल हो रहा है, तो सेटअप के चरणों में RulesTestEnvironment.withSecurityRulesDisabled का इस्तेमाल करें. ऐसा इसलिए, ताकि पढ़ने और लिखने से PERMISSION_DENIED गड़बड़ियां ट्रिगर न हों.

इसके बाद, आपका टेस्ट RulesTestEnvironment.authenticatedContext और unauthenticatedContext का इस्तेमाल करके, पुष्टि किए गए या बिना पुष्टि वाले उपयोगकर्ता के तौर पर कार्रवाइयां कर सकता है. इससे आपको यह पुष्टि करने में मदद मिलती है कि आपका Cloud Firestore Security Rules, अलग-अलग मामलों को सही तरीके से अनुमति देता है / अस्वीकार करता है.