Database Engineering

تأمين طبقة التطبيقات متعددة المستأجرين: تنفيذ أمان مستوى الصف لمهندسي قواعد البيانات

في مشهد الخدمات السحابية الحديثة (SaaS)، تعد تعدد المستأجرين استراتيجية نشر فحسب، بل هي متطلب معماري أساسي. بينما توفر قواعد البيانات المشتركة كفاءة كبيرة في التكاليف وتبسيط النسخ الاحتياطي، إلا أنها تطرح تحدياً أمنياً حاسماً: عزل البيانات. كيف تضمن أن المستأجر أ لا يرى أبداً بيانات المستأجر ب، حتى في حال حدوث خطأ في التطبيق أو ارتكاب المطور لخطأ؟ تكمن الإجابة في أمان مستوى الصف (RLS).

يُعد أمان مستوى الصف ميزة قوية متاحة في قواعد البيانات العلائقية المتقدمة مثل PostgreSQL وAzure SQL وOracle. تسمح هذه الميزة لمحرك قاعدة البيانات بفرض سياسات التحكم في الوصول بنفسه، مما ينقل عبء الأمن من طبقة التطبيق إلى طبقة البيانات. في هذا المنشور، نستكشف كيفية تنفيذ RLS بفعالية، مما يضمن عزلاً قوياً دون التضحية بالأداء أو تجربة المطور.

لماذا يتفوق RLS على التصفية على مستوى التطبيق

يتضمن النهج التقليدي لتعدد المستأجرين إضافة عمود tenant_id إلى كل جدول والتأكد من أن كل استعلام يتضمن عبارة WHERE tenant_id = current_user_tenant_id. بينما يعمل هذا النهج، إلا أنه يعتمد كلياً على دقة كود التطبيق. إذا نسي المطور تطبيق عامل التصفية، أو إذا فشل منشئ الاستعلام الديناميكي المعقد في حقن الشرط، يحدث خرق بيانات هائل.

يقضي RLS على هذا الخطر من خلال فرض القيود على مستوى تنفيذ SQL. حتى إذا منح المسؤول صلاحيات واسعة لمستخدم، فإن سياسة RLS تعمل كعامل تصفية غير مرئي، مقيدة النتائج بالصفوف فقط التي يُسمح للمستخدم بالوصول إليها. يُعد هذا النهج الدفاعي متعدد الطبقات حاسماً لأطر الامتثال مثل GDPR وHIPAA وSOC2.

تنفيذ RLS في PostgreSQL

لنلقِ نظرة على تنفيذ عملي باستخدام PostgreSQL، المعيار الصناعي للميزات المتقدمة لأمان مستوى الصف. يتضمن المفهوم الأساسي إنشاء دالة تحدد سياق المستأجر الحالي وتعريف سياسات تفرض هذا السياق.

الخطوة 1: إنشاء سياق المستأجر

أولاً، نحتاج إلى طريقة لتحديد المستأجر الحالي. يتم ذلك عادةً عن طريق تعيين متغير الجلسة أو استخدام مطالبة من رمز المصادقة (مثل JWT). لهذا المثال، سنستخدم معلمة جلسة مخصصة.

-- تمكين سياق الأمان
-- في تطبيق حقيقي، يتم تعيين هذا بعد المصادقة
SET app.current_tenant_id = 'tenant_001';

-- دالة مساعدة لاسترداد معرف المستأجر
CREATE OR REPLACE FUNCTION get_current_tenant_id()
RETURNS UUID AS $$
BEGIN
    RETURN current_setting('app.current_tenant_id')::UUID;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

الخطوة 2: تعريف سياسات الأمان

الآن، نطبق السياسات على الجداول المحددة. إليك مثال لجدول orders قياسي.

-- تمكين RLS على الجدول
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

-- السياسة: يمكن للمستخدمين رؤية بياناتهم فقط
CREATE POLICY tenant_isolation_policy ON orders
    USING (tenant_id = get_current_tenant_id());

-- اختياري: سياسة للمستخدمين الإداريين (المستخدمين ذوي الامتيازات الكاملة)
-- إذا كنت بحاجة إلى أن يرى المسؤولون جميع البيانات، فقد تقوم بإنشاء سياسة ثانية
CREATE POLICY admin_override_policy ON orders
    FOR ALL
    TO admin_role
    USING (true);

لاحظ التمييز بين عبارة USING وعبارة WITH CHECK. تتحكم عبارة USING في الصفوف التي يتم إرجاعها أثناء SELECT. تتحكم عبارة WITH CHECK في الصفوف التي يمكن إدراجها أو تحديثها، مما يضمن عدم قدرة المستخدمين على تعديل سجلات تابعة لمستأجرين آخرين عن طريق الخطأ (أو بسوء نية).

الخطوة 3: التعامل مع الهوية

في العديد من التطبيقات، تحتاج أيضاً إلى تتبع من أنشأ السجل. إذا كان جدول المستخدمين يتضمن user_id، يمكنك توسيع السياسة لضمان وصول المستخدمين فقط إلى البيانات التي أنشأوها شخصياً، بالإضافة إلى بيانات مستأجرهم.

-- سياسة أكثر دقة: يمكن للمستخدمين رؤية طلباتهم فقط
CREATE POLICY user_isolation_policy ON orders
    FOR SELECT
    USING (
        tenant_id = get_current_tenant_id()
        AND user_id = current_user_id()
    );

اعتبارات الأداء

بينما يعد RSec آمناً، إلا أنه يمكن أن يؤثر على الأداء إذا لم يتم فهرسته بشكل صحيح. يجب على محرك قاعدة البيانات تقييم السياسة لكل صف يتم الوصول إليه. لذلك، من الحاسم أن يكون عمود tenant_id مفهرساً. بدون فهرس مناسب، قد يقوم قاعدة البيانات بإجراء مسح تسلسلي لكل استعلام، مما يؤدي إلى ارتفاع كبير في زمن الاستجابة مع نمو حجم البيانات.

بالإضافة إلى ذلك، ضع في اعتبارك أن سياسات RLS تضيف عبئاً إلى مرحلة تخطيط الاستعلام. قم بمعايرة استعلاماتك تحت الحمل للتأكد من أن عبء الأمان لا يتجاوز ميزانيات الأداء الخاصة بك. لأحمال العمل التي تعتمد على القراءة، فكر في استخدام نسخ القراءة أو استراتيجيات التخزين المؤقت للتخفيف من تأثير تقييم السياسات على عمليات الكتابة.

الخاتمة

يُعد تنفيذ أمان مستوى الصف أحد أكثر الطرق فعالية لتأمين بنية متعددة المستأجرين. فهو ينقل الأمن من نموذج منطق التطبيق "ثق ولكن تحقق" إلى نموذج قاعدة البيانات "لا تثق أبداً، تحقق دائماً". من خلال الاستفادة من RLS، يمكن لمهندسي قواعد البيانات توفير أساس أمني قوي يتوسع مع الأعمال، ويحمي البيانات الحساسة، ويحافظ على الامتثال بأقل قدر من العبء على مستوى التطبيق.

عندما تدمج RLS في بنيتك البرمجية، تذكر اختبار الحالات الحدية، والتأكد من الفهرسة المناسبة، وتوثيق سياسات الأمان الخاصة بك بوضوح. في عالم تعدد المستأجرين، الأمن ليس ميزة؛ بل هو الأساس.

Share: