Bagikan melalui


Menggunakan enkripsi sisi klien dengan Always Encrypted untuk Azure Cosmos DB

BERLAKU UNTUK: NoSQL

Penting

Perubahan besar telah diperkenalkan dengan rilis 1.0 paket enkripsi kami. Jika Anda membuat kunci enkripsi data dan kontainer yang mendukung enkripsi dengan versi sebelumnya, Anda perlu membuat ulang database dan kontainer Anda setelah memigrasikan kode klien ke paket 1.0.

Always Encrypted adalah fitur yang dirancang untuk melindungi data sensitif, seperti nomor kartu kredit atau nomor identifikasi nasional/regional (misalnya, nomor jaminan sosial AS), yang disimpan di Azure Cosmos DB. Always Encrypted memungkinkan klien untuk mengenkripsi data sensitif di dalam aplikasi klien dan tidak pernah mengungkapkan kunci enkripsi ke database.

Always Encrypted memberikan kemampuan enkripsi sisi klien ke Azure Cosmos DB. Mengenkripsi sisi klien data Anda mungkin diperlukan dalam skenario berikut:

  • Melindungi data sensitif yang memiliki karakteristik kerahasiaan khusus: Always Encrypted memungkinkan klien untuk mengenkripsi data sensitif di dalam aplikasi mereka dan tidak pernah mengungkapkan data teks biasa atau kunci enkripsi ke layanan Azure Cosmos DB.
  • Menerapkan kontrol akses per properti: Karena enkripsi dikontrol dengan kunci yang Anda miliki dan dikelola dari Azure Key Vault, Anda dapat menerapkan kebijakan akses untuk mengontrol properti sensitif mana yang dapat diakses oleh setiap klien.

Konsep

Always Encrypted untuk Azure Cosmos DB memperkenalkan beberapa konsep baru yang terlibat dalam konfigurasi enkripsi sisi klien Anda.

Kunci enkripsi

Kunci enkripsi data

Saat menggunakan Always Encrypted, data dienkripsi dengan kunci enkripsi data (DEK) yang harus dibuat sebelumnya. DEK ini disimpan dalam layanan Azure Cosmos DB dan diatur pada tingkat database, sehingga DEK dapat dibagikan di beberapa kontainer. Pembuatan DEK dilakukan dari sisi klien dengan menggunakan Azure Cosmos DB SDK.

Anda dapat:

  • Membuat satu DEK per properti untuk mengenkripsi, atau
  • Menggunakan DEK yang sama untuk mengenkripsi beberapa properti.

Kunci yang dikelola pelanggan

Sebelum DEK disimpan di Azure Cosmos DB, DEK dibungkus oleh kunci yang dikelola pelanggan (CMK). Dengan mengontrol pembungkusan dan pembukaan bungkusan DEK, CMK mengontrol akses secara efektif ke data yang dienkripsi dengan DEK yang sesuai. Penyimpanan kunci yang dikelola pelanggan dirancang agar dapat diperluas, dengan penerapan default yang mengharapkan penyimpanan kunci yang dikelola pelanggan disimpan di Azure Key Vault.

Kunci enkripsi

Kebijakan enkripsi

Mirip dengan kebijakan pengindeksan, kebijakan enkripsi adalah spesifikasi tingkat kontainer yang menjelaskan bagaimana properti JSON harus dienkripsi. Kebijakan ini harus diberikan saat kontainer dibuat dan tidak dapat diubah. Dalam rilis saat ini, Anda tidak dapat memperbarui kebijakan enkripsi.

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 DEK yang digunakan saat mengenkripsi dan mendekripsi properti.
  • Jenis enkripsi. Ini dapat berupa acak atau deterministik.
  • Algoritma enkripsi yang digunakan saat mengenkripsi properti. Algoritma yang ditentukan dapat mengambil alih algoritma yang ditentukan saat membuat kunci jika kompatibel.

Enkripsi acak vs deterministik

Layanan Azure Cosmos DB tidak dapat melihat teks biasa dari properti yang dienkripsi dengan Always Encrypted. Namun, layanan ini masih mendukung beberapa kemampuan kueri melalui data terenkripsi, bergantung pada jenis enkripsi yang digunakan untuk properti. Always Encrypted mendukung dua jenis enkripsi berikut ini:

  • Enkripsi deterministik: Enkripsi ini selalu menghasilkan nilai terenkripsi yang sama untuk nilai teks biasa dan konfigurasi enkripsi apa pun. 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.

Lihat Menghasilkan vektor inisialisasi (IV) untuk mempelajari selengkapnya tentang enkripsi deterministik dan acak di Always Encrypted.

Penyiapan Azure Key Vault

Langkah pertama untuk memulai Always Encrypted adalah membuat CMK di Azure Key Vault:

  1. Buat instans Azure Key Vault baru atau telusuri yang sudah ada.
  2. Buat kunci baru di bagian Kunci.
  3. 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 menghilangkan versi kunci yang ada di akhir pengidentifikasi kunci, versi kunci terbaru akan digunakan.

Selanjutnya, Anda perlu mengonfigurasi bagaimana Azure Cosmos DB SDK akan mengakses instans Azure Key Vault Anda. Autentikasi ini dilakukan melalui identitas Microsoft Entra. Kemungkinan besar, Anda akan menggunakan identitas aplikasi Microsoft Entra atau identitas terkelola sebagai proksi antara kode klien dan instans Azure Key Vault Anda, meskipun segala jenis identitas dapat digunakan. Gunakan langkah-langkah berikut untuk menggunakan identitas Microsoft Entra Anda sebagai proksi:

  1. Kembali ke instans Azure Key Vault Anda, telusuri bagian Kebijakan akses, dan tambahkan kebijakan baru:

    1. Dalam Izin kunci, pilih Dapatkan, Daftar, Buka Bungkus Kunci, Bungkus Kunci, Verifikasi, dan Tanda tangani.
    2. Di Pilih prinsipal, cari identitas Microsoft Entra Anda.

Lindungi CMK Anda dari penghapusan yang tidak disengaja

Untuk memastikan Anda tidak kehilangan akses ke data terenkripsi setelah penghapusan CMK yang tidak disengaja, disarankan untuk mengatur dua properti pada instans Azure Key Vault Anda: Penghapusan Sementara dan Perlindungan Penghapusan Menyeluruh.

Jika Anda membuat instans Azure Key Vault baru, aktifkan properti ini selama pembuatan:

Cuplikan layar properti penghapusan sementara dan perlindungan penghapusan menyeluruh untuk instans Azure Key Vault baru.

Jika Anda menggunakan instans Azure Key Vault yang sudah ada, Anda dapat memverifikasi bahwa properti ini diaktifkan dengan melihat bagian Properti di portal Microsoft Azure. Jika salah satu properti ini tidak diaktifkan, lihat bagian "Mengaktifkan penghapusan sementara" dan "Mengaktifkan Perlindungan Pembersihan Menyeluruh" di salah satu artikel berikut ini:

Menginisialisasi SDK

Catatan

Always Encrypted untuk Azure Cosmos DB saat ini mendukung:

Untuk menggunakan Always Encrypted, instans KeyResolver harus dilampirkan ke instans SDK Azure Cosmos DB Anda. Kelas ini, yang ditentukan dalam namespace Azure.Security.KeyVault.Keys.Cryptography, digunakan untuk berinteraksi dengan penyimpanan kunci yang menghosting kunci yang dikelola pelanggan Anda.

Cuplikan berikut menggunakan DefaultAzureCredential kelas untuk mengambil identitas Microsoft Entra yang akan digunakan saat mengakses instans Azure Key Vault Anda. Anda dapat menemukan contoh pembuatan berbagai jenis kelas TokenCredentialdi sini.

Catatan

Anda memerlukan paket Azure.Identity tambahan untuk mengakses kelas TokenCredential.

var tokenCredential = new DefaultAzureCredential();
var keyResolver = new KeyResolver(tokenCredential);
var client = new CosmosClient("<connection-string>")
    .WithEncryption(keyResolver, KeyEncryptionKeyResolverName.AzureKeyVault);

Membuat kunci enkripsi data

Sebelum data dapat dienkripsi dalam kontainer, kunci enkripsi data harus dibuat di database induk.

Membuat kunci enkripsi data baru dilakukan dengan memanggil metode CreateClientEncryptionKeyAsync dan meneruskan:

  • 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 di mana:
    • type menentukan jenis penyelesai kunci (misalnya, Azure Key Vault).
    • name dapat berupa nama ramah apa pun yang Anda inginkan.
    • value harus menjadi pengidentifikasi kunci.

    Penting

    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 menghilangkan versi kunci yang ada di akhir pengidentifikasi kunci, versi kunci terbaru akan digunakan.

    • algorithm menentukan algoritma mana yang akan digunakan untuk membungkus kunci enkripsi kunci dengan kunci yang dikelola pelanggan.
var database = client.GetDatabase("my-database");
await database.CreateClientEncryptionKeyAsync(
    "my-key",
    DataEncryptionAlgorithm.AeadAes256CbcHmacSha256,
    new EncryptionKeyWrapMetadata(
        KeyEncryptionKeyResolverName.AzureKeyVault,
        "akvKey",
        "https://<my-key-vault>.vault.azure.net/keys/<key>/<version>",
        EncryptionAlgorithm.RsaOaep.ToString()));

Membuat kontainer dengan kebijakan enkripsi

Tentukan kebijakan enkripsi tingkat kontainer saat membuat kontainer.

var path1 = new ClientEncryptionIncludedPath
{
    Path = "/property1",
    ClientEncryptionKeyId = "my-key",
    EncryptionType = EncryptionType.Deterministic.ToString(),
    EncryptionAlgorithm = DataEncryptionAlgorithm.AeadAes256CbcHmacSha256
};
var path2 = new ClientEncryptionIncludedPath
{
    Path = "/property2",
    ClientEncryptionKeyId = "my-key",
    EncryptionType = EncryptionType.Randomized.ToString(),
    EncryptionAlgorithm = DataEncryptionAlgorithm.AeadAes256CbcHmacSha256
};
await database.DefineContainer("my-container", "/partition-key")
    .WithClientEncryptionPolicy()
    .WithIncludedPath(path1)
    .WithIncludedPath(path2)
    .Attach()
    .CreateAsync();

Membaca dan menulis data terenkripsi

Cara data dienkripsi

Setiap kali dokumen ditulis ke Azure Cosmos DB, SDK melihat kebijakan enkripsi untuk mencari tahu properti mana yang perlu dienkripsi, dan bagaimana. Hasil enkripsi adalah string dasar 64.

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 sub-properti menengah tetap dalam bentuk teks biasa.

Membaca item terenkripsi

Tidak diperlukan tindakan eksplisit untuk mendekripsi properti terenkripsi saat mengeluarkan pembacaan titik (mengambil satu item dengan ID dan kunci partisi), kueri, atau membaca umpan perubahan. Hal ini terjadi karena:

  • SDK melihat kebijakan enkripsi untuk mencari tahu properti mana yang perlu didekripsi.
  • Hasil enkripsi menyematkan jenis nilai JSON asli.

Perhatikan bahwa resolusi properti terenkripsi dan dekripsi berikutnya hanya didasarkan pada hasil yang dikembalikan dari permintaan Anda. Misalnya, jika property1 dienkripsi tetapi diproyeksikan ke property2 (SELECT property1 AS property2 FROM c), properti tidak akan diidentifikasi sebagai properti terenkripsi saat diterima oleh SDK.

Memfilter kueri pada properti terenkripsi

Saat menulis kueri yang memfilter pada properti terenkripsi, metode tertentu harus digunakan untuk meneruskan nilai parameter kueri. Metode ini membutuhkan argumen berikut:

  • Nama parameter kueri.
  • Nilai yang akan digunakan dalam kueri.
  • Jalur properti terenkripsi (sebagaimana didefinisikan dalam kebijakan enkripsi).

Penting

Properti terenkripsi hanya dapat digunakan dalam filter kesetaraan (WHERE c.property = @Value). Penggunaan lainnya akan mengembalikan hasil kueri yang tidak dapat diprediksi dan salah. Kendala ini akan lebih baik diterapkan pada SDK versi berikutnya.

var queryDefinition = container.CreateQueryDefinition(
    "SELECT * FROM c where c.property1 = @Property1");
await queryDefinition.AddParameterAsync(
    "@Property1",
    1234,
    "/property1");

Membaca dokumen hanya saat sekumpulan properti dapat didekripsi

Dalam situasi saat klien tidak memiliki akses ke semua CMK yang digunakan untuk mengenkripsi properti, hanya subkumpulan properti dapat didekripsi saat data dibaca kembali. Misalnya, jika property1 dienkripsi dengan key1 dan property2 dienkripsi dengan key2, aplikasi klien yang hanya memiliki akses ke key1 masih dapat membaca data, tetapi property2 tidak. Dalam kasus seperti itu, Anda harus membaca data melalui kueri SQL dan memproyeksikan properti yang tidak dapat didekripsi klien: SELECT c.property1, c.property3 FROM c.

Rotasi CMK

Anda mungkin ingin "memutar" CMK Anda (yaitu, menggunakan CMK baru dan bukan CMK saat ini) jika Anda menduga bahwa CMK saat ini telah disusupi. Ini juga merupakan praktik keamanan umum untuk memutar CMK secara teratur. Untuk melakukan rotasi ini, Anda hanya perlu memberikan pengidentifikasi kunci CMK baru yang harus digunakan untuk membungkus DEK tertentu. Perhatikan bahwa operasi ini tidak memengaruhi enkripsi data Anda, tetapi akan memengaruhi perlindungan DEK. Akses ke CMK sebelumnya tidak boleh dicabut sampai rotasi selesai.

await database.RewrapClientEncryptionKeyAsync(
    "my-key",
    new EncryptionKeyWrapMetadata(
        KeyEncryptionKeyResolverName.AzureKeyVault,
        "akvKey",
        "https://<my-key-vault>.vault.azure.net/keys/<new-key>/<version>",
        EncryptionAlgorithm.RsaOaep.ToString()));

Rotasi DEK

Melakukan rotasi kunci enkripsi data tidak ditawarkan sebagai kemampuan turnkey. Hal ini karena memperbarui DEK memerlukan pemindaian semua kontainer tempat kunci ini digunakan dan enkripsi ulang semua properti yang dienkripsi dengan kunci ini. Operasi ini hanya dapat terjadi di sisi klien karena layanan Azure Cosmos DB tidak menyimpan atau mengakses nilai teks biasa DEK.

Dalam praktiknya, rotasi DEK dapat dilakukan dengan melakukan migrasi data dari kontainer yang terkena dampak ke kontainer baru. Kontainer baru dapat dibuat dengan cara yang sama persis seperti yang asli. Untuk membantu Anda dengan migrasi data seperti itu, Anda dapat menemukan alat migrasi mandiri di GitHub.

Menambahkan properti terenkripsi tambahan

Menambahkan properti terenkripsi tambahan ke kebijakan enkripsi yang ada tidak didukung karena alasan yang sama seperti yang dijelaskan di bagian di atas. Operasi ini memerlukan pemindaian penuh kontainer untuk memastikan bahwa semua instans properti dienkripsi dengan benar, dan ini adalah operasi yang hanya dapat terjadi di sisi klien. Sama seperti rotasi DEK, menambahkan properti terenkripsi tambahan dapat dilakukan dengan melakukan migrasi data ke kontainer baru dengan kebijakan enkripsi yang sesuai.

Jika Anda memiliki fleksibilitas dalam cara properti terenkripsi baru dapat ditambahkan dari sudut pandang skema, Anda juga dapat memanfaatkan sifat skema-agnostik Azure Cosmos DB. Jika menggunakan properti yang ditentukan dalam kebijakan enkripsi Anda sebagai "tas properti", Anda dapat menambahkan lebih banyak properti di bawah ini tanpa batasan. Misalnya, bayangkan bahwa property1 ditentukan dalam kebijakan enkripsi Anda dan pada awalnya Anda menulis property1.property2 di dokumen Anda. Jika, pada tahap selanjutnya, Anda perlu menambahkan property3 sebagai properti terenkripsi, Anda dapat mulai menulis property1.property3 di dokumen dan properti baru juga akan otomatis dienkripsi. Pendekatan ini tidak memerlukan migrasi data apa pun.

Langkah berikutnya