تشفير MySQL: مخزن المفاتيح

عشية بدء تعيين جديد لدورة "قواعد البيانات" ، قمنا بإعداد ترجمة لمقال مفيد لك.






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



كيرينغ MySQL



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



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



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


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



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



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



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



  • key id — , :

    INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
  • key type — , , : «AES», «RSA» «DSA».
  • key length — , AES: 16, 24 32, RSA 128, 256, 512 DSA 128, 256 384.
  • user — . , , Master Key, . keyring_udf, .


يتم تحديد المفتاح بشكل فريد من قبل الزوج: key_id ، user.



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



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



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



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



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



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



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



ما اعني؟ يجب أن يكون لكل خادم (على سبيل المثال ، Percona Server) في المجموعة موقع منفصل على خادم Vault حيث يجب على خادم Percona تخزين مفاتيحه. يحتوي كل مفتاح رئيسي مخزن في الخزنة على GUID الخاص بخادم Percona ضمن معرفه. لماذا هو مهم؟ تخيل أن لديك Vault Server واحدًا وأن جميع خوادم Percona في المجموعة تستخدم خادم Vault الفردي. تبدو المشكلة واضحة. إذا كانت جميع خوادم Percona تستخدم المفتاح الرئيسي بدون معرفات فريدة ، على سبيل المثال ، id = 1 ، id = 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 ، ألا يجب أن تفشل وظيفة keyring_key_store على server2؟ ومن المثير للاهتمام ، إذا حاولت أن تفعل الشيء نفسه على نفس الخادم ، فسوف تحصل على خطأ:



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


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



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



في الحالة الأولى ، الوضع مختلف. Server1 و server2 لهما ذاكرة تخزين مؤقت منفصلة. بعد إضافة ROB_1 إلى ذاكرات التخزين المؤقت للمفاتيح على server1 و Vault ، تكون ذاكرة التخزين المؤقت للمفاتيح على server2 غير متزامنة. لا يوجد مفتاح ROB_1 في ذاكرة التخزين المؤقت على الخادم 2. وبالتالي ، تتم كتابة مفتاح 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 = (...)


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



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


في هذه الحالة ، يستخدم كلا الخادمين نفس نقطة_التثبيت ، لكن مسارات مختلفة. عندما يتم إنشاء السر الأول على server1 على طول هذا المسار ، يقوم Vault تلقائيًا بإنشاء دليل "server1". بالنسبة للخادم 2 ، كل شيء هو نفسه. عند إزالة السر الأخير في 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 المساعدة لفعل الشيء نفسه. لكن هذا يجعل من السهل أتمتة إنشاء نقطة التحميل. أتمنى أن تجد هذه المعلومات مفيدة وسنراكم في المقالات التالية في هذه السلسلة.





اقرأ أكثر:






All Articles