قوانین امنیتی برای عملیات Pipeline

درحالی‌که عملیات Pipeline مجموعه غنی‌ای از ویژگی‌ها را ارائه می‌دهد، موتور Rules به تشخیص فیلترهای مقایسه‌ای (مثلاً >) و منطقی (مثلاً or) محدود شده است تا از رضایت‌بخش بودن و امنیت محدودیت‌ها اطمینان حاصل شود.

عبارت‌های فیلتر پشتیبانی‌شده

برای اینکه عملیات Pipeline به مرزهای تعیین‌شده توسط قوانین شما محدود شود، باید از عملگرهای منطقی و مقایسه‌ای دربرابر ثابت‌ها استفاده کند. موتور «قوانین» انواع فیلتر زیر را تشخیص می‌دهد:

  • مقایسه‌ها: eq، neq، gt، gte، lt، lte، in، arrayContains.
  • منطقی: and، or.

چند نمونه در زیر آمده است:

  • where(eq("foo", 2))
  • where(lt("foo", 2))
  • documents("/user/1", "/user/2").where(...)

درخواست ویژگی‌ها

می‌توانید همچنان از شیء request برای اعتبارسنجی اصالت‌سنجی و زمینه پُرسمان استفاده کنید، هرچند برخی‌از ویژگی‌های موجود در پُرسمان‌های استاندارد در عملیات «خط لوله» پشتیبانی نمی‌شوند.

مشخصات پشتیبانی‌شده

موتور جدید همچنان از ویژگی‌های زیر پشتیبانی می‌کند:

  • ‫request.auth: دسترسی به شناسه کاربری و داده‌های رمزه.
  • request.method: عملیات را شناسایی می‌کند (برای مثال، get، list).
  • ‫request.path: مسیر منبعی که به آن دسترسی پیدا شده است.
  • ‫request.time: مُهر زمان سمت سرور درخواست.

ویژگی‌های پشتیبانی‌نشده

ویژگی‌های request.query مانند limit، offset، و orderBy برای بررسی‌های قانون عملیات Pipeline پشتیبانی نمی‌شوند، زیرا تعیین این مقادیر در پُرسمان‌های چندمرحله‌ای پیچیده است.

مدیریت و اجازه‌های مرحله خط لوله

مراحل خط لوله مختلفی وجود دارد که به عملیات دانه‌ای خاص در قوانین امنیتی نگاشت می‌شوند:

  • اجازه‌های allow list: با مراحل collection()، collectionGroup()، و database() راه‌اندازی می‌شود.
  • اجازه‌های allow get: با مرحله documents() راه‌اندازی می‌شود که مشابه عملیات دسته‌ای get درنظر گرفته می‌شود.
  • اجازه‌های allow create: با insert() مرحله، و upsert() مرحله هنگام ایجاد سندهای جدید راه‌اندازی می‌شود.
  • اجازه‌های allow update: با مراحل update() و مراحل upsert() هنگام به‌روزرسانی اسناد موجود راه‌اندازی می‌شود.
  • اجازه‌های allow delete: با delete() مرحله راه‌اندازی شد.
  • اجازه‌های allow write: برای همه عملیات DML (insert()، update()، upsert()، و delete()) اعمال می‌شود.
  • مرحله Literals: مرحله literals() از پایگاه داده نمی‌خواند اما می‌تواند هزینه داشته باشد. برای جلوگیری از سوءاستفاده، باید با مرحله دیگری (مثل collection()) که با قوانین قابل‌تأیید باشد جفت شود.

مراحل اصلاح فیلد

قوانین فقط روی داده‌های ذخیره‌شده عمل می‌کنند و نه مقادیر مشتق‌شده. اگر خط لوله‌ای شامل مراحلی باشد که فیلدها را اصلاح می‌کنند (برای مثال، add_fields(...)، replace_with(...)، select(...)، remove_fields(...))، موتور «قوانین» پس‌از مواجه شدن با آن مرحله، اعمال محدودیت‌های فیلتر را متوقف می‌کند. برای اطمینان از اینکه قوانین طبق انتظار کار می‌کنند، مراحل فیلترتان را (یعنی where) قبل‌از هر مرحله‌ای که می‌تواند اسناد ذخیره‌شده اصلی را اصلاح کند قرار دهید.

برای مثال، قانون امنیتی زیر را درنظر بگیرید:

match /databases/{database}/documents {
  match /cities/{city} {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    allow read: if resource.data.visibility == 'public';
  }
}

ردشده: این قانون خط لوله زیر را رد می‌کند زیرا مرحله addFields قبل‌از فیلتر کردن اسنادی که visibility در آن‌ها public است رخ می‌دهد:

const results = await db.pipeline()
  .collection("/cities")
  // Filters after a modification stage are ignored by Rules.
  .addFields(constant(1000).as("population"))
  .where(eq(field("visibility"), constant("public")))
  .execute();

مجاز: این قانون به خط لوله زیر اجازه می‌دهد زیرا مرحله where(eq(field("visibility"), constant("public"))) قبل‌از هرگونه مرحله اصلاح رخ می‌دهد:

const results = await db.pipeline()
  .collection("/cities")
  .where(eq(field("visibility"), constant("public")))
  .addFields(constant(1000).as("population"))
  .execute();

مراحل زبان دستکاری داده و قوانین امنیتی

هنگام اجرای مراحل زبان دستکاری داده (DML) (insert()، update()، upsert()، و delete())، «قوانین امنیتی» اجازه‌ها را به‌طور متفاوتی نسبت به پرس‌وجوهای خواندن ارزیابی می‌کنند:

  • ارزیابی قانون برای هر سند: برخلاف خطوط لوله خواندن که برای محدود کردن پُرسمان در زمان برنامه‌ریزی به عبارت‌های فیلتر ازپیش نیاز دارند، عملیات DML قوانین امنیتی را دربرابر هر جهش سند جداگانه ارزیابی می‌کنند.
  • متغیرهای قانون:
    • request.resource: حاوی داده‌های سند پیشنهادی برای عملیات insert()، update()، و upsert() است.
    • resource: حاوی داده‌های سند فعلی ذخیره‌شده در پایگاه داده پیش‌از اصلاح (دردسترس برای update()،‏ delete()، و upsert() اسناد موجود).

محدودیت‌های سیستم و رفتار اجرا با DML

هنگام اجرای عملیات DML با «قوانین امنیتی»، محدودیت‌های سیستم و رفتارهای اجرایی زیر را درنظر داشته باشید:

محدودیت ۲۰ جست‌وجو در get() و exists()

«قوانین امنیتی Firebase» حداکثر ۲۰ جستجوی سند (get() یا exists()) را در کل درخواست مجاز می‌کند.

وقتی خط لوله DML خارج از تراکنش صریح اجرا می‌شود، Cloud Firestore نوشتن سند را به‌صورت دسته‌ای پردازش می‌کند. چون هر دسته در تراکنش خودش اجرا می‌شود و ممکن است اسناد به‌طور هم‌زمان بین دسته‌ها اصلاح شوند، قوانین امنیتی و جستجوهای سند برای هر دسته نوشتاری دوباره ارزیابی می‌شوند.

حتی اگر قوانین امنیتی شما دربرابر یک سند ایستا ارزیابی شود (برای مثال، بررسی اینکه آیا کاربر سرپرست است یا نه):

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts/{postId} {
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true;
    }
  }
}

هر دسته نوشتاری ۱۰ سندی یک جست‌وجو انجام می‌دهد. درنتیجه، پس‌از نوشتن همه سندهای ممکن، به حد ۲۰ جستجو برای درخواست می‌رسید، و خط لوله با خطای PERMISSION_DENIED ناموفق می‌شود. علاوه‌براین، هر جستجویی که برای هر دسته نوشتن انجام می‌شود، صورت‌حساب خواندن خودش را دارد.

موفقیت جزئی و PERMISSION_DENIED

هنگام اجرا خارج از تراکنش، عملیات DML نوشتن‌ها را در دسته‌های متوالی ثبت می‌کند. اگر دسته‌ای ناموفق باشد (به‌دلیل اینکه سند شرط قانونی را برآورده نمی‌کند یا به‌دلیل اینکه از حد ۲۰ جستجو فراتر رفته است)، کانال متوقف می‌شود و خطای PERMISSION_DENIED را برمی‌گرداند.

اما دسته‌هایی که قبلاً ثبت شده‌اند برگردانده نمی‌شوند. پایگاه داده در وضعیت نیمه‌به‌روزرسانی‌شده باقی می‌ماند. چون کارخواه خطایی بدون فهرست اسناد اصلاح‌شده دریافت می‌کند، باید داده‌هایتان را پُرسمان کنید تا بررسی کنید کدام نوشتن‌ها موفقیت‌آمیز بوده است.

عیب‌یابی کردن خرابی‌های قانون با Cloud Audit Logs

به‌دلایل امنیتی، خطاهای PERMISSION_DENIED که مشتری با آن‌ها مواجه می‌شود، مشخص نمی‌کنند که کدام شرط قانون امنیتی ناموفق بوده است یا اینکه به حد ۲۰ جستجو رسیده است یا نه.

برای تشخیص خرابی‌های ارزیابی قانون، سرپرستان پروژه می‌توانند «گزارش‌های ممیزی Cloud» را در کنسول Google Cloud (در بخش Firestore > پایش یا در کاوشگر گزارش‌ها) بررسی کنند تا ورودی‌های EvaluationError تفصیلی را مشاهده کنند.