因為遮碼的示範不是重點,這邊沿用 EDB 關於 Data Redaction 教學文章的範例就好。
在範例中,原本使用的遮碼設定如下:
CREATE REDACTION POLICY emp_data_protect
ON employees FOR (session_user <> 'privilegeduser')
ADD COLUMN ssn USING redact_ssn(ssn),
ADD COLUMN salary USING redact_salary(salary);
如紅色部份的設定,只有除了 Superuser 以及這邊指定的 privilegeduser 之外,其他帳號都不能查看原本內容。
如果要透過群組控制呢?(例如,非群組成員跟 Superuser 之外的帳號都不能偷看~)
雖然要檢查群組成員是 OK 的。
edb=# select session_user::regrole = any (grolist::regrole[]) from pg_group where groname = 'grp'; ?column? ---------- f (1 row) edb=#
但這樣的 SQL 沒辦法塞進去 Redaction Policy 裡面。
edb=# CREATE REDACTION POLICY emp_data_protect ON employees FOR (select session_user::regrole = any (grolist::regrole[]) from pg_group where groname = 'grp') ADD COLUMN ssn USING redact_ssn(ssn); ERROR: syntax error at or near "select" LINE 1: ...DACTION POLICY emp_data_protect ON employees FOR (select ses... ^ edb=#
因此要塞一個表達式才行,不能塞一句 SQL。。。
所幸 Postgres 提供許多系統函數可以改寫上述的檢查方式。
這邊使用的函數是檢查權限的函數之一 pg_has_role()。
首先,先建立一下新的測試帳號跟群組。這邊帳號 aaa 屬於群組 grp,然後有一個對照組,帳號 bbb。
edb=# create role grp; CREATE ROLE edb=# create user aaa; CREATE USER edb=# grant grp to aaa; GRANT edb=# create user bbb; CREATE USER edb=# edb=# \du List of roles Role name | Attributes | Member of -----------------------+------------------------------------------------------------+----------- aaa | Profile default | {grp} aq_administrator_role | No inheritance, Cannot login +| {} | Profile default | bbb | Profile default | {superu} enterprisedb | Superuser, Create role, Create DB, Replication, Bypass RLS+| {} | Profile default | grp | Cannot login +| {} | Profile default | superu | Superuser, No inheritance, Cannot login +| {} | Profile default | edb=#
然後讓我們變更 Redaction Policy,調整為「非群組成員」不能看到完整內容(注意,Superuser不受本設定影響)
ALTER REDACTION POLICY emp_data_protect ON employees
FOR ( NOT pg_has_role('grp'::name, 'member') );
修改之後,表格資訊如下:
edb=# \d enterprisedb.employees Table "enterprisedb.employees" Column | Type | Collation | Nullable | Default --------+-----------------------+-----------+----------+---------------------------------- id | integer | | not null | generated by default as identity name | character varying(40) | | not null | ssn | character varying(11) | | not null | salary | money | | | Indexes: "employees_pkey" PRIMARY KEY, btree (id) Redaction Policies: REDACTION POLICY "emp_data_protect" FOR (NOT pg_has_role('grp'::name, 'member'::text)) ENABLED Number of redacted columns: 2 (Use \d+ to list them.) edb=#
接著進行測試。
1) 登入帳號 aaa,確認群組成員看得到資料內容
edb=# \c edb aaa You are now connected to database "edb" as user "aaa". edb=> select * from enterprisedb.employees; id | name | ssn | salary ----+--------------+-------------+------------ 1 | Sally Sample | 020-78-9345 | $51,234.34 2 | Jane Doe | 123-33-9345 | $62,500.00 3 | Bill Foo | 123-89-9345 | $45,350.00 (3 rows) edb=>
b) 再登入帳號 bbb,確認群組以外的普通帳號,只看得到遮碼結果
edb=> \c edb bbb You are now connected to database "edb" as user "bbb". edb=> select * from enterprisedb.employees; id | name | ssn | salary ----+--------------+-------------+-------- 1 | Sally Sample | xxx-xx-9345 | $0.00 2 | Jane Doe | xxx-xx-9345 | $0.00 3 | Bill Foo | xxx-xx-9345 | $0.00 (3 rows) edb=>
若是現在將 bbb 也加入群組,就會發現 bbb 帳號也可以看資料了
edb=# grant grp to bbb; GRANT ROLE edb=# \c edb bbb You are now connected to database "edb" as user "bbb". edb=> select * from enterprisedb.employees; id | name | ssn | salary ----+--------------+-------------+------------ 1 | Sally Sample | 020-78-9345 | $51,234.34 2 | Jane Doe | 123-33-9345 | $62,500.00 3 | Bill Foo | 123-89-9345 | $45,350.00 (3 rows) edb=>
基本上這樣就測試的差不多了~如果要反過來,只針對某群組的帳號作限制,把 NOT 拿掉就好
ALTER REDACTION POLICY emp_data_protect ON employees
FOR ( pg_has_role('grp'::name, 'member') );
參考資料:
之前的筆記
沒有留言:
張貼留言