Banyak organisasi, terutama yang finansial, harus berurusan dengan berbagai standar keamanan - misalnya, PCI DSS. Sertifikasi semacam itu memerlukan enkripsi data. Enkripsi data transparan pada disk Enkripsi Data Transparan diimplementasikan di banyak DBMS industri.
Apache Ignite digunakan di bank, oleh karena itu, diputuskan untuk mengimplementasikan TDE di dalamnya.
Saya akan menjelaskan bagaimana kami mengembangkan TDE melalui komunitas, secara publik, melalui proses Apachev.
Di bawah ini adalah versi teks laporan:
Saya akan mencoba berbicara tentang arsitektur, tentang kompleksitas pembangunan, bagaimana tampilannya di open source.
Apa yang telah dilakukan dan apa yang masih harus dilakukan?
Apache Ignite TDE saat ini diimplementasikan. Fase 1.
Ini termasuk fitur dasar bekerja dengan cache terenkripsi:
- Manajemen kunci
- Membuat Tembolok Terenkripsi
- Menyimpan semua data cache ke disk dalam bentuk terenkripsi
Pada Fase 2, direncanakan untuk memungkinkan kemungkinan rotasi (perubahan) dari kunci master.
Dalam Fase 3, kemampuan untuk memutar kunci cache.
Terminologi
- Enkripsi Data Transparan - enkripsi data transparan (untuk pengguna) saat menyimpan ke disk. Dalam kasus Ignite, enkripsi cache, karena Ignite adalah tentang cache.
- Ignite cache - cache nilai kunci di Apache Ignite. Data cache dapat disimpan ke disk
- Halaman - halaman data. Di Ignite, semua data diberi nomor halaman. Halaman ditulis ke disk dan harus dienkripsi.
- WAL - tulis log di depan. Semua perubahan data di Ignite disimpan di sana, semua tindakan yang kami lakukan untuk semua cache.
- Keystore - standar java keystore, yang dihasilkan oleh keytool Javascript. Ini berfungsi dan disertifikasi di mana-mana, kami menggunakannya.
- Kunci utama - kunci utama. Dengan menggunakannya, kunci untuk tabel dienkripsi, kunci enkripsi cache. Disimpan di java keystore.
- Kunci cache - kunci yang dengannya data sebenarnya dienkripsi. Bersama dengan kunci master, struktur dua tingkat diperoleh. Kunci master disimpan secara terpisah dari cache kunci dan data master - untuk tujuan keamanan, pemisahan hak akses, dll.
Arsitektur
Semuanya diimplementasikan sesuai dengan skema berikut:
- Semua data cache dienkripsi menggunakan Enkripsi SPI baru.
- Secara default, AES digunakan - suatu algoritma enkripsi industri.
- Kunci master disimpan dalam file JKS - file java standar untuk kunci.
Bank dan organisasi lain menggunakan algoritma enkripsi mereka sendiri: GOST dan lainnya. Jelas bahwa kami telah memberikan kesempatan untuk menyelipkan Enkripsi SPI kami - implementasi enkripsi yang dibutuhkan pengguna tertentu.
Skema kerja

Jadi, kami memiliki RAM - memori akses acak dengan halaman yang berisi data murni. Menggunakan RAM menyiratkan bahwa kita tidak terlindungi dari peretas yang mendapatkan akses root dan membuang semua memori. Kami melindungi diri dari administrator yang mengambil hard drive dan menjualnya di pasar Tushino (atau tempat data serupa sedang dijual).
Selain halaman dengan cache, data juga disimpan dalam log tulis di depan, yang menulis ke disk delta catatan yang diubah dalam transaksi. Metastore menyimpan kunci enkripsi cache. Dan dalam file terpisah - kunci master.
Setiap kali kunci untuk cache dibuat, sebelum menulis atau mentransfer ke jaringan, kami mengenkripsi kunci ini menggunakan kunci utama. Sehingga tidak ada yang bisa mendapatkan kunci cache setelah menerima data Ignite. Hanya dengan mencuri kunci master dan data Anda dapat mengaksesnya. Ini tidak mungkin, karena akses ke file-file ini memerlukan berbagai hak.
Algoritma tindakan adalah sebagai berikut:
- Pada awal node, kurangi kunci utama dari jks.
- Di awal node, baca meta store dan dekripsi kunci cache.
- Ketika bergabung dengan node dalam sebuah cluster:
- memverifikasi hash kunci utama.
- periksa kunci untuk cache bersama.
- Simpan kunci untuk cache baru.
- Saat membuat cache secara dinamis, kami menghasilkan kunci dan menyimpannya di meta store.
- Saat membaca / menulis halaman, kami mendekripsi / mengenkripsi itu.
- Setiap entri WAL untuk cache terenkripsi juga dienkripsi.
Sekarang lebih terinci:
Pada awal node, kami memiliki panggilan balik yang meluncurkan EncryptionSPI kami. Menurut parameter, kami mengurangi kunci utama dari file jks.
Selanjutnya, ketika metastore siap, kita mendapatkan kunci enkripsi yang tersimpan. Dalam hal ini, kami sudah memiliki kunci master, sehingga kami dapat mendekripsi kunci dan mendapatkan akses ke data cache.
Secara terpisah, ada proses yang sangat menarik - bagaimana kita bergabung dengan simpul baru ke dalam sebuah cluster. Kami sudah memiliki sistem terdistribusi yang terdiri dari beberapa node. Bagaimana cara memastikan bahwa node baru dikonfigurasi dengan benar, bahwa itu bukan penyerang?
Kami melakukan tindakan ini:
- Ketika sebuah node baru tiba, ia mengirimkan hash dari kunci master. Kami melihat bahwa itu cocok dengan yang sudah ada.
- Kemudian kami memverifikasi kunci untuk cache bersama. Dari node tersebut muncul pengidentifikasi cache dan kunci cache terenkripsi. Kami memeriksa mereka untuk memastikan bahwa semua data pada semua node dienkripsi dengan kunci yang sama. Jika tidak demikian, maka kita tidak punya hak untuk membiarkan node masuk ke cluster, jika tidak, ia akan bepergian dengan kunci dan data.
- Jika ada kunci dan cache baru pada node baru, simpan untuk digunakan di lain waktu.
- Saat membuat cache secara dinamis, fungsi pembuatan kunci disediakan. Kami menghasilkannya, menyimpannya di meta store dan dapat terus melakukan operasi yang dijelaskan.
Bagian kedua adalah suprastruktur atas operasi I / O. Halaman ditulis ke file partisi. Add-in kami mencari cache halaman mana, mengenkripsi mereka sesuai dan menyimpannya.
Hal yang sama berlaku untuk WAL. Ada serializer yang membuat serial objek rekaman WAL. Dan jika catatan adalah untuk cache terenkripsi, maka kita harus mengenkripsi dan hanya menyimpannya ke disk.
Kesulitan pengembangan
Kesulitan umum untuk semua proyek open source yang lebih atau kurang kompleks:
- Pertama, Anda perlu memahami perangkat Ignite sama sekali. Mengapa, apa, dan bagaimana hal itu dilakukan di sana, bagaimana dan di tempat apa untuk melampirkan penangan Anda.
- Penting untuk memberikan kompatibilitas ke belakang. Ini bisa sangat sulit, tidak jelas. Saat mengembangkan produk yang digunakan orang lain, Anda perlu mempertimbangkan bahwa pengguna ingin diperbarui tanpa masalah. Kompatibilitas mundur benar dan baik. Ketika Anda membuat perbaikan besar seperti TDE, Anda mengubah aturan untuk menyimpan ke disk, Anda mengenkripsi sesuatu. Dan kompatibilitas ke belakang harus dikerjakan.
- Poin tidak jelas lainnya terkait dengan distribusi sistem kami. Ketika klien berbeda mencoba membuat cache yang sama, Anda harus menyetujui kunci enkripsi, karena secara default dua yang berbeda akan dihasilkan. Kami telah memecahkan masalah ini. Saya tidak akan membahas lebih detail - solusinya layak mendapat posting terpisah. Sekarang kami dijamin menggunakan satu kunci.
- Hal penting berikutnya mengarah pada perbaikan besar, ketika tampaknya semuanya sudah siap (cerita yang akrab?) :). Enkripsi memiliki overhead. Kami memiliki vektor init - nol data acak yang digunakan dalam algoritma AES. Mereka disimpan dalam bentuk terbuka, dan dengan bantuan mereka kami meningkatkan entropi: data yang sama akan dienkripsi secara berbeda dalam sesi enkripsi yang berbeda. Secara kasar, bahkan jika kita memiliki dua Ivan Petrovs dengan nama keluarga yang sama, setiap kali kita mengenkripsi, kita akan menerima data terenkripsi yang berbeda. Ini mengurangi kemungkinan peretasan.
Enkripsi terjadi dalam blok 16 byte, dan jika data tidak disejajarkan dengan 16 byte, maka kami menambahkan info padding - berapa banyak data yang sebenarnya telah kami enkripsi. Pada disk Anda harus menulis halaman yang merupakan kelipatan dari 2 Kb. Ini adalah persyaratan kinerja: kita harus menggunakan buffer disk. Jika kita menulis bukan 2 Kb (bukan 4 atau tidak 8, tergantung pada buffer disk), maka kita segera mendapatkan kinerja penurunan besar.
Bagaimana kami memecahkan masalah? Saya harus merangkak ke PageIO, dalam RAM dan memotong 16 byte dari setiap halaman, yang akan dienkripsi ketika ditulis ke disk. Dalam 16 byte ini kita menulis vektor init.
- Kesulitan lain adalah tidak merusak apa pun. Ini adalah hal yang umum ketika Anda datang dan melakukan beberapa perubahan. Pada kenyataannya, itu tidak sesederhana kelihatannya.
- Di MVP ternyata 6 ribu baris. Sulit untuk ditinjau, dan beberapa orang ingin melakukan ini - terutama dari para ahli yang sudah tidak punya waktu. Kami memiliki berbagai bagian - API publik, bagian inti, manajer SPI, toko persisten untuk halaman, manajer WAL. Perubahan dalam berbagai subsistem mengharuskan mereka ditinjau oleh orang yang berbeda. Dan ini juga menimbulkan kesulitan tambahan. Terutama ketika Anda bekerja di komunitas tempat semua orang sibuk dengan tugasnya. Namun demikian, semuanya berjalan baik bagi kami.
Apa yang akan terjadi di TDE. Fase 2 dan 3
Fase 1 sekarang diimplementasikan. Anda, sebagai pengembang, dapat membantu dengan Fase 2. Tantangan di depan menarik. PCI DSS, seperti standar lainnya, memerlukan fitur tambahan dari sistem enkripsi. Sistem kami harus dapat mengubah kunci master. Misalnya, jika ia dikompromikan atau waktunya baru saja datang sesuai dengan kebijakan keamanan. Sekarang Ignite tidak tahu caranya. Namun dalam rilis mendatang, kami akan mengajarkan TDE untuk mengubah kunci master.
Hal yang sama dengan kemampuan untuk mengubah kunci cache tanpa menghentikan cluster dan bekerja dengan data. Jika cache berumur panjang dan pada saat yang sama menyimpan beberapa data - finansial, medis - Ignite harus dapat mengubah kunci enkripsi cache dan mengenkripsi ulang semuanya dengan cepat. Kami akan memecahkan masalah ini di fase ketiga.
Total: Bagaimana menerapkan fitur besar dalam proyek sumber terbuka?
Untuk meringkas. Mereka akan relevan untuk sumber terbuka apa pun. Saya berpartisipasi dalam Kafka dan dalam proyek-proyek lain - di mana-mana ceritanya sama.
- Mulailah dengan tugas-tugas kecil. Jangan pernah mencoba memecahkan masalah yang sangat besar segera. Penting untuk memahami apa yang terjadi, bagaimana itu terjadi, bagaimana hal itu diwujudkan. Siapa yang akan membantu Anda? Dan secara umum - dari sisi mana untuk mendekati proyek ini.
- Pahami proyeknya. Biasanya, semua pengembang - setidaknya saya - datang dan berkata: semuanya harus ditulis ulang. Semuanya buruk sebelum saya, dan sekarang saya akan menulis ulang - dan semuanya akan baik-baik saja. Dianjurkan untuk menunda pernyataan seperti itu, untuk mencari tahu apa yang sebenarnya buruk dan apakah perlu diubah.
- Diskusikan apakah perbaikan diperlukan. Saya punya kasus ketika saya datang ke berbagai komunitas dengan pengalaman, misalnya, di Spark. Dia memberi tahu saya, tetapi komunitas itu tidak tertarik karena suatu alasan. Bagaimanapun itu terjadi. Anda memerlukan revisi ini, tetapi komunitas mengatakan: tidak, kami tidak tertarik, kami tidak akan bergabung dan membantu.
- Buat desain. Ada proyek open source di mana ini wajib. Anda tidak dapat memulai pengkodean tanpa desain yang disetujui oleh panitia dan orang yang berpengalaman. Dalam Ignite, ini tidak benar secara formal, tetapi secara umum ini adalah bagian penting dari pengembangan. Penting untuk membuat deskripsi dalam bahasa Inggris atau Rusia yang kompeten, tergantung pada proyek. Agar teks dapat dibaca dan jelas apa yang akan Anda lakukan.
- Diskusikan API publik. Argumen utama: jika ada API publik yang indah dan mudah dipahami yang mudah digunakan, maka desainnya benar. Hal-hal ini biasanya berdekatan satu sama lain.
Kiat lebih lanjut yang lebih jelas yang tidak mudah diikuti:
- Terapkan fitur tanpa merusak apa pun. Lakukan tes.
- Tanyakan dan tunggu (ini yang paling sulit) untuk mendapat ulasan dari orang yang tepat, dari anggota komunitas yang tepat.
- Buat tolok ukur, cari tahu apakah Anda mengalami penurunan kinerja. Ini sangat penting ketika menyelesaikan beberapa subsistem kritis.
- Tunggu penggabungan, lakukan beberapa contoh dan dokumentasi.
Terima kasih sudah membaca!