Cài đặt và kích hoạt extension pgcrypto trong PostgreSQL
Bước đầu tiên là đảm bảo gói mở rộng pgcrypto đã được cài đặt và sẵn sàng để PostgreSQL sử dụng. Extension này cung cấp các hàm mã hóa và giải mã tiêu chuẩn để bảo vệ dữ liệu ở cấp độ ứng dụng hoặc dữ liệu thô.
Tại sao: Mặc dù TDE thường đề cập đến mã hóa ở cấp độ file, nhưng trong PostgreSQL, pgcrypto là công cụ nền tảng để mã hóa các cột dữ liệu nhạy cảm trước khi lưu trữ, tạo thành một lớp bảo vệ bổ sung cho TDE ở cấp độ OS.
Kết quả mong đợi: Extension pgcrypto xuất hiện trong danh sách các extension đã tạo và có thể gọi các hàm như pgp_sym_encrypt.
Thực hiện lệnh sau để cài đặt gói pgcrypto nếu chưa có (trên Ubuntu/Debian):
sudo apt-get install -y postgresql-contrib-15
Chạy lệnh này để vào shell của PostgreSQL với quyền superuser:
sudo -u postgres psql
Tạo extension pgcrypto trong database mục tiêu (ví dụ: my_secure_db). Thay thế 'my_secure_db' bằng tên database thực tế của bạn:
CREATE EXTENSION IF NOT EXISTS pgcrypto;
Verify kết quả bằng cách liệt kê các extension đang hoạt động:
\dx
Bạn sẽ thấy dòng output có tên 'pgcrypto' trong cột Name. Nếu không thấy, extension chưa được kích hoạt thành công.
Tạo và quản lý key encryption (KEK) an toàn trên hệ thống file
Sau khi kích hoạt extension, bạn cần tạo một Key Encryption Key (KEK) để sử dụng cho việc mã hóa dữ liệu. Trong PostgreSQL, key này thường được lưu dưới dạng một file mã hóa hoặc trong biến môi trường an toàn, nhưng để minh họa quy trình TDE, chúng ta sẽ tạo một file key riêng biệt được bảo vệ bởi quyền truy cập hệ thống.
Tại sao: Việc lưu key trên hệ thống file với quyền truy cập chặt chẽ (chmod 600) đảm bảo chỉ có user postgres mới có thể đọc key, ngăn chặn các user khác hoặc attacker đọc được key mã hóa.
Kết quả mong đợi: Một file key được tạo tại đường chỉ định với nội dung là chuỗi hex hoặc binary, và quyền truy cập chỉ dành cho owner.
Đầu tiên, tạo thư mục riêng để chứa key, đảm bảo nó nằm ngoài thư mục dữ liệu mặc định của PostgreSQL để tránh bị sao lưu tự động không an toàn:
sudo mkdir -p /opt/pgcrypto_keys
sudo chown postgres:postgres /opt/pgcrypto_keys
sudo chmod 700 /opt/pgcrypto_keys
Chuyển sang user postgres để tạo key an toàn:
sudo -u postgres bash
Sử dụng công cụ openssl để tạo một file key 256-bit AES (Advanced Encryption Standard) dưới dạng hex:
openssl rand -hex 32 > /opt/pgcrypto_keys/master_key.hex
Đặt quyền truy cập chặt chẽ cho file key, chỉ cho phép owner đọc và ghi:
chmod 600 /opt/pgcrypto_keys/master_key.hex
Verify kết quả bằng cách kiểm tra quyền và nội dung file (nội dung sẽ là chuỗi hex dài 64 ký tự):
ls -l /opt/pgcrypto_keys/master_key.hex
cat /opt/pgcrypto_keys/master_key.hex
Bạn sẽ thấy quyền là '-rw-------' và owner là postgres. Nội dung file là chuỗi hex ngẫu nhiên.
Áp dụng chính sách mã hóa cho các table cụ thể hoặc toàn bộ database
Bây giờ bạn đã có extension và key, bước tiếp theo là áp dụng mã hóa vào dữ liệu thực tế. Chúng ta sẽ tạo một table mẫu với các cột được mã hóa sử dụng hàm pgp_sym_encrypt với key đã tạo ở trên.
Tại sao: Việc mã hóa ở cấp độ cột (Column-Level Encryption) cho phép bạn bảo vệ dữ liệu nhạy cảm (như SSN, số thẻ tín dụng, mật khẩu hash) ngay cả khi file database bị đánh cắp, vì attacker không có key để giải mã các cột đó.
Kết quả mong đợi: Một table được tạo với các cột chứa dữ liệu mã hóa, và khi truy vấn dữ liệu gốc, bạn phải dùng hàm pgp_sym_decrypt để xem nội dung.
Vào lại shell PostgreSQL (nếu chưa vào):
sudo -u postgres psql -d my_secure_db
Tạo một table mới 'user_sensitive_data' với các cột mã hóa. Lưu ý: Cột 'encrypted_ssn' sẽ lưu dữ liệu đã mã hóa dưới dạng bytea.
CREATE TABLE user_sensitive_data (
id SERIAL PRIMARY KEY,
username TEXT NOT NULL,
encrypted_ssn BYTEA,
encrypted_notes TEXT
);
Chèn dữ liệu vào table. Ở đây, chúng ta đọc key từ file và dùng để mã hóa dữ liệu SSN và ghi chú. Thay thế '123-45-6789' bằng dữ liệu thực tế cần mã hóa:
INSERT INTO user_sensitive_data (username, encrypted_ssn, encrypted_notes)
VALUES ('john_doe',
pgp_sym_encrypt('123-45-6789', (SELECT pg_read_file('/opt/pgcrypto_keys/master_key.hex'))),
pgp_sym_encrypt('This is a highly confidential note.', (SELECT pg_read_file('/opt/pgcrypto_keys/master_key.hex'))));
Verify kết quả bằng cách truy vấn dữ liệu thô (sẽ thấy chuỗi mã hóa) và dữ liệu đã giải mã (sẽ thấy nội dung gốc):
SELECT id, username, encrypted_ssn, pgp_sym_decrypt(encrypted_ssn, (SELECT pg_read_file('/opt/pgcrypto_keys/master_key.hex'))) AS decrypted_ssn
FROM user_sensitive_data;
Bạn sẽ thấy cột 'encrypted_ssn' chứa chuỗi bytea ngẫu nhiên, nhưng cột 'decrypted_ssn' hiển thị chính xác '123-45-6789'. Điều này xác nhận quy trình mã hóa và giải mã hoạt động chính xác với key đã quản lý.
Để áp dụng cho toàn bộ database, bạn cần viết script để lặp qua tất cả các table và cột nhạy cảm, thực hiện lệnh INSERT/UPDATE tương tự như trên. Tuy nhiên, trong môi trường production, bạn nên sử dụng Stored Procedures hoặc Trigger để tự động hóa việc mã hóa khi dữ liệu được chèn hoặc cập nhật.
Tạo một trigger function để tự động mã hóa cột SSN khi có dữ liệu mới:
CREATE OR REPLACE FUNCTION auto_encrypt_ssn()
RETURNS TRIGGER AS $$
BEGIN
NEW.encrypted_ssn := pgp_sym_encrypt(NEW.ssn, (SELECT pg_read_file('/opt/pgcrypto_keys/master_key.hex')));
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Thêm cột 'ssn' (dữ liệu gốc) vào table và tạo trigger:
ALTER TABLE user_sensitive_data ADD COLUMN ssn TEXT;
CREATE TRIGGER trigger_encrypt_ssn
BEFORE INSERT OR UPDATE ON user_sensitive_data
FOR EACH ROW EXECUTE FUNCTION auto_encrypt_ssn();
Verify kết quả bằng cách chèn dữ liệu vào cột 'ssn' (không mã hóa thủ công) và kiểm tra cột 'encrypted_ssn':
INSERT INTO user_sensitive_data (username, ssn) VALUES ('jane_doe', '987-65-4321');
SELECT username, ssn, encrypted_ssn FROM user_sensitive_data WHERE username = 'jane_doe';
Kết quả sẽ hiển thị 'ssn' là '987-65-4321' và 'encrypted_ssn' đã được tự động điền bằng dữ liệu mã hóa tương ứng, xác nhận trigger hoạt động đúng chính sách mã hóa.
Điều hướng series:
Mục lục: Series: Triển khai Database an toàn với Transparent Data Encryption và Audit trên Linux
« Phần 2: Cấu hình cơ bản cho Audit trên Linux
Phần 4: Tích hợp Audit và TDE vào quy trình vận hành »