Fitur Confidential database menyediakan driver klien khusus, Encrypted Java Database Connectivity (EncJDBC), yang memungkinkan integrasi tanpa hambatan dengan aplikasi Java Anda tanpa perlu memodifikasi kode. EncJDBC secara otomatis mendekripsi ciphertext dan mengembalikan data teks biasa secara transparan bagi aplikasi. Anda hanya perlu beberapa baris konfigurasi untuk menghubungkan aplikasi ke fitur Confidential database, tanpa perubahan pada kode bisnis yang sudah ada.
Arsitektur solusi
Fitur Confidential database merupakan solusi enkripsi dan dekripsi dinamis berbasis Proksi database. Lapisan proksi mengenkripsi field sensitif yang telah dikonfigurasi dalam set hasil kueri sebelum mengembalikannya ke klien. Aplikasi klien harus menggunakan driver EncJDBC khusus untuk mendekripsi data secara transparan saat menerima data tersebut.
Alur kerja dan izin role:
Permintaan kueri: Aplikasi klien mengirim kueri SQL standar ke titik akhir kluster PolarDB melalui driver EncJDBC.
Pemrosesan proksi: Proksi database menerima permintaan dan meneruskannya ke kernel database backend untuk dieksekusi.
Enkripsi on-the-fly: Saat set hasil kueri dikembalikan, lapisan proksi memeriksa apakah hasil tersebut sesuai dengan kebijakan enkripsi yang telah ditentukan. Jika ditemukan kecocokan, field sensitif dalam set hasil dienkripsi menggunakan kunci tertentu dari KMS atau kunci yang dikelola sendiri.
Pengembalian data: Set hasil yang telah dienkripsi dikembalikan ke klien.
Dekripsi transparan: Driver EncJDBC di sisi klien secara otomatis mendekripsi ciphertext. Aplikasi menerima data teks biasa, dan seluruh proses ini transparan bagi kode bisnis Anda.
Hasil kueri bervariasi berdasarkan role akun database:
Super administrator: Hasil kueri selalu dalam bentuk teks biasa dan tidak terpengaruh oleh kebijakan enkripsi. Hal ini berguna untuk manajemen dan audit database.
Pengguna biasa: Hasil kueri dikembalikan sebagai ciphertext. Anda harus menggunakan driver EncJDBC dan kunci yang benar untuk mendekripsi data di sisi klien.
Pengguna lain: Hasil kueri dikembalikan sebagai ciphertext dan tidak dapat didekripsi.
Batasan
Sebelum mengimplementasikan fitur ini, tinjau batasan berikut untuk menilai apakah fitur ini memenuhi kebutuhan arsitektur bisnis dan teknis Anda.
Persyaratan titik akhir: Aturan enkripsi hanya berlaku ketika Anda terhubung menggunakan cluster endpoint atau custom endpoint. Menghubungkan langsung ke primary endpoint melewati proksi, sehingga menonaktifkan fitur enkripsi.
Manajemen kunci: Saat menggunakan kunci yang dikelola sendiri, rotasi kunci tidak didukung. Anda juga berisiko kehilangan atau kebocoran kunci. Jika kunci hilang, data terenkripsi yang sesuai tidak dapat didekripsi. Anda harus menerapkan prosedur keamanan yang ketat untuk mengelola kunci Anda.
Versi JDK: Anda harus menggunakan JDK 1.8 atau yang lebih baru.
Gunakan kunci KMS
Langkah 1: Konfigurasikan izin akses KMS
Dapatkan pasangan AccessKey: Dapatkan
AccessKeyIddanAccessKeySecretdari pengguna RAM. Hal ini memungkinkan aplikasi untuk memperoleh kunci enkripsi utama (MEK) yang dikelola oleh KMS.Jika Anda sudah memiliki pengguna RAM yang sesuai untuk mengakses KMS, Anda dapat menggunakan pengguna tersebut.
Jika belum memiliki pengguna RAM yang sesuai, buka Konsol RAM. Di panel navigasi sebelah kiri, pilih . Klik Create User dan ikuti petunjuk di layar untuk membuat pengguna.
Berikan izin kepada pengguna RAM:
Buka Konsol RAM. Di panel navigasi sebelah kiri, pilih . Klik Create Access Policy. Beralih ke editor skrip, salin konten berikut, lalu klik OK. Masukkan nama kebijakan dan selesaikan pembuatan.
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "KMS:Decrypt", "Resource": "*" } ] }Kembali ke Konsol RAM. Di panel navigasi sebelah kiri, pilih . Temukan pengguna RAM target. Di kolom Actions, klik Add Permissions. Berikan kebijakan akses yang baru dibuat kepada pengguna tersebut. Hal ini memungkinkan PolarDB untuk mendekripsi data secara dinamis.
Langkah 2: Instal dependensi
Tambahkan dependensi berikut ke file pom.xml proyek Maven Anda.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>Saat menambahkan dependensi Maven, gantilah nilai version sesuai kebutuhan. Anda dapat menemukan versi terbaru aliyun-cls-jdbc di situs resmi.
Langkah 3: Konfigurasikan MEK untuk terhubung ke database
Anda dapat mengonfigurasi MEK menggunakan JDBC properties, file, atau URL. Jika Anda mengonfigurasi JDBC menggunakan dua metode atau lebih, prioritasnya adalah sebagai berikut: konfigurasi JDBC properties > konfigurasi file > konfigurasi URL.
Dalam metode konfigurasi dan koneksi berikut,
MEKdiproses secara lokal di klien dan dikirim ke server menggunakan metode aman (enkripsi amplop) untuk memastikan bahwaMEKtidak bocor.Jangan hard-code pasangan AccessKey (
AccessKeyIddanAccessKeySecret) dalam kode bisnis Anda. Contoh ini menggunakan variabel lingkungan sistem untuk mengelola pasangan AccessKey. Untuk informasi selengkapnya, lihat Konfigurasikan variabel lingkungan pada sistem Linux, macOS, dan Windows.Untuk menggunakan kredensial akses temporary guna memperoleh MEK yang dikelola KMS, Anda dapat menggunakan SDK STS untuk memperoleh kredensial temporary, yaitu token Security Token Service (STS). Untuk contoh SDK STS, lihat Ikhtisar SDK STS.
Konfigurasi JDBC properties
Saat koneksi JDBC standar dibuat, Anda dapat mengatur atribut kustom menggunakan objek Properties.
Contoh
// Siapkan informasi koneksi seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Dapatkan AccessKey ID dan AccessKey secret dari variabel lingkungan.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Jika Anda menggunakan kredensial akses STS temporary untuk membaca kunci KMS, Anda juga perlu mengisi token Security Token Service (SecurityToken) yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan public endpoint untuk akses jaringan publik. Gunakan instance VPC endpoint untuk akses dalam VPC.
String kmsEndpoint = "your-kms-endpoint";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_ID", accessKeyId);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET", accessKeySecret);
props.setProperty("ALIBABA_CLOUD_KMS_ENDPOINT", kmsEndpoint);
// props.setProperty("ALIBABA_CLOUD_STS_TOKEN","stsToken");
// Berikut adalah format URL koneksi untuk database MySQL: "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Berikut memuat driver EncJDBC untuk database MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Lakukan kueri ...Konfigurasi URL
Anda dapat menyematkan parameter untuk memperoleh kunci KMS dalam URL.
Contoh
// Siapkan informasi koneksi seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Dapatkan AccessKey ID dan AccessKey secret dari variabel lingkungan.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Jika Anda menggunakan kredensial akses STS temporary untuk membaca kunci KMS, Anda juga perlu mengisi token Security Token Service (SecurityToken) yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan public endpoint untuk akses jaringan publik. Gunakan instance VPC endpoint untuk akses dalam VPC.
String kmsEndpoint = "your-kms-endpoint";
// Berikut adalah format URL koneksi untuk database MySQL.
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint);
// Gunakan token STS.
// String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?ALIBABA_CLOUD_ACCESS_KEY_ID=%s&ALIBABA_CLOUD_ACCESS_KEY_SECRET=%s&ALIBABA_CLOUD_KMS_ENDPOINT=%s&ALIBABA_CLOUD_STS_TOKEN=%s", hostname, port, dbname, accessKeyId, accessKeySecret, kmsEndpoint, stsToken);
// Berikut memuat driver EncJDBC untuk database MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Lakukan kueri ...Langkah 4: Kueri data teks biasa dari kolom terenkripsi
Setelah berhasil terhubung ke database, Anda dapat melakukan operasi database seperti halnya kueri JDBC biasa. EncJDBC secara otomatis mendekripsi kolom terenkripsi dan mengembalikan data teks biasa.
Contoh
// Buat pernyataan kueri.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
// Telusuri set hasil.
while (resultSet.next()) {
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}Lampiran: Contoh kode lengkap
Contoh ini menggunakan Maven versi 3.9.9 dan tool pengembangan IntelliJ IDEA Community Edition 2024.1.2.
import java.sql.*;
import java.util.Properties;
public class EncryptedColumnAccess {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// Perbarui informasi koneksi berikut dengan detail instans Anda, seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Dapatkan AccessKey ID dan AccessKey secret dari variabel lingkungan.
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Jika Anda menggunakan kredensial akses STS temporary untuk membaca kunci KMS, Anda juga perlu mengisi token Security Token Service (SecurityToken) yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan public endpoint untuk akses jaringan publik. Gunakan instance VPC endpoint untuk akses dalam VPC.
String kmsEndpoint = "your-kms-endpoint";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_ID", accessKeyId);
props.setProperty("ALIBABA_CLOUD_ACCESS_KEY_SECRET", accessKeySecret);
props.setProperty("ALIBABA_CLOUD_KMS_ENDPOINT", kmsEndpoint);
// props.setProperty("ALIBABA_CLOUD_STS_TOKEN","stsToken");
// Format URL koneksi untuk database MySQL adalah "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Muat driver EncJDBC.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, props);
// Lakukan kueri.
try {
// Buat pernyataan kueri.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
// Telusuri set hasil.
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
// Proses field lain berdasarkan skema tabel Anda.
System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
}
// Tutup resource.
resultSet.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}Gunakan kunci lokal
Langkah 1: Hasilkan MEK
MEK adalah kredensial root yang digunakan untuk mengotorisasi klien mengakses data terenkripsi. Untuk alasan keamanan, database terenkripsi tidak menyimpan atau mengelola MEK Anda. Fitur ini juga tidak menyediakan layanan pembuatan atau backup MEK. Anda bertanggung jawab untuk menghasilkan MEK. Penyimpanan dan pengelolaan MEK sangat penting bagi keamanan database. Oleh karena itu, kami menyarankan agar Anda melakukan backup MEK secara aman.
MEK: MEK dikirim dari klien ke server database menggunakan protokol enkripsi kunci asimetris yang aman. Hal ini memungkinkan server dan klien berbagi kunci yang sama untuk transmisi data aman melalui enkripsi simetris.
Nilai valid: string heksadesimal 16-byte dengan panjang 32 karakter. Misalnya, 00112233445566778899aabbccddeeff.
Metode pembuatan umum: Anda dapat menggunakan tool pembuatan password atau fungsi acak dalam bahasa pemrograman.
Contoh
Pada Linux, Anda dapat menggunakan tool OpenSSL bawaan. Jalankan
openssl rand -hex 16untuk menghasilkan kunci.# Gunakan OpenSSL untuk menghasilkan kunci acak yang aman openssl rand -hex 16 # Contoh output: 11ce9a9489fab7355cf710837cea5d5bPada Windows, Anda dapat menginstal paket OpenSSL.
Langkah 2: Instal dependensi
Tambahkan dependensi berikut ke file pom.xml proyek Maven Anda.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>Saat menambahkan dependensi Maven, gantilah nilai version sesuai kebutuhan. Anda dapat menemukan versi terbaru aliyun-cls-jdbc di situs resmi.
Langkah 3: Konfigurasikan MEK untuk terhubung ke database
Anda dapat mengonfigurasi MEK menggunakan JDBC properties, file, atau URL. Jika Anda mengonfigurasi JDBC menggunakan dua metode atau lebih, prioritasnya adalah sebagai berikut: konfigurasi JDBC properties > konfigurasi file > konfigurasi URL.
Dalam metode konfigurasi dan koneksi berikut, MEK diproses secara lokal di klien dan dikirim ke server menggunakan metode aman (enkripsi amplop) untuk memastikan bahwa MEK tidak bocor.
Konfigurasi JDBC properties
Saat koneksi JDBC standar dibuat, Anda dapat mengatur atribut kustom menggunakan objek Properties.
Contoh
// Siapkan informasi koneksi seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Customer master key.
String mek = "00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
// Format URL koneksi untuk database MySQL adalah "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Muat driver EncJDBC untuk database MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Lakukan kueri ...Konfigurasi file
Metode konfigurasi file hanya berlaku untuk mengonfigurasi MEK lokal.
Anda dapat mengimpor parameter, seperti MEK yang diperlukan, dari file konfigurasi. Dalam proyek Anda, atur properti bernama encJdbcConfigFile dan atur nilainya ke path file konfigurasi. Jika Anda tidak menentukan path, sistem akan menggunakan file encjdbc.conf secara default. Kode berikut menunjukkan isi file konfigurasi:
MEK=00112233445566778899aabbccddeeffContoh
Anda dapat menentukan lokasi file konfigurasi dengan salah satu dari dua cara berikut:
Letakkan file di direktori resources proyek Anda, seperti yang ditunjukkan pada gambar berikut:

Letakkan file di direktori root proyek, yaitu direktori runtime program.
Setelah mengonfigurasi file, Anda tidak perlu melakukan konfigurasi tambahan dalam program Anda, seperti yang ditunjukkan pada kode berikut:
// Siapkan informasi koneksi seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password. String hostname = "your-hostname"; String port = "your-port"; String dbname = "your-database-name"; String username = "your-username"; String password = "your-password"; // Format URL koneksi untuk database MySQL adalah "jdbc:mysql:encdb://%s:%s/%s". String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname); // Muat driver EncJDBC untuk database MySQL. Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver"); // Dapatkan koneksi database. Connection connection = DriverManager.getConnection(dbUrl, username, password); // ... Lakukan kueri ...
Konfigurasi URL
Anda dapat menyematkan parameter, seperti MEK, dalam URL.
Contoh
// Siapkan informasi koneksi seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Customer master key.
String mek = "00112233445566778899aabbccddeeff";
// Format URL koneksi untuk database MySQL adalah "jdbc:mysql:encdb://%s:%s/%s?MEK=%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s?MEK=%s", hostname, port, dbname, mek);
// Muat driver EncJDBC untuk database MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, username, password);
// ... Lakukan kueri ...Langkah 4: Kueri data teks biasa dari kolom terenkripsi
Setelah berhasil terhubung ke database, Anda dapat melakukan operasi database seperti halnya kueri JDBC biasa. EncJDBC secara otomatis mendekripsi kolom terenkripsi dan mengembalikan data teks biasa.
Contoh
// Buat pernyataan kueri.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM your_table_name");
// Telusuri set hasil.
while (resultSet.next()) {
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i + 1));
System.out.print("\t");
}
System.out.print("\n");
}Lampiran: Contoh kode lengkap
Contoh ini menggunakan Maven versi 3.9.9 dan tool pengembangan IntelliJ IDEA Community Edition 2024.1.2.
import java.sql.*;
import java.util.Properties;
public class EncryptedColumnAccess {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// Perbarui informasi koneksi berikut dengan detail instans Anda, seperti titik akhir (hostname), port, nama instans database (dbname), username, dan password.
String hostname = "your-hostname";
String port = "your-port";
String dbname = "your-database-name";
String username = "your-username";
String password = "your-password";
// Ini hanya contoh. Gunakan kunci yang lebih kompleks.
String mek="00112233445566778899aabbccddeeff";
Properties props = new Properties();
props.setProperty("user", username);
props.setProperty("password", password);
props.setProperty("MEK", mek);
// Format URL koneksi untuk database MySQL adalah "jdbc:mysql:encdb://%s:%s/%s".
String dbUrl = String.format("jdbc:mysql:encdb://%s:%s/%s", hostname, port, dbname);
// Muat driver EncJDBC.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, props);
// Lakukan kueri.
try {
// Buat pernyataan kueri.
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("SELECT * FROM users");
// Telusuri set hasil.
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
// Proses field lain berdasarkan skema tabel Anda.
System.out.println("ID: " + id + ", Name: " + name + ", Phone: " + phone);
}
// Tutup resource.
resultSet.close();
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}