การเข้ารหัสใน MySQL: Keystore

โดยคาดว่าจะเริ่มการลงทะเบียนใหม่สำหรับหลักสูตร "ฐานข้อมูล" ได้เตรียมการแปลบทความที่เป็นประโยชน์สำหรับคุณ

การเข้ารหัสใน MySQL: Keystore

การเข้ารหัสข้อมูลแบบโปร่งใส (TDE) ปรากฏขึ้น เซิร์ฟเวอร์ Percona สำหรับ MySQL และ MySQL มาระยะหนึ่งแล้ว แต่คุณเคยคิดบ้างไหมว่ามันทำงานอย่างไรภายใต้ประทุนและ TDE จะส่งผลกระทบอย่างไรต่อเซิร์ฟเวอร์ของคุณ? ในชุดบทความนี้ เราจะมาดูว่า TDE ทำงานภายในอย่างไร เริ่มจากที่เก็บข้อมูลคีย์กันก่อน เนื่องจากจำเป็นสำหรับการเข้ารหัสจึงจะทำงาน จากนั้น เราจะมาดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานของการเข้ารหัสใน Percona Server สำหรับ MySQL/MySQL และคุณสมบัติเพิ่มเติมใดบ้างที่มีให้ใช้งานใน Percona Server สำหรับ MySQL

พวงกุญแจ MySQL

คีย์ริงคือปลั๊กอินที่อนุญาตให้เซิร์ฟเวอร์สืบค้น สร้าง และลบคีย์ในไฟล์ในเครื่อง (keyring_file) หรือบนเซิร์ฟเวอร์ระยะไกล (เช่น ใน HashiCorp Vault) คีย์จะถูกแคชไว้ในเครื่องเสมอเพื่อเร่งการดึงข้อมูล

ปลั๊กอินสามารถแบ่งออกเป็นสองประเภท:

  • ที่เก็บข้อมูลท้องถิ่น ตัวอย่างเช่น ไฟล์ในเครื่อง (เราเรียกสิ่งนี้ว่าพวงกุญแจแบบไฟล์)
  • ที่เก็บข้อมูลระยะไกล ตัวอย่างเช่น 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, ผู้ใช้

นอกจากนี้ยังมีความแตกต่างในการจัดเก็บและการลบคีย์

การจัดเก็บไฟล์เร็วขึ้น คุณอาจคิดว่าที่เก็บคีย์เป็นเพียงการเขียนคีย์ไปยังไฟล์เพียงครั้งเดียว แต่ไม่ใช่ - ยังมีอะไรอีกมากมายเกิดขึ้นที่นี่ เมื่อใดก็ตามที่มีการแก้ไขพื้นที่จัดเก็บไฟล์ เนื้อหาทั้งหมดจะถูกสำรองข้อมูลก่อน สมมติว่าไฟล์ชื่อ my_biggest_secrets จากนั้นข้อมูลสำรองจะเป็น my_biggest_secrets.backup ถัดไป แคชจะถูกเปลี่ยน (เพิ่มหรือลบคีย์) และหากทุกอย่างสำเร็จ แคชจะถูกทิ้งลงในไฟล์ ในบางกรณีที่เกิดขึ้นไม่บ่อยนัก เช่น เซิร์ฟเวอร์ขัดข้อง คุณอาจเห็นไฟล์สำรองข้อมูลนี้ ไฟล์สำรองข้อมูลจะถูกลบในครั้งถัดไปที่โหลดคีย์ (โดยปกติหลังจากรีสตาร์ทเซิร์ฟเวอร์)

เมื่อบันทึกหรือลบคีย์ในร้านค้าเซิร์ฟเวอร์ ร้านค้าจะต้องเชื่อมต่อกับเซิร์ฟเวอร์ MySQL ด้วยคำสั่ง "ส่งคีย์" / "ขอลบคีย์"

กลับไปที่ความเร็วเริ่มต้นของเซิร์ฟเวอร์กันดีกว่า นอกเหนือจากข้อเท็จจริงที่ว่าห้องนิรภัยนั้นส่งผลต่อความเร็วในการเริ่มต้นระบบแล้ว ยังมีคำถามว่าต้องได้รับกุญแจจำนวนเท่าใดจากห้องนิรภัยเมื่อเริ่มต้นระบบ แน่นอนว่านี่เป็นสิ่งสำคัญอย่างยิ่งสำหรับการจัดเก็บเซิร์ฟเวอร์ เมื่อเริ่มต้นระบบ เซิร์ฟเวอร์จะตรวจสอบว่าคีย์ใดที่จำเป็นสำหรับตาราง/พื้นที่ตารางที่เข้ารหัส และขอคีย์จากที่จัดเก็บข้อมูล บนเซิร์ฟเวอร์ "สะอาด" ที่มีมาสเตอร์คีย์ - ต้องมีมาสเตอร์คีย์หนึ่งอันสำหรับการเข้ารหัส ซึ่งจะต้องดึงข้อมูลจากที่จัดเก็บข้อมูล อย่างไรก็ตาม อาจจำเป็นต้องใช้คีย์เพิ่มเติม เช่น เมื่อมีการคืนค่าการสำรองข้อมูลจากเซิร์ฟเวอร์หลักไปยังเซิร์ฟเวอร์สำรอง ในกรณีเช่นนี้ ควรจัดให้มีการหมุนเวียนมาสเตอร์คีย์ เราจะกล่าวถึงรายละเอียดเพิ่มเติมในบทความต่อๆ ไป แม้ว่าในที่นี้ ฉันอยากจะทราบว่าเซิร์ฟเวอร์ที่ใช้มาสเตอร์คีย์หลายอันอาจใช้เวลาในการเริ่มต้นนานกว่าเล็กน้อย โดยเฉพาะอย่างยิ่งเมื่อใช้ที่เก็บคีย์เซิร์ฟเวอร์

ตอนนี้เรามาพูดคุยเพิ่มเติมอีกเล็กน้อยเกี่ยวกับ keyring_file ตอนที่ฉันออกแบบ keyring_file ฉันยังกังวลเกี่ยวกับวิธีตรวจสอบการเปลี่ยนแปลง keyring_file ในขณะที่เซิร์ฟเวอร์กำลังทำงานอยู่ ในเวอร์ชัน 5.7 การตรวจสอบดำเนินการตามสถิติของไฟล์ ซึ่งไม่เหมาะ และในเวอร์ชัน 8.0 ถูกแทนที่ด้วยการตรวจสอบผลรวม SHA256

ครั้งแรกที่รัน keyring_file สถิติของไฟล์และเช็คซัมจะถูกคำนวณและจดจำโดยเซิร์ฟเวอร์ และการเปลี่ยนแปลงจะถูกนำไปใช้หากตรงกันเท่านั้น เมื่อไฟล์เปลี่ยนแปลง เช็คซัมจะได้รับการอัปเดต

เราได้กล่าวถึงคำถามมากมายเกี่ยวกับร้านขายคีย์แล้ว อย่างไรก็ตาม มีหัวข้อสำคัญอีกหัวข้อหนึ่งที่มักถูกลืมหรือเข้าใจผิด นั่นคือการแชร์คีย์ระหว่างเซิร์ฟเวอร์

สิ่งที่ผมหมายถึง? แต่ละเซิร์ฟเวอร์ (เช่น Percona Server) ในคลัสเตอร์จะต้องมีตำแหน่งแยกต่างหากบน Vault Server ซึ่ง Percona Server จะต้องจัดเก็บคีย์ของตน มาสเตอร์คีย์แต่ละคีย์ที่จัดเก็บไว้ใน Vault จะมี Percona Server GUID อยู่ภายใน ID ทำไมมันถึงสำคัญ? ลองนึกภาพว่าคุณมี Vault Server เพียงเซิร์ฟเวอร์เดียวและเซิร์ฟเวอร์ Percona ทั้งหมดในคลัสเตอร์ใช้ Vault Server เดียวนี้ ปัญหาดูเหมือนชัดเจน หากเซิร์ฟเวอร์ Percona ทั้งหมดใช้มาสเตอร์คีย์โดยไม่มีตัวระบุเฉพาะ เช่น id = 1, id = 2 เป็นต้น เซิร์ฟเวอร์ทั้งหมดในคลัสเตอร์จะใช้มาสเตอร์คีย์เดียวกัน นี่คือสิ่งที่ GUID มอบให้ - ความแตกต่างระหว่างเซิร์ฟเวอร์ เหตุใดจึงต้องพูดถึงการแชร์คีย์ระหว่างเซิร์ฟเวอร์หากมี GUID ที่ไม่ซ้ำกันอยู่แล้ว มีปลั๊กอินอื่น - keyring_udf ด้วยปลั๊กอินนี้ ผู้ใช้เซิร์ฟเวอร์ของคุณสามารถจัดเก็บคีย์ของตนไว้บนเซิร์ฟเวอร์ห้องนิรภัยได้ ปัญหาเกิดขึ้นเมื่อผู้ใช้สร้างคีย์ เช่น บนเซิร์ฟเวอร์ 1 จากนั้นพยายามสร้างคีย์ด้วย ID เดียวกันบนเซิร์ฟเวอร์ 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 หรือปลั๊กอิน vault อื่น ๆ (พวงกุญแจ) จะแคช ID คีย์ทั้งหมดในหน่วยความจำ ดังนั้น หลังจากสร้างคีย์ใหม่แล้ว ROB_1 จะถูกเพิ่มไปยังเซิร์ฟเวอร์1 และนอกเหนือจากการส่งคีย์นี้ไปยังห้องนิรภัยแล้ว คีย์นั้นยังถูกเพิ่มลงในแคชด้วย ตอนนี้เมื่อเราพยายามเพิ่มคีย์เดียวกันเป็นครั้งที่สอง keyring_vault จะตรวจสอบว่าคีย์นั้นมีอยู่ในแคชหรือไม่และส่งข้อผิดพลาดออกมา

ในกรณีแรก สถานการณ์แตกต่างออกไป Server1 และ server2 มีแคชแยกกัน หลังจากเพิ่ม ROB_1 ไปยังคีย์แคชบนเซิร์ฟเวอร์ 1 และเซิร์ฟเวอร์ห้องนิรภัยแล้ว คีย์แคชบนเซิร์ฟเวอร์ 2 จะไม่ซิงค์กัน แคชบนเซิร์ฟเวอร์ 2 ไม่มีคีย์ ROB_1 ดังนั้นคีย์ ROB_1 จึงถูกเขียนไปยัง keyring_key_store และไปยังเซิร์ฟเวอร์ Vault ซึ่งจริงๆ แล้วเขียนทับ (!) ค่าก่อนหน้า ตอนนี้คีย์ ROB_1 บนเซิร์ฟเวอร์ Vault คือ 543210987654321 สิ่งที่น่าสนใจคือเซิร์ฟเวอร์ Vault ไม่ได้บล็อกการกระทำดังกล่าวและเขียนทับค่าเก่าได้อย่างง่ายดาย

ตอนนี้เราเข้าใจแล้วว่าทำไมการแบ่งแยกตามเซิร์ฟเวอร์ในห้องนิรภัยจึงมีความสำคัญเมื่อคุณใช้ keyring_udf และต้องการจัดเก็บคีย์ไว้ในห้องนิรภัย จะให้การแยกดังกล่าวในเซิร์ฟเวอร์ 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 = (...)

ในกรณีนี้ เซิร์ฟเวอร์ทั้งสองใช้จุดเชื่อมต่อ "mount_point" เดียวกัน แต่มีเส้นทางต่างกัน เมื่อคุณสร้างข้อมูลลับแรกบนเซิร์ฟเวอร์ 1 โดยใช้เส้นทางนี้ เซิร์ฟเวอร์ห้องนิรภัยจะสร้างไดเรกทอรี "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) สอดคล้องกับพารามิเตอร์ของไฟล์การกำหนดค่า แน่นอน คุณสามารถใช้ยูทิลิตี้ห้องนิรภัยเพื่อทำเช่นเดียวกันได้ แต่การสร้างจุดเชื่อมต่ออัตโนมัตินั้นง่ายกว่า ฉันหวังว่าคุณจะพบว่าข้อมูลนี้มีประโยชน์และพบกันในบทความถัดไปในชุดนี้

การเข้ารหัสใน MySQL: Keystore

อ่านเพิ่มเติม:

ที่มา: will.com

เพิ่มความคิดเห็น