अपने 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 CLI का इस्तेमाल करते समय, यह पहला सामान्य चरण होता है.

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()

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

यह तरीका एक कॉलबैक फ़ंक्शन लेता है, जो Security-Rules-bypassing context लेता है और एक प्रॉमिस दिखाता है. वादा पूरा होने या अस्वीकार होने के बाद, कॉन्टेक्स्ट मिटा दिया जाएगा.

RulesTestEnvironment.cleanup()

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

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

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

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

फ़ंक्शन यह दावा करता है कि एमुलेटर ऑपरेशन को रैप करने वाले दिए गए Promise को, सुरक्षा नियमों का उल्लंघन किए बिना हल किया जाएगा.

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

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

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

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

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

एमुलेटर के हिसाब से तरीके

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

RulesTestEnvironment.clearFirestore() => Promise<void>

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

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

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

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

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

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

Firestore एमुलेटर के अनुरोधों को मॉनिटर करने वाला टूल, जो सुरक्षा नियमों के आकलन दिखाता है

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

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

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

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 Test SDK टूल में, rules-unit-testing लाइब्रेरी में initializeTestApp() तरीका उपलब्ध कराया है. यह तरीका auth फ़ील्ड लेता है. इस तरीके का इस्तेमाल करके बनाया गया Firebase हैंडल, इस तरह काम करेगा जैसे आपने जो भी इकाई दी है उसकी पुष्टि हो गई है. null पास करने पर, यह पुष्टि न किए गए उपयोगकर्ता की तरह काम करेगा. उदाहरण के लिए, auth != null नियम काम नहीं करेंगे.

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

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

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

अगर आपके टेस्ट कभी-कभी पास हो रहे हैं और काम नहीं कर रहे हैं, भले ही उनमें कोई बदलाव नहीं किया गया हो, तो आपको इस बात की पुष्टि करनी पड़ सकती है कि उन्हें सही तरीके से क्रम में लगाया जा रहा है. एमुलेटर के साथ ज़्यादातर इंटरैक्शन एसिंक्रोनस होते हैं. इसलिए, दोबारा जांच लें कि सभी एसिंक्रोनस कोड का क्रम सही है या नहीं. प्रॉमिसेस को चेन करके या 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, अलग-अलग मामलों को सही तरीके से अनुमति देता है या अस्वीकार करता है.