PostgreSQL Dynamic Data Masking: Đừng để lộ dữ liệu khách hàng khi làm Dev/Test

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Bối cảnh: Cơn ác mộng mang tên “Lộ data khách hàng”

Làm nghề quản trị dữ liệu, chắc hẳn bạn đã từng rơi vào tình huống khóc dở mếu dở: Team Dev cần data thật từ Production để fix một bug logic “khó nhằn”, hoặc team Test cần dữ liệu đa dạng để chạy automation. Ngặt nỗi, database lại chứa toàn thông tin nhạy cảm như số điện thoại, email hay số dư tài khoản.

Bê nguyên cục data đó về máy cá nhân hay môi trường Staging là bạn đang đánh cược với rủi ro bảo mật. Chỉ cần một laptop của developer bị mất hoặc một bản backup vô tình nằm trên cloud không bảo mật, toàn bộ thông tin khách hàng sẽ bị rao bán ngay lập tức.

Tôi từng làm một dự án Fintech với database hơn 500GB. Mỗi lần đồng bộ dữ liệu về Lab, team phải mất cả buổi sáng viết script UPDATE để ghi đè dữ liệu giả. Cách làm thủ công này khiến transaction log tăng vọt, làm database phình to thêm vài chục GB và tốn hàng giờ chờ đợi script chạy xong trên những bảng hàng chục triệu record.

Dynamic Data Masking (DDM) là cứu cánh cho bài toán này. Thay vì sửa đổi dữ liệu vật lý, DDM đóng vai trò như một “lớp kính lọc”. Dữ liệu thật vẫn nằm yên dưới đĩa cứng, nhưng tùy vào quyền hạn, người dùng sẽ chỉ thấy những chuỗi ký tự đã được che mờ hoặc làm giả hoàn toàn.

Cài đặt postgresql_anonymizer

PostgreSQL không hỗ trợ sẵn tính năng này như SQL Server Enterprise. Tuy nhiên, extension postgresql_anonymizer (thường gọi tắt là anon) đã trở thành tiêu chuẩn vàng để xử lý masking hiện nay.

1. Triển khai nhanh với Docker

Cách “mì ăn liền” nhất để thử nghiệm là dùng Docker Image chính thức đã tích hợp sẵn extension:

docker run -d --name pg_anon -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 registry.gitlab.com/dalibo/postgresql_anonymizer

2. Cài đặt trên server Linux

Nếu đang chạy Ubuntu hoặc Debian, bạn hãy cài đặt trực tiếp từ PGDG repository:

# Cài đặt extension cho Postgres 15
sudo apt-get install postgresql-15-anonymizer

Tiếp theo, bạn cần cấu hình để Postgres tự động nạp extension này mỗi khi khởi động bằng cách sửa file postgresql.conf:

shared_preload_libraries = 'anon'

Sau khi restart Postgres, hãy kích hoạt công cụ này trong database của bạn:

CREATE EXTENSION anon CASCADE;
SELECT anon.init();

Cấu hình Masking: Dán nhãn để ẩn dữ liệu

Cơ chế của anon rất trực quan: Bạn dán nhãn (Security Label) lên cột nào, cột đó sẽ bị ẩn đi theo quy tắc bạn chọn.

Bước 1: Thiết lập User cho team Dev

Đầu tiên, hãy tạo một user riêng cho môi trường Test. User này sẽ bị giới hạn quyền nhìn thấy data thật.

CREATE ROLE dev_user LOGIN PASSWORD 'password123';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO dev_user;

Bước 2: Áp dụng quy tắc Masking

Giả sử bảng customers cần bảo mật. Chúng ta sẽ áp dụng 3 kỹ thuật phổ biến nhất:

  1. Partial Masking: Chỉ để lộ vài ký tự đầu của email để vẫn định danh được nhưng không lấy được địa chỉ thật.
  2. Faking: Thay tên thật bằng tên ngẫu nhiên (ví dụ: “Nguyễn Văn A” thành “John Doe”).
  3. Destructive Masking: Chèn ký tự lạ vào giữa số điện thoại.
-- Che email, giữ lại 2 ký tự đầu và 2 ký tự cuối
SECURITY LABEL FOR anon ON COLUMN customers.email
IS 'MASKED WITH FUNCTION anon.partial(email,2,$$******$$,2)';

-- Thay tên bằng dữ liệu giả ngẫu nhiên
SECURITY LABEL FOR anon ON COLUMN customers.full_name
IS 'MASKED WITH FUNCTION anon.fake_first_name()';

-- Làm mờ số điện thoại
SECURITY LABEL FOR anon ON COLUMN customers.phone
IS 'MASKED WITH FUNCTION anon.partial(phone,3,$$****$$,2)';

Bước 3: Kích hoạt chế độ ẩn danh

Cuối cùng, bạn cần ra lệnh cho Postgres áp dụng luật masking lên đúng user dev_user:

SELECT anon.start_masking();
SECURITY LABEL FOR anon ON ROLE dev_user IS 'MASKED';

Kiểm chứng kết quả thực tế

Hãy so sánh sự khác biệt khi truy vấn cùng một dòng dữ liệu bằng hai tài khoản khác nhau.

Admin (Nhìn thấy toàn bộ):

-- Kết quả: "Trần Văn B", "[email protected]", "0912345678"

Dev_user (Dữ liệu đã bị xáo trộn):

SET ROLE dev_user;
SELECT full_name, email, phone FROM customers LIMIT 1;
-- Kết quả: "Robert", "tr******om", "091****78"

Cách đây vài tháng, tôi áp dụng phương pháp này cho một hệ thống ERP. Thay vì tốn 1 ngày ròng rã chạy script xáo trộn dữ liệu (obfuscation), tôi chỉ mất đúng 15 phút cấu hình rule. Dù hiệu năng truy vấn của user bị mask giảm khoảng 5-10% do tốn CPU xử lý hàm ẩn danh, nhưng đổi lại là sự an tâm tuyệt đối.

Vài lưu ý “xương máu” khi vận hành:

  • Vấn đề Performance: Masking diễn ra ngay lúc bạn SELECT. Nếu bạn query hàng triệu dòng mà không có WHERE hoặc LIMIT, CPU server sẽ tăng vọt để xử lý các hàm fake_*.
  • Ràng buộc UNIQUE: Hãy cẩn thận khi mask các cột có index Unique. Nếu hàm fake vô tình sinh ra hai giá trị trùng nhau, các câu lệnh Join có thể trả về kết quả sai lệch so với logic nghiệp vụ.
  • Tính năng Backup an toàn: Khi dùng pg_dump với user bị masked, bản dump thu được sẽ chỉ chứa dữ liệu giả. Đây là cách tuyệt vời để gửi database cho các đối tác outsource mà không lo lộ bí mật kinh doanh.

Bảo mật dữ liệu không nhất thiết phải là rào cản làm chậm tiến độ công việc. Với Dynamic Data Masking, team Dev vẫn có dữ liệu chất lượng để làm việc, còn bạn thì có thể kê cao gối ngủ ngon mỗi đêm.

Share: