Untuk mengintegrasikan aplikasi Java Anda tanpa perubahan kode, gunakan driver JDBC terenkripsi (EncJDBC) khusus yang disediakan bersama PolarDB Selalu-rahasia. EncJDBC secara otomatis mendekripsi ciphertext dan mengembalikan data teks biasa. Proses ini transparan bagi aplikasi Anda, sehingga Anda dapat terhubung ke PolarDB Selalu-rahasia hanya dengan beberapa perubahan konfigurasi.
Arsitektur solusi
PolarDB Selalu-rahasia adalah solusi enkripsi dan dekripsi Enkripsi on-the-fly berbasis database proxy. Proxy ini mengenkripsi bidang sensitif yang telah dikonfigurasi sebelumnya saat mengembalikan result set kueri ke client. Aplikasi client harus menggunakan driver EncJDBC khusus untuk mendekripsi data yang diterima secara transparan.
Alur Kerja dan Izin Peran:
-
Kueri: Aplikasi client mengirimkan query SQL standar ke PolarDB cluster endpoint melalui driver EncJDBC.
-
Pemrosesan proxy: database proxy menerima permintaan dan meneruskannya ke kernel database backend untuk dieksekusi.
-
Enkripsi on-the-fly: Saat mengembalikan hasil kueri, lapisan proxy memeriksa apakah hasil tersebut sesuai dengan kebijakan enkripsi yang telah ditentukan. Jika cocok, proxy mengenkripsi bidang sensitif dalam result set menggunakan key yang Anda tentukan dari Key Management Service (KMS) atau self-managed key.
-
Pengembalian data: result set yang telah dienkripsi dikembalikan ke client.
-
Dekripsi transparan: Driver EncJDBC pada client 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 dipengaruhi oleh kebijakan enkripsi. Hal ini berguna untuk manajemen dan audit database.
-
Pengguna biasa: Hasil kueri dikembalikan sebagai ciphertext. Anda harus menggunakan driver EncJDBC dan key yang benar untuk mendekripsi data di sisi client.
-
Pengguna lain: Hasil kueri dikembalikan sebagai ciphertext dan tidak dapat didekripsi.
Batasan
Sebelum melanjutkan, tinjau batasan utama berikut untuk menentukan apakah solusi ini memenuhi kebutuhan bisnis dan teknis Anda.
-
Persyaratan titik akhir: Aturan enkripsi hanya berlaku saat Anda terhubung ke cluster endpoint atau custom endpoint. Menghubungkan langsung ke primary endpoint melewati proxy, sehingga menonaktifkan fitur enkripsi.
-
Manajemen kunci: Saat menggunakan self-managed key, rotasi key tidak didukung, dan Anda berisiko kehilangan atau kebocoran key. Jika key hilang, Anda tidak dapat mendekripsi data terenkripsi yang sesuai. Anda harus menerapkan prosedur keamanan ketat untuk mengelola key.
-
Versi JDK: Anda harus menggunakan JDK version 1.8 atau lebih baru.
Gunakan kunci dari KMS
Langkah 1: Konfigurasikan izin akses KMS
-
Peroleh Pasangan Kunci Akses: Dapatkan
AccessKey IDdanAccessKey secretdari RAM user. Hal ini memungkinkan aplikasi Anda mengambil master encryption key (MEK) yang dikelola oleh Key Management Service (KMS).-
Jika Anda sudah memiliki RAM user yang sesuai dengan izin untuk mengakses KMS, Anda dapat menggunakan user tersebut.
-
Jika Anda belum memiliki RAM user yang sesuai, buka RAM console. Di panel navigasi kiri, pilih Identity Management > Users. Klik Create User dan ikuti petunjuk di layar untuk membuat user.
-
-
Berikan izin kepada RAM user:
-
Buka RAM console. Di panel navigasi kiri, pilih Permission Management > Policies. Klik Create Policy. Beralih ke tab JSON, salin konten berikut, lalu klik OK. Masukkan nama untuk membuat kebijakan.
{ "Version": "1", "Statement": [ { "Effect": "Allow", "Action": "KMS:Decrypt", "Resource": "*" } ] } -
Kembali ke RAM console. Di panel navigasi kiri, pilih Identity Management > Users. Temukan RAM user target, klik Add Permissions di kolom Actions, dan berikan access policy yang baru dibuat kepada user tersebut. Hal ini memungkinkan PolarDB mendekripsi data secara dinamis.
-
Langkah 2: Instal dependensi
Tambahkan dependensi berikut ke file pom.xml dalam proyek Maven Anda.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>
Saat menambahkan dependensi Maven, ganti nilai version sesuai kebutuhan Anda. Anda dapat menemukan versi terbaru aliyun-cls-jdbc di Repositori Maven.
Langkah 3: Konfigurasikan MEK
Anda dapat mengonfigurasi MEK menggunakan JDBC properties, konfigurasi file, atau konfigurasi URL. Jika Anda menggunakan beberapa metode konfigurasi, prioritasnya adalah sebagai berikut: konfigurasi JDBC properties > konfigurasi file > konfigurasi URL.
-
Dalam metode konfigurasi dan koneksi berikut,
MEKdiproses di sisi client dan dikirimkan ke server secara aman menggunakan envelope encryption. Hal ini memastikanMEKtidak bocor. -
Kami menyarankan agar Anda tidak menyematkan AccessKey pair (
AccessKey IDdanAccessKey secret) secara langsung dalam kode aplikasi Anda. Topik ini menggunakan Variabel lingkungan untuk mengelola AccessKey pair. Untuk informasi lebih lanjut, lihat Konfigurasi variabel lingkungan pada sistem Linux, macOS, dan Windows. -
Jika Anda perlu menggunakan temporary STS access credential untuk memperoleh MEK yang dikelola oleh KMS, Anda dapat menggunakan SDK STS untuk memperoleh STS token temporary. Untuk contoh SDK STS, lihat Ikhtisar SDK STS.
JDBC properties
Saat membuat koneksi JDBC standar, Anda dapat mengatur atribut kustom menggunakan objek Properties.
Contoh
// Siapkan informasi koneksi, seperti hostname, port, nama 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";
// Peroleh 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 temporary STS access credential untuk membaca kunci KMS, Anda juga harus menyediakan STS token yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan titik akhir publik untuk akses internet atau titik akhir VPC 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 untuk database MySQL.
Class.forName("com.aliyun.encdb.mysql.jdbc.EncDriver");
// Dapatkan koneksi database.
Connection connection = DriverManager.getConnection(dbUrl, props);
// ... Lakukan kueri ...
URL
Anda dapat menyematkan parameter KMS key dalam URL koneksi.
Contoh
// Siapkan informasi koneksi, seperti hostname, port, nama 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";
// Peroleh 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 temporary STS access credential untuk membaca kunci KMS, Anda juga harus menyediakan STS token yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan titik akhir publik untuk akses internet atau titik akhir VPC untuk akses dalam VPC.
String kmsEndpoint = "your-kms-endpoint";
// Sematkan parameter kunci KMS dalam URL koneksi.
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 STS token.
// 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);
// 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
Setelah terhubung ke database, Anda dapat melakukan operasi database seperti pada kueri JDBC standar. 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");
// Iterasi 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
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 {
// Ganti informasi koneksi berikut dengan detail instans Anda, seperti hostname, port, nama 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";
// Peroleh 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 temporary STS access credential untuk membaca kunci KMS, Anda juga harus menyediakan STS token yang diperoleh.
// String stsToken= "yourSecurityToken";
// Untuk titik akhir instans KMS, gunakan titik akhir publik untuk akses internet atau titik akhir VPC 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");
// Iterasi set hasil.
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
// Proses bidang 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
master encryption key (MEK) adalah kredensial utama yang mengizinkan client mengakses data terenkripsi. Untuk alasan keamanan, database terenkripsi tidak menyimpan, mengelola, menghasilkan, atau mencadangkan MEK Anda. Anda bertanggung jawab penuh untuk menghasilkan, mengelola secara aman, dan mencadangkannya. Penyimpanan dan pengelolaan MEK sangat penting bagi keamanan database. Kami sangat menyarankan agar Anda mencadangkan MEK Anda.
MEK: Client mengirimkan MEK ke server database melalui protokol enkripsi asimetris yang aman. Hal ini memungkinkan client dan server berbagi key yang sama, sehingga memungkinkan transmisi data aman melalui enkripsi simetris.
Persyaratan nilai: String heksadesimal 16 byte (panjang 32 karakter). Contohnya, 00112233445566778899aabbccddeeff.
Metode umum pembuatan: Anda dapat menggunakan tool pembuatan password atau fungsi acak dalam bahasa pemrograman.
Contoh
-
Pada Linux, gunakan tool OpenSSL bawaan. Jalankan
openssl rand -hex 16untuk menghasilkan key.# Gunakan OpenSSL untuk menghasilkan kunci acak yang aman openssl rand -hex 16 # Contoh output: 11ce9a9489fab7355cf710837cea5d5b -
Pada Windows, instal paket OpenSSL.
Langkah 2: Instal dependensi
Tambahkan dependensi berikut ke file pom.xml dalam proyek Maven Anda.
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-cls-jdbc</artifactId>
<version>1.0.10-1</version>
</dependency>
Saat menambahkan dependensi Maven, ganti nilai version sesuai kebutuhan Anda. Anda dapat menemukan versi terbaru aliyun-cls-jdbc di Repositori Maven.
Langkah 3: Konfigurasikan MEK
Anda dapat mengonfigurasi MEK menggunakan JDBC properties, konfigurasi file, atau konfigurasi URL. Jika Anda menggunakan beberapa metode konfigurasi, prioritasnya adalah sebagai berikut: konfigurasi JDBC properties > konfigurasi file > konfigurasi URL.
Dalam metode konfigurasi dan koneksi berikut, MEK diproses di sisi client dan dikirimkan ke server secara aman menggunakan envelope encryption. Hal ini memastikan MEK tidak bocor.
JDBC properties
Saat membuat koneksi JDBC standar, Anda dapat mengatur atribut kustom menggunakan objek Properties.
Contoh
// Siapkan informasi koneksi, seperti hostname, port, nama 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";
// Kunci enkripsi utama.
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 ...
File
Metode konfigurasi file hanya berlaku untuk mengonfigurasi local key MEK.
Anda dapat mengimpor parameter dari file konfigurasi untuk mengonfigurasi MEK yang diperlukan. Dalam proyek Anda, atur properti encJdbcConfigFile ke path file konfigurasi. Jika Anda tidak menentukan path, sistem akan menggunakan file encjdbc.conf secara default. File konfigurasi harus berisi konten berikut:
MEK=00112233445566778899aabbccddeeff
Contoh
-
Anda dapat menentukan lokasi file konfigurasi dengan salah satu dari dua cara berikut:
-
Letakkan file di direktori
resourcesproyek Anda, seperti struktur berikut:src main java resources encjdbc.conf -
Letakkan file di direktori root proyek Anda, yaitu direktori waktu proses program.
-
-
Setelah mengonfigurasi file, Anda tidak perlu melakukan konfigurasi tambahan dalam program Anda, seperti pada kode berikut:
// Siapkan informasi koneksi, seperti hostname, port, nama 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 ...
URL
Anda dapat menyematkan MEK dan parameter lain dalam URL koneksi.
Contoh
// Siapkan informasi koneksi, seperti hostname, port, nama 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";
// Kunci enkripsi utama.
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
Setelah terhubung ke database, Anda dapat melakukan operasi database seperti pada kueri JDBC standar. 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");
// Iterasi 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
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 {
// Ganti informasi koneksi berikut dengan detail instans Anda, seperti hostname, port, nama 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. Kami menyarankan agar Anda menggunakan 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");
// Iterasi set hasil.
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("username");
String phone = resultSet.getString("phone");
// Proses bidang 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();
}
}
}