Trung hòa, thu nhỏ, ẩn danh hóa và làm mờ là bốn thao tác khác nhau trên một bản sao database Odoo. Mỗi thao tác trả lời câu hỏi gì, và khi nào dùng cái nào.

Mỗi lần khôi phục một database production lên máy của lập trình viên, lên máy chủ staging hay lên một CI runner đều là một vụ rò rỉ dữ liệu đang chờ xảy ra. Email khách hàng thật, lương, tài khoản ngân hàng và thông tin đăng nhập API đang hoạt động rơi vào những nơi chưa bao giờ được dự tính để chứa chúng. Những cron vốn đang ngủ yên trên production thì thức dậy trên bản sao và bắt đầu gửi email cho người thật.

Cách sửa không nằm ở một công cụ duy nhất. Đó là bốn thao tác khác nhau mà người ta vẫn thường xuyên lẫn lộn: trung hòa, thu nhỏ, ẩn danh hóa và làm mờ. Chúng có phần chồng lấn, thường được chạy cùng nhau, nhưng trả lời những câu hỏi khác nhau. Bài này định nghĩa từng thao tác và đưa ra một quy tắc để biết khi nào dùng cái nào.

Đây là phần 1 của một loạt ba bài. Phần 2 điểm qua các công cụ bên ngoài (module cộng đồng và extension của PostgreSQL). Phần 3 đi qua cách Trobz xử lý chuyện này.


Bốn thao tác nhìn trong một bảng

Thao tácCâu hỏi nó trả lờiTình huống điển hình
Trung hòa“Bản sao này có nói chuyện ra thế giới bên ngoài không, và nó có trỏ đúng môi trường không?”Mọi lần khôi phục không phải production
Thu nhỏ“Bản sao này đã đủ nhẹ để làm việc chưa?”Database production lớn, dùng ở máy cá nhân hoặc CI
Ẩn danh hóa“Từ bản sao này có truy ngược ra một con người cụ thể không?”Bản sao ra khỏi vòng tin cậy (debug, kiểm thử tự động, demo)
Làm mờ“Có thể che giá trị bây giờ rồi khôi phục lại sau không?”Bản sao phải quay về với giá trị thật

Ba thao tác đầu xếp theo thứ tự dữ liệu đi xa tới đâu. Một bản sao nằm yên trên một máy chủ staging tin cậy thì cần trung hòa. Một bản sao đi vào kiểm thử tự động hoặc lên một máy tính không được quản lý thì cần cả ba. Làm mờ nằm ngoài thứ tự đó: nó che giá trị theo kiểu đảo ngược được.


Trung hòa

Trung hòa ngăn một bản sao database tương tác với thế giới bên ngoài: không gửi thư đi, không thu tiền thanh toán, không gọi ra API bên ngoài, không có tác vụ theo lịch nào bắn vào hệ thống đang chạy thật. Nó cũng lo nốt nửa còn lại của cùng công việc đó, là điều chỉnh bản sao cho hợp với môi trường nó vừa chuyển tới, để những gì nó còn với tới được đều thuộc về môi trường đó chứ không phải production.

Trung hòa có hai nửa. Nửa do module điều khiển đã là một lệnh chính thức từ Odoo 16.0:

odoo neutralize

Cơ chế là SQL thuần, không phải Python. odoo neutralize đọc danh sách module đã cài từ ir_module_module, và với mỗi module có kèm một file data/neutralize.sql thì chạy file đó. Không có phương thức _neutralize() nào để ghi đè; một module tham gia đơn giản bằng cách thêm file đó vào. Trên các module hiện có kèm file này, phạm vi bao gồm:

  • Thư gửi đi (base: vô hiệu hóa ir_mail_server, chèn vào một máy chủ giả để dự phòng)
  • Cron / tác vụ theo lịch (base: vô hiệu hóa các bản ghi ir.cron, trừ tác vụ autovacuum)
  • Đồng bộ ngân hàng
  • Nhà cung cấp thanh toán (theo từng module thanh toán: xóa sạch thông tin đăng nhập của nhà cung cấp)
  • Tích hợp giao vận (delivery: tắt môi trường prod và các hãng vận chuyển bên ngoài)
  • Tiêu thụ IAP (iap: vô hiệu hóa các token iap_account)
  • Lập chỉ mục và hiển thị của website (website: xóa domain, tắt CDN, đặt robots.txt chặn mọi bot)

Vì phần SQL nằm ngay cạnh module mà nó bảo vệ, trung hòa là chỗ đúng đắn cho phần an toàn riêng của từng module. Nếu bạn viết một module mà, chẳng hạn, đồng bộ một token xác thực giữa website và backend Odoo theo từng công ty, module đó nên kèm một data/neutralize.sql xóa hoặc làm giả token. Người viết tích hợp biết rõ chỗ nào nguy hiểm; kiến thức đó thuộc về module, không thuộc về một script riêng mà ai đó phải nhớ cập nhật.

Trung hòa tự động trên Odoo.sh

Odoo.sh tự chạy trung hòa cho bạn trong hai tình huống:

  1. Khi một bản dump production được khôi phục lên một nhánh staging.

  2. Theo mặc định, khi một bản dump database được tải về qua giao diện Odoo.sh.

    Hộp thoại tải bản dump của Odoo.sh, với tùy chọn trung hòa database được bật sẵn

Nửa phụ thuộc môi trường

odoo neutralize chạy ở đâu cũng giống nhau. Nửa còn lại phụ thuộc vào nơi bản sao vừa đặt chân tới: nó chỉnh database sao cho chạy đúng trong môi trường mới, trỏ vào cấu hình của chính môi trường đó thay vì của production.

Các bước điển hình:

  • Cập nhật web.base.url và report.url sang tên miền của môi trường mới.
  • Đặt lại mật khẩu admin về một giá trị đã biết.
  • Trỏ catchall/alias domain của thư sang một tên miền dùng để thử nghiệm.
  • Đổi các endpoint kết nối ra ngoài (CRM, thương mại điện tử, công cụ marketing) sang thông tin đăng nhập của chính môi trường đó.

Nhu cầu này rất cụ thể. Giả sử một dự án CRM kết nối tới một dịch vụ quản trị bên ngoài qua API, và mỗi môi trường lẽ ra phải dùng thông tin đăng nhập riêng. Khôi phục production lên staging mà bỏ qua bước này, thì staging giờ đây xác thực với dịch vụ bên ngoài đó dưới danh nghĩa production.

Quy tắc: Trung hòa là không thể thương lượng trên mọi database không phải production. Đó là sàn, không phải trần.

Điều trung hòa không làm: nó không gỡ bỏ dữ liệu cá nhân. Đó là việc của hai thao tác tiếp theo.


Thu nhỏ

Thu nhỏ (còn gọi là minify) xóa bớt các bản ghi mà môi trường đích không cần, để bản sao nhẹ hơn và làm việc nhanh hơn. Một database production nặng vài gigabyte rất khổ khi phải khôi phục đi khôi phục lại trên máy cá nhân hay trong CI; cắt bớt nhiều năm giao dịch lịch sử, file đính kèm cũ hoặc các bảng log rời rạc có thể giảm được cả một bậc độ lớn.

Thu nhỏ là thao tác duy nhất hoàn toàn thuộc về sự tiện dụng, không thuộc về an toàn. Bỏ qua nó thì bạn vẫn có một bản sao đúng và an toàn — chỉ là chậm và nặng. Vì xóa bản ghi nghĩa là phải lách qua các khóa ngoại và ràng buộc toàn vẹn tham chiếu của Odoo, đây cũng là thao tác khó làm cho đúng nhất, và đó là lý do nó chỉ dành cho những trường hợp mà kích thước thật sự gây đau.

Khuyến nghị: Chỉ thu nhỏ khi kích thước thật sự là vấn đề. Với hầu hết các lần khôi phục lên staging, một bản sao nguyên cỡ sẽ đơn giản và ít rủi ro hơn một bản đã bị xóa dở.


Ẩn danh hóa

Ẩn danh hóa gỡ bỏ hoặc thay thế dữ liệu cá nhân và dữ liệu nhạy cảm để không thể truy ngược ra một cá nhân nào từ bản sao. Đây là thao tác có sức nặng pháp lý đứng sau: theo GDPR và các quy định tương tự, một bản sao production đầy dữ liệu cá nhân thật nằm trên máy của một lập trình viên là một hoạt động xử lý dữ liệu mà nhiều khả năng bạn không biện minh được.

Ẩn danh hóa nhắm vào:

  • PII trực tiếp: họ tên, email, số điện thoại, địa chỉ, số định danh cá nhân, số tài khoản ngân hàng, ngày sinh.
  • Dữ liệu kinh doanh nhạy cảm: lương, giá vốn, biên lợi nhuận, giá bán — dữ liệu mang tính bảo mật ngay cả khi không phải dữ liệu cá nhân.

Mục tiêu là một database đủ thực tế để phát triển và kiểm thử, nhưng không phơi bày ai cả nếu bị rò rỉ. Một lập trình viên đang debug lỗi bảng lương cần các phiếu lương có cấu trúc đáng tin; họ không cần biết lương thật của ai.

Ẩn danh hóa là thao tác nhiều việc nhất vì nó phụ thuộc vào lược đồ cụ thể. Các công cụ chung có thể che những trường hiển nhiên như res_partner.email, nhưng database thật mang PII trong cả các trường tùy chỉnh, các bản sao phi chuẩn hóa, phần thân tin nhắn trong mail message, lịch sử giá trị theo dõi và file đính kèm. Làm cho tới nơi nghĩa là đi qua lược đồ thật, không chỉ các bảng tiêu chuẩn.

Quy tắc: Nếu một bản sao sẽ dùng cho kiểm thử tự động, chia sẻ để debug, hay đem ra demo — tức bất kỳ đâu ngoài vòng tin cậy vốn đã có quyền truy cập production — thì nó phải được ẩn danh hóa. Trung hòa không thay thế được điều này: một database đã trung hòa vẫn chứa đủ mọi tên thật và mức lương thật.


Làm mờ

Làm mờ thay các giá trị nhạy cảm bằng giá trị đã mã hóa mà một mật khẩu có thể đưa trở lại thành bản gốc. Odoo có sẵn tính năng này từ 16.0 dưới dạng odoo obfuscate:

odoo obfuscate -d {{database}} --pwd "$OBFUSCATE_PWD" \
  --fields res_partner_bank.acc_number
odoo obfuscate -d {{database}} --pwd "$OBFUSCATE_PWD" --unobfuscate \
  --fields res_partner_bank.acc_number

Lệnh này mã hóa giá trị ngay tại chỗ bằng pgcrypto của PostgreSQL. Nó làm việc theo từng cột, không theo từng bản ghi: mọi dòng của một cột được liệt kê đều bị mã hóa, và không có cách nào chọn ra một tập con bản ghi. Lệnh có sẵn một danh sách cột mặc định (tên đối tác, các trường liên hệ và địa chỉ, phần thân mail_message, lịch sử mail_tracking_value, lead của CRM). Tham số --fields table.column,... hoặc một file (--file, mỗi dòng một table.column) mở rộng danh sách đó với các cột riêng của dự án, và đúng danh sách ấy phải được truyền lại khi gỡ làm mờ. Chỉ các cột kiểu văn bản mới đủ điều kiện, nên số tiền, ngày tháng và file đính kèm vẫn đọc được.

Vì các giá trị đã mã hóa được ghi đè vào chính dữ liệu thật:

  • Lệnh hỏi xác nhận trước khi chạy: This will alter data in the database <db> and can lead to a data loss. Cho tới khi bản sao được gỡ làm mờ, các giá trị gốc chỉ tồn tại dưới dạng bản mã.
  • Mật khẩu được lưu trong ir_config_parameter (odoo_cyph_pwd), mã hóa bằng chính nó để các lần chạy sau kiểm chứng được. Hãy giữ mật khẩu cẩn thận; mất nó là mất trắng mọi giá trị đã làm mờ.
  • Một giá trị đã mã hóa mà bị cập nhật trong lúc database đang ở trạng thái làm mờ (do người dùng sửa, hoặc do một trường tính toán như complete_name nối chuỗi vào) thì không còn là bản mã hợp lệ, và lần chạy --unobfuscate sau đó sẽ hỏng ở đúng chỗ ấy.

Làm mờ không phải ẩn danh hóa. Bất kỳ ai có mật khẩu đều đọc lại được dữ liệu, và chính lời nhắc của lệnh nói rằng nó không được coi là an toàn để chuyển dữ liệu cho bên thứ ba. Các giá trị đã mã hóa là chuỗi base64, không phải dữ liệu kiểm thử trông thực tế. Nó hợp với một bản sao phải quay về với giá trị thật.


Một quy tắc để quyết định

Hãy xuất phát từ chỗ bản sao sẽ đi tới, rồi áp dụng mọi thứ cho tới mức đó:

  1. Mọi bản sao không phải production → trung hòa, cả hai nửa.
  2. Bản sao lớn và kích thước gây đau → thu nhỏ thêm.
  3. Bản sao rời khỏi vòng tin cậy (máy của lập trình viên, CI, demo, bất kỳ ai không có quyền truy cập production) → ẩn danh hóa thêm.

Sai lầm phổ biến nhất và nguy hiểm nhất là dừng ở bước 1 trong khi bản sao thực ra thuộc diện bước 3, tức coi “cron đã tắt và URL đã sửa” là “database đã an toàn”. Không phải vậy. Một máy chủ staging mà cả đội với tới được, chứa dữ liệu production nhận diện được đầy đủ, chỉ là một vụ rò rỉ có thêm vài bước.

Làm mờ không thỏa mãn bước 3. Một bản sao đã làm mờ vẫn giữ đủ mọi giá trị thật, chỉ cách một cái mật khẩu.


Những điểm chính

Xử lý dữ liệu nhạy cảm trong Odoo là bốn thao tác, không phải một. Trung hòa ngăn bản sao với tới thế giới bên ngoài (odoo neutralize, thứ thuộc về chính các module của bạn) và cấu hình lại nó cho môi trường mới. Thu nhỏ cắt bớt cho dễ làm việc. Ẩn danh hóa lột bỏ dữ liệu cá nhân và dữ liệu nhạy cảm để một vụ rò rỉ không làm hại ai. Làm mờ (odoo obfuscate) mã hóa các cột ngay tại chỗ và đảo ngược được, miễn là mật khẩu còn giữ và các giá trị đã mã hóa không bị đụng tới. Chúng thường được chạy cùng nhau, nhưng biết rõ cái nào là cái nào sẽ cho bạn biết còn thiếu gì khi một bản sao chuyển sang một nơi mới.