Memahami Always Encrypted
Selalu terenkripsi mengenkripsi data sensitif seperti nomor kartu kredit atau informasi penggajian di dalam aplikasi sisi klien. Database menerima data yang sudah dienkripsi dari sisi klien, dan tidak berisi kunci dekripsi. Ini berarti bahwa database tidak memiliki cara untuk mendekripsi data ini. Ketika klien membutuhkan data, database akan mengirim data terenkripsi kembali dan karena klien memiliki kunci dekripsi, klien akan mendekripsi data.
Always Encrypted memberikan kemampuan enkripsi sisi klien ke Azure Cosmos DB. Karena data dienkripsi di sisi klien, layanan Azure Cosmos DB tidak pernah dilengkapi dengan kunci dekripsi atau data yang tidak terenkripsi. Anda memiliki, mengontrol, dan mengelola kunci dekripsi. kunci ini disimpan di Azure Key Vault, tempat Anda dapat menerapkan kebijakan untuk mengontrol kunci dan rahasia apa yang dapat diakses setiap klien.
Konsep selalu terenkripsi
Selalu dienkripsi menggunakan kunci enkripsi dan kebijakan dekripsi.
Kunci enkripsi
Kunci Enkripsi Data
Selalu dienkripsi mengharuskan Anda membuat kunci enkripsi data (DEK) sebelumnya. DEK dibuat di sisi klien menggunakan Azure Comsos DB SDK. DEK ini disimpan dalam layanan Azure Cosmos DB. DEK didefinisikan pada tingkat database sehingga DEK dapat dibagi di beberapa kontainer. Setiap DEK yang Anda buat dapat digunakan untuk mengenkripsi hanya satu properti, atau dapat digunakan untuk mengenkripsi banyak properti. Anda dapat memiliki beberapa DEK per database.
Kunci yang dikelola pelanggan
DEK harus dibungkus dengan kunci yang dikelola pelanggan (CMK) sebelum disimpan di Azure Cosmos DB. Karena CMK mengontrol pembungkusan dan pelepasan DEK, CMK mengontrol akses ke data yang dienkripsi dengan DEK tersebut. Penyimpanan CMK dirancang sebagai model yang dapat diperluas/plug-in, dengan implementasi default yang dapat disimpan di Azure Key Vault. Hubungan antara komponen-komponen ini ditampilkan dalam diagram berikut.
Kebijakan enkripsi
Kebijakan enkripsi adalah spesifikasi tingkat kontainer yang menjelaskan bagaimana properti JSON harus dienkripsi. Kebijakan ini mirip dengan kebijakan pengindeksan dalam struktur. Dalam rilis saat ini, Anda harus membuat kebijakan ini pada waktu pembuatan kontainer dan tidak dapat diperbarui setelah dibuat.
Untuk setiap properti yang ingin Anda enkripsi, kebijakan enkripsi menentukan:
- Jalur properti dalam bentuk /property. Hanya jalur tingkat atas yang saat ini didukung, jalur berlapis seperti /path/to/property tidak didukung.
- ID dari DEK yang digunakan saat mengenkripsi dan mendekripsi properti.
- Jenis enkripsi. Ini dapat berupa proses acak atau proses deterministik.
- Algoritma enkripsi yang digunakan saat mengenkripsi properti. Algoritma yang ditentukan dapat mengambil alih algoritma yang ditentukan saat membuat kunci jika kompatibel.
Anda tidak dapat mengenkripsi ID atau kunci partisi kontainer.
Enkripsi acak vs. deterministik
Karena layanan Azure Cosmos DB mungkin perlu mendukung beberapa kemampuan kueri melalui data terenkripsi, dan tidak dapat mengevaluasi data dalam teks biasa, Always Encrypted memiliki lebih dari satu jenis enkripsi. Jenis enkripsi yang didukung oleh Always Encrypted adalah:
Enkripsi deterministik: Ini selalu menghasilkan nilai terenkripsi yang sama untuk nilai teks biasa dan konfigurasi enkripsi tertentu. Menggunakan enkripsi deterministik memungkinkan kueri untuk melakukan filter kesetaraan pada properti terenkripsi. Namun, enkripsi ini dapat memungkinkan penyerang untuk menebak informasi tentang nilai terenkripsi dengan memeriksa pola di properti terenkripsi. Hal ini terutama berlaku jika ada sekumpulan kecil nilai terenkripsi yang memungkinkan, seperti True/False, atau wilayah Utara/Selatan/Timur/Barat.
Enkripsi acak: Ini menggunakan metode yang mengenkripsi data dengan cara yang kurang dapat diprediksi. Enkripsi acak lebih aman, tetapi mencegah kueri memfilter properti terenkripsi.
Menyiapkan dan menggunakan Always Encrypted dengan Azure Cosmos DB
Menyiapkan Always encrypted akan menjadi proses multi-langkah, mulai dari mengatur CMK Anda di Azure Key Vault hingga membuat DEK Anda dan akhirnya membuat kontainer dengan kebijakan enkripsi.
Penyiapan Azure Key Vault
Sebelum membuat CMK, kita perlu membuat yang baru atau menggunakan Azure Key Vault yang sudah ada untuk menyimpan CMK.
- Di portal Azure, ikuti instruksi untuk membuat Azure Key Vault baru atau pilih dan yang sudah ada.
- Di bawah Kunci, buat Kunci baru.
- Setelah kunci dibuat, telusuri ke versi saat ini, dan salin pengidentifikasi kunci lengkapnya:
https://<my-key-vault>.vault.azure.net/keys/<key>/<version>
. Jika Anda ingin selalu menggunakan versi kunci terbaru, abaikan saja versi kunci di akhir pengidentifikasi kunci.
Identitas Microsoft Entra akan diperlukan untuk memberikan akses Azure Cosmos DB SDK ke instans Azure Key Vault. Aplikasi Microsoft Entra atau identitas terkelola umumnya digunakan sebagai proksi antara kode klien dan instans Azure Key Vault. Untuk menggunakan aplikasi AD sebagai proksi, gunakan langkah-langkah berikut:
- Buat aplikasi Microsoft Entra baru dan tambahkan rahasia klien seperti yang dijelaskan dalam mulai cepat ini.
- Di instans Azure Key Vault, di bawah Kebijakan akses, pilih + Tambahkan Kebijakan Akses dan tambahkan kebijakan baru:
- Di Izin kunci, pilih Dapatkan, Daftar, Membuka Pembungkus Kunci, Membungkus Kunci, **Verifikasi, dan Tandai.
- Di Pilih Utama, cari aplikasi Microsoft Entra yang telah Anda buat sebelumnya.
Menginisialisasi SDK
Untuk menggunakan Always Encrypted, instans suatu EncryptionKeyStoreProvider
harus dilampirkan ke instans Azure Cosmos DB SDK Anda. Objek ini digunakan untuk berinteraksi dengan penyimpanan kunci yang menghosting CMK Anda. Penyedia penyimpanan kunci default untuk Azure Key Vault diberi nama AzureKeyVaultKeyStoreProvider
. Untuk menggunakan AzureKeyVaultKeyStoreProvider
, Anda harus menambahkan paket Microsoft.Data.Encryption.AzureKeyVaultProvider
.
Cuplikan berikut menunjukkan cara menggunakan identitas aplikasi Microsoft Entra dengan rahasia klien.
var tokenCredential = new ClientSecretCredential(
"<aad-app-tenant-id>", "<aad-app-client-id>", "<aad-app-secret>");
var keyStoreProvider = new AzureKeyVaultKeyStoreProvider(tokenCredential);
var client = new CosmosClient("<connection-string>")
.WithEncryption(keyStoreProvider);
Membuat kunci enkripsi data
Setelah membuat CMK di Azure Key Vault, saatnya membuat DEK di database induk. Untuk membuat DEK ini, kita akan menggunakan metode CreateClientEncryptionKeyAsync
dan meneruskan informasi berikut:
- Pengidentifikasi string yang akan mengidentifikasi kunci dalam database secara unik.
- Algoritma enkripsi yang dimaksudkan untuk digunakan dengan kunci. Saat ini, hanya satu algoritma yang didukung.
- Pengidentifikasi utama CMK yang disimpan di Azure Key Vault. Parameter ini diteruskan dalam objek generik
EncryptionKeyWrapMetadata
saatname
dapat berupa nama apa pun yang Anda inginkan, danvalue
harus menjadi pengidentifikasi utama.
Cuplikan berikut menunjukkan bagaimana kita membuat DEK ini di .NET.
var database = client.GetDatabase("my-database");
await database.CreateClientEncryptionKeyAsync(
"my-key",
DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256,
new EncryptionKeyWrapMetadata(
keyStoreProvider.ProviderName,
"akvKey",
"https://<my-key-vault>.vault.azure.net/keys/<key>/<version>"));
Ini adalah praktik keamanan yang baik untuk memutar CMK Anda secara teratur. Anda juga harus memutar CMK Anda jika Anda menduga bahwa CMK saat ini telah disusupi. Setelah CMK diputar, Anda memberikan pengidentifikasi CMK baru untuk pembuat ulang DEK untuk mulai menggunakannya. Operasi ini tidak memengaruhi enkripsi data Anda, tetapi perlindungan DEK. Tinjau skrip berikut yang membuka kembali CMK baru ke DEK:
await database.RewrapClientEncryptionKeyAsync(
"my-key",
new EncryptionKeyWrapMetadata(
keyStoreProvider.ProviderName,
"akvKey",
" https://<my-key-vault>.vault.azure.net/keys/<new-key>/<version>"));
Membuat kontainer dengan kebijakan enkripsi
Sekarang setelah kita mengonfigurasi CMK dan DEK, saatnya membuat kontainer baru menggunakan SDK .NET. Cuplikan berikut menunjukkan cara kami membuat penampung my-container
menggunakan DEK my-key
yang dibuat pada contoh sebelumnya. Kontainer ini akan memiliki kebijakan dua enkripsi pada properti, property1
dan, property2
dan kunci partisi partition-key
. Kedua properti akan menggunakan my-key
DEK, tetapi satu akan menggunakan deterministik jenis enkripsi, sementara yang lain akan menggunakan acak.
var path1 = new ClientEncryptionIncludedPath
{
Path = "/property1",
ClientEncryptionKeyId = "my-key",
EncryptionType = EncryptionType.Deterministic.ToString(),
EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256.ToString()
};
var path2 = new ClientEncryptionIncludedPath
{
Path = "/property2",
ClientEncryptionKeyId = "my-key",
EncryptionType = EncryptionType.Randomized.ToString(),
EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AEAD_AES_256_CBC_HMAC_SHA256.ToString()
};
await database.DefineContainer("my-container", "/partition-key")
.WithClientEncryptionPolicy()
.WithIncludedPath(path1)
.WithIncludedPath(path2)
.Attach()
.CreateAsync();
Menulis data terenkripsi
Saat dokumen Azure Cosmos DB ditulis, SDK mengevaluasi kebijakan enkripsi untuk menentukan apakah ada properti yang perlu dienkripsi dan cara mengenkripsinya. Jika properti perlu dienkripsi, itu membuat string dasar 64 di tempat teks asli.
Enkripsi jenis kompleks
- Saat properti untuk dienkripsi adalah array JSON, setiap entri array dienkripsi.
- Saat properti untuk dienkripsi adalah objek JSON, hanya nilai leaf objek yang akan dienkripsi. Nama subproperti perantara tetap dalam bentuk teks biasa.
Membaca item terenkripsi
Jika Anda mengambil satu item dengan ID
dan kunci partisi, menjalankan kueri, atau membaca umpan perubahan, tidak ada langkah tambahan yang diperlukan untuk mendekripsi properti terenkripsi. Ini karena SDK mengetahui properti mana yang perlu didekripsi dengan mencari kebijakan enkripsi.
Memfilter kueri pada properti terenkripsi
Metode AddParameterAsync
meneruskan nilai parameter kueri yang digunakan dalam kueri yang memfilter properti terenkripsi. Metode ini membutuhkan argumen berikut:
- Nama parameter kueri.
- Nilai yang akan digunakan dalam kueri.
- Jalur properti terenkripsi (sebagaimana didefinisikan dalam kebijakan enkripsi).
Kita bisa melihat contoh yang menggunakan AddParameterAsync
di bawah ini:
var queryDefinition = container.CreateQueryDefinition(
"SELECT * FROM c where c.property1 = @Property1");
await queryDefinition.AddParameterAsync(
"@Property1",
1234,
"/property1");
Properti terenkripsi hanya dapat digunakan dalam filter kesetaraan (WHERE c.property = @Value
). Penggunaan lainnya akan mengembalikan hasil kueri yang tidak dapat diprediksi dan salah.
Membaca dokumen hanya saat sekumpulan properti dapat didekripsi
Properti dokumen yang berbeda dalam kontainer yang sama dapat menggunakan kebijakan enkripsi yang berbeda. Setiap kebijakan dapat menggunakan CMK yang berbeda untuk mengenkripsi properti. Jika klien Anda memiliki akses ke beberapa CMK yang digunakan untuk mendekripsi beberapa properti, tetapi tidak mengakses CMK lain untuk mendekripsi properti lain, Anda masih dapat meminta sebagian dokumen dengan properti yang dapat Anda dekripsi. Anda hanya harus menghapus properti tersebut dari kueri Anda, yang Anda tidak memiliki akses ke CMK mereka. Misalnya, jika property1
dienkripsi dengan key1
dan property2
dienkripsi dengan key2
, dan aplikasi Anda hanya memiliki akses ke key1
, kueri Anda harus mengabaikan property2
. Kueri ini dapat terlihat seperti, SELECT c.property1, c.property3 FROM c
.