التشفير في MySQL: Keystore

تحسبا لبدء تسجيل جديد للدورة "قاعدة البيانات" لقد أعددنا لك ترجمة لمقالة مفيدة.

التشفير في MySQL: Keystore

ظهر التشفير الشفاف للبيانات (TDE). خادم بيركونا لـ MySQL وMySQL لبعض الوقت. ولكن هل فكرت يومًا في كيفية العمل تحت الغطاء وما هو التأثير الذي يمكن أن يحدثه TDE على الخادم الخاص بك؟ في هذه السلسلة من المقالات سنلقي نظرة على كيفية عمل TDE داخليًا. لنبدأ بتخزين المفاتيح، حيث أن هذا مطلوب لكي يعمل أي تشفير. ثم سنلقي نظرة فاحصة على كيفية عمل التشفير في Percona Server for MySQL/MySQL وما هي الميزات الإضافية التي يتمتع بها Percona Server for MySQL.

حلقة مفاتيح MySQL

Keyring عبارة عن مكونات إضافية تسمح للخادم بالاستعلام عن المفاتيح وإنشائها وحذفها في ملف محلي (keyring_file) أو على خادم بعيد (مثل HashiCorp Vault). يتم دائمًا تخزين المفاتيح مؤقتًا محليًا لتسريع عملية استرجاعها.

يمكن تقسيم الإضافات إلى فئتين:

  • التخزين المحلي. على سبيل المثال، ملف محلي (نسميه حلقة مفاتيح تعتمد على الملف).
  • التخزين عن بعد. على سبيل المثال، Vault Server (نسميه حلقة مفاتيح تعتمد على الخادم).

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

عند استخدام وحدة تخزين الملفات، عند بدء التشغيل، يتم تحميل محتويات وحدة التخزين بالكامل في ذاكرة التخزين المؤقت: معرف المفتاح، والمستخدم الرئيسي، ونوع المفتاح، والمفتاح نفسه.

في حالة وجود مخزن من جانب الخادم (مثل Vault Server)، يتم تحميل معرف المفتاح والمستخدم الرئيسي فقط عند بدء التشغيل، وبالتالي فإن الحصول على جميع المفاتيح لا يؤدي إلى إبطاء عملية بدء التشغيل. يتم تحميل المفاتيح بتكاسل. أي أنه يتم تحميل المفتاح نفسه من Vault فقط عند الحاجة إليه بالفعل. بمجرد التنزيل، يتم تخزين المفتاح مؤقتًا في الذاكرة بحيث لا يلزم الوصول إليه من خلال اتصالات TLS بخادم Vault Server في المستقبل. بعد ذلك، دعونا نلقي نظرة على المعلومات الموجودة في مخزن المفاتيح.

تحتوي المعلومات الأساسية على ما يلي:

  • معرف المفتاح - معرف المفتاح، على سبيل المثال:
    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • نوع المفتاح - نوع المفتاح بناءً على خوارزمية التشفير المستخدمة، والقيم المحتملة: "AES" أو "RSA" أو "DSA".
  • طول المفتاح - طول المفتاح بالبايت، AES: 16، 24 أو 32، RSA 128، 256، 512 وDSA 128، 256 أو 384.
  • المستخدم - صاحب المفتاح . إذا كان المفتاح هو النظام، على سبيل المثال، المفتاح الرئيسي، فهذا الحقل فارغ. إذا تم إنشاء مفتاح باستخدام keyring_udf، فسيحدد هذا الحقل مالك المفتاح.
  • المفتاح نفسه

يتم تعريف المفتاح بشكل فريد بواسطة الزوج: key_id، user.

هناك أيضًا اختلافات في تخزين المفاتيح وحذفها.

تخزين الملفات أسرع. قد تعتقد أن مخزن المفاتيح هو ببساطة كتابة مفتاح الملف مرة واحدة، ولكن لا، هناك المزيد مما يحدث هنا. كلما تم إجراء تعديل على تخزين الملف، يتم أولاً إنشاء نسخة احتياطية من كل المحتوى. لنفترض أن الملف يسمى my_biggest_secrets، وستكون النسخة الاحتياطية هي my_biggest_secrets.backup. بعد ذلك، يتم تغيير ذاكرة التخزين المؤقت (تتم إضافة المفاتيح أو حذفها)، وإذا نجح كل شيء، تتم إعادة تعيين ذاكرة التخزين المؤقت إلى ملف. في حالات نادرة، مثل فشل الخادم، قد ترى ملف النسخ الاحتياطي هذا. يتم حذف ملف النسخة الاحتياطية في المرة التالية التي يتم فيها تحميل المفاتيح (عادةً بعد إعادة تشغيل الخادم).

عند حفظ أو حذف مفتاح في مخزن الخادم، يجب أن يتصل المخزن بخادم MySQL باستخدام الأوامر "إرسال المفتاح" / "طلب حذف المفتاح".

دعنا نعود إلى سرعة بدء تشغيل الخادم. بالإضافة إلى حقيقة أن سرعة الإطلاق تتأثر بالقبو نفسه، هناك أيضًا مشكلة تتعلق بعدد المفاتيح من الخزينة التي يجب استرجاعها عند بدء التشغيل. وبطبيعة الحال، هذا مهم بشكل خاص لتخزين الخادم. عند بدء التشغيل، يتحقق الخادم من المفتاح المطلوب للجداول/مساحات الطاولة المشفرة ويطلب المفتاح من وحدة التخزين. على خادم "نظيف" مزود بتشفير Master Key، يجب أن يكون هناك مفتاح رئيسي واحد، والذي يجب استرداده من وحدة التخزين. ومع ذلك، قد تكون هناك حاجة لعدد أكبر من المفاتيح، على سبيل المثال، عندما يقوم خادم النسخ الاحتياطي باستعادة نسخة احتياطية من الخادم الأساسي. في مثل هذه الحالات، ينبغي توفير دوران المفتاح الرئيسي. سيتم تناول ذلك بمزيد من التفصيل في المقالات المستقبلية، على الرغم من أنني أود هنا أن أشير إلى أن الخادم الذي يستخدم مفاتيح رئيسية متعددة قد يستغرق وقتًا أطول قليلاً لبدء التشغيل، خاصة عند استخدام مخزن مفاتيح من جانب الخادم.

الآن دعونا نتحدث أكثر قليلاً عن keyring_file. عندما كنت أقوم بتطوير ملف keyring_file، كنت مهتمًا أيضًا بكيفية التحقق من تغييرات ملف keyring_file أثناء تشغيل الخادم. في الإصدار 5.7، تم إجراء الفحص بناءً على إحصائيات الملف، وهو ما لم يكن حلاً مثاليًا، وفي الإصدار 8.0 تم استبداله بالمجموع الاختباري SHA256.

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

لقد قمنا بالفعل بتغطية العديد من الأسئلة حول خزائن المفاتيح. ومع ذلك، هناك موضوع مهم آخر غالبًا ما يتم نسيانه أو إساءة فهمه: مشاركة المفاتيح عبر الخوادم.

الذي أقصده؟ يجب أن يكون لكل خادم (على سبيل المثال، Percona Server) في المجموعة موقع منفصل على Vault Server الذي يجب أن يقوم Percona Server بتخزين مفاتيحه فيه. يحتوي كل مفتاح رئيسي محفوظ في وحدة التخزين على المعرف الفريد العمومي (GUID) لخادم Percona ضمن معرفه. لماذا هو مهم؟ تخيل أن لديك Vault Server واحدًا فقط وأن جميع خوادم Percona في المجموعة تستخدم خادم Vault الوحيد هذا. تبدو المشكلة واضحة. إذا استخدمت جميع خوادم Percona مفتاحًا رئيسيًا بدون معرفات فريدة، مثل المعرف = 1، والمعرف = 2، وما إلى ذلك، فستستخدم جميع الخوادم في المجموعة نفس المفتاح الرئيسي. ما يوفره GUID هو التمييز بين الخوادم. لماذا إذن نتحدث عن مشاركة المفاتيح بين الخوادم إذا كان المعرف الفريد العمومي (GUID) موجودًا بالفعل؟ هناك مكون إضافي آخر - keyring_udf. باستخدام هذا البرنامج الإضافي، يمكن لمستخدم الخادم الخاص بك تخزين مفاتيحه على خادم Vault. تحدث المشكلة عندما يقوم المستخدم بإنشاء مفتاح على الخادم 1، على سبيل المثال، ثم يحاول إنشاء مفتاح بنفس المعرف على الخادم 2، على سبيل المثال:

--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 значит успешное завершение
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1

انتظر. يستخدم كلا الخادمين نفس خادم Vault Server، ألا يجب أن تفشل وظيفة keyring_key_store على الخادم 2؟ ومن المثير للاهتمام، إذا حاولت أن تفعل الشيء نفسه على خادم واحد، فسوف تتلقى خطأ:

--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0

هذا صحيح، ROB_1 موجود بالفعل.

دعونا نناقش المثال الثاني أولا. كما قلنا سابقًا، يقوم keyring_vault أو أي مكون إضافي آخر من keyring بتخزين جميع معرفات المفاتيح في الذاكرة مؤقتًا. لذلك، بعد إنشاء مفتاح جديد، تتم إضافة ROB_1 إلى الخادم 1، وبالإضافة إلى إرسال هذا المفتاح إلى Vault، تتم إضافة المفتاح أيضًا إلى ذاكرة التخزين المؤقت. الآن، عندما نحاول إضافة نفس المفتاح مرة أخرى، يتحقق keyring_vault مما إذا كان المفتاح موجودًا في ذاكرة التخزين المؤقت ويلقي خطأً.

في الحالة الأولى الوضع مختلف. يحتوي Server1 وserver2 على ذاكرة تخزين مؤقت منفصلة. بعد إضافة ROB_1 إلى ذاكرة التخزين المؤقت للمفاتيح على الخادم 1 وخادم Vault، أصبحت ذاكرة التخزين المؤقت للمفاتيح على الخادم 2 غير متزامنة. لا يوجد مفتاح ROB_2 في ذاكرة التخزين المؤقت على الخادم 1. وبالتالي، تتم كتابة مفتاح ROB_1 إلى keyring_key_store وإلى خادم Vault، الذي يقوم بالفعل بالكتابة فوق (!) القيمة السابقة. الآن أصبح مفتاح ROB_1 الموجود على خادم Vault هو 543210987654321. ومن المثير للاهتمام أن خادم Vault لا يحظر مثل هذه الإجراءات ويستبدل القيمة القديمة بسهولة.

يمكننا الآن معرفة سبب أهمية تقسيم الخادم في Vault - عندما تستخدم keyring_udf وترغب في تخزين المفاتيح في Vault. كيف يمكن تحقيق هذا الفصل على خادم Vault؟

هناك طريقتان للتقسيم إلى Vault. يمكنك إنشاء نقاط تثبيت مختلفة لكل خادم، أو استخدام مسارات مختلفة داخل نفس نقطة التثبيت. ومن الأفضل توضيح ذلك بالأمثلة. لذلك دعونا نلقي نظرة على نقاط التثبيت الفردية أولاً:

--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = server1_mount
token = (...)
vault_ca = (...)

--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = sever2_mount
token = (...)
vault_ca = (...)

هنا يمكنك أن ترى أن server1 وserver2 يستخدمان نقاط تحميل مختلفة. عند تقسيم المسارات، سيبدو التكوين كما يلي:

--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/server1
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/sever2
token = (...)
vault_ca = (...)

في هذه الحالة، يستخدم كلا الخادمين نفس نقطة التثبيت "mount_point"، ولكن مسارات مختلفة. عندما تقوم بإنشاء السر الأول على الخادم 1 باستخدام هذا المسار، يقوم خادم Vault تلقائيًا بإنشاء دليل "server1". لserver2 كل شيء مشابه. عندما تقوم بحذف السر الأخير في mount_point/server1 أو mount_point/server2، يقوم خادم Vault أيضًا بحذف تلك الدلائل. في حالة استخدام فصل المسار، يجب عليك إنشاء نقطة تحميل واحدة فقط وتغيير ملفات التكوين بحيث تستخدم الخوادم مسارات منفصلة. يمكن إنشاء نقطة تحميل باستخدام طلب HTTP. باستخدام CURL يمكن القيام بذلك على النحو التالي:

curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINT

جميع الحقول (TOKEN، VAULT_CA، VAULT_URL، SECRET_MOUNT_POINT) تتوافق مع معلمات ملف التكوين. بالطبع، يمكنك استخدام أدوات Vault المساعدة للقيام بنفس الشيء. ولكن من الأسهل أتمتة إنشاء نقطة التثبيت. أتمنى أن تجد هذه المعلومات مفيدة وسنراكم في المقالات القادمة في هذه السلسلة.

التشفير في MySQL: Keystore

اقرأ أكثر:

المصدر: www.habr.com

إضافة تعليق