台灣台北 - 2023 年 3 月 9 日
我很榮幸地宣布 pg_anonymize 的 Beta 版本。
pg_anonymize 是一個 PostgreSQL 擴充套件,提供簡單、穩健且透明的基礎架構,用於資料匿名化。 其目標是確保任何與匿名角色連線的人,只會看到資料的匿名版本,而不會對使用的客戶端(可以是 psql、pg_dump、您自己的應用程式,甚至其他工具,例如 pg_sample...)或架構和關聯的數量有任何限制。
匿名化是使用宣告式方法完成的,依靠 SECURITY LABEL:您只需要為每個應匿名化的欄位宣告一個表達式,該表達式將動態執行匿名化。可以使用任何產生正確型別的有效表達式,因此您可以使用純 SQL、PL/pgSQL 或您選擇的任何其他程序語言編寫它們。
此擴充套件與 PostgreSQL 10 及以上版本相容。 有關其使用的更多詳細資訊,請查看下面的 使用方法 部分或 文件。
如果您遇到任何問題或想要求新功能,請隨時 開啟 issue。
pg_anonymize 提供以下設定選項
pg_anonymize.enabled (bool):允許全域啟用或停用 pg_anonymize。預設值為 on。
pg_anonymize.check_labels (bool):在宣告安全標籤時,對定義的表達式執行健全性檢查(表達式有效性、唯讀、傳回型別和缺少 SQL 注入)。預設值為 on。
注意:即使停用了 pg_anonymize.check_labels,pg_anonymize 仍會檢查定義的表達式是否不包含任何 SQL 注入。
必須先載入 pg_anonymize 才能使用它。有多種方法可以做到這一點。通常,只有少數角色需要資料匿名化,因此建議的方式是僅為這些角色載入擴充套件。例如,假設應使用角色 alice
ALTER ROLE alice SET session_preload_libraries = 'pg_anonymize';
注意:只有在成功執行此命令後由 alice 開啟的會話才會載入 pg_anonymize。
或者,您可以明確載入它,例如
LOAD 'pg_anonymize';
注意:LOAD 需要超級使用者權限。
然後,您需要將所需的角色宣告為需要匿名資料。這是透過在目標角色上新增 SECURITY LABEL anonymize 來完成的。例如
-- 在宣告 SECURITY LABEL 之前需要載入 pg_anonymize LOAD 'pg_anonymize'; SECURITY LABEL FOR pg_anonymize ON ROLE alice IS 'anonymize';
注意:在角色上宣告 SECURITY LABEL 需要 CREATEROLE 權限。
然後,您可以使用 SECURITY LABEL 宣告如何匿名化每個欄位,定義一個表達式來替換實際內容。
例如,假設有一個簡單的客戶表格
``` CREATE TABLE public.customer(id integer, first_name text, last_name text, birthday date, phone_number text);
INSERT INTO public.customer VALUES (1, 'Nice', 'Customer', '1970-03-04', '+886 1234 5678');
GRANT SELECT ON TABLE public.customer TO alice; ```
讓我們匿名化姓氏、生日和電話號碼
SECURITY LABEL FOR pg_anonymize ON COLUMN public.customer.last_name IS $$substr(last_name, 1, 1) || '*****'$$; SECURITY LABEL FOR pg_anonymize ON COLUMN public.customer.birthday IS $$date_trunc('year', birthday)::date$$; SECURITY LABEL FOR pg_anonymize ON COLUMN public.customer.phone_number IS $$regexp_replace(phone_number, '\d', 'X', 'g')$$;
注意:在欄位上宣告 SECURITY LABEL 需要成為基礎關係的所有者。
alice 角色現在將自動看到匿名化的資料。例如
``` -- 目前角色看到的是正常資料 =# SELECT * FROM public.customer; id | first_name | last_name | birthday | phone_number ----+------------+-----------+------------+---------------- 1 | Nice | Customer | 1970-03-04 | +886 1234 5678 (1 row)
-- 但 alice 將看到匿名化的資料 =# \c - alice 您現在以使用者 "alice" 連線到資料庫 "rjuju"。
=> SELECT * FROM public.customer; id | first_name | last_name | birthday | phone_number ----+------------+-----------+------------+---------------- 1 | Nice | C* | 1970-01-01 | +XXX XXXX XXXX (1 row)
-- pg_dump 也會看到匿名化的資料 $ pg_dump -U alice -t public.customer -a rjuju | grep "COPY" -A2 COPY public.customer (id, first_name, last_name, birthday, phone_number) FROM stdin; 1 Nice C* 1970-01-01 +XXX XXXX XXXX . ```