PostgreSQL的行級安全策略(RLS)

[MemFireDB,帶你體驗不一樣的雲端飛翔。]()

RLS(ROW Level Security) 是PostgreSQL 9。5版本中新增特性,提供了基於行的安全策略,限制資料庫使用者的查看錶資料許可權。要知道在9。5版本之前,資料庫中對使用者的許可權管控在表級別,例如:限制某個使用者只能查詢某個表。採用RLS後,不同的使用者訪問一個表可以看到不同的資料。

1、概述

預設的話,表沒有任何安全策略限制。這樣使用者根據 SQL 特權系統具有對錶的訪問特權,對於查詢或更新來說其中所有的行都是平等的。當在一個表上啟用行安全性時,所有對該表選擇行或者修改行的普通訪問都必須被一條 行安全性策略所允許(不過,表的擁有者通常不服從行安全性策略)。如果表上不存在安全策略,如果沒有配置安全策略,所有的資料查詢和更新都會禁止,但是對全表進行操作的命令,比如 TRUNCATE 和 REFERENCES 不受影響。

行安全性策略可以針對特定的命令、角色或者兩者。一條策略可以被指定為適用於ALL命令,或者查詢(SELECT)、 插入(INSERT)、更新(UPDATE)或者刪除(DELETE)。同一個策略可分配多個角色,並且通常的角色成員關係和繼承規則也適用。但是表的所有者,超級使用者 (postgres) 以及加上了 BYPASSRLS 屬性的角色不受安全性的限制。

只有所有者才具有啟用 / 禁用行級安全性,給表新增策略的許可權。

常見命令:

CREATE POLICY :建立策略

ALTER POLICY :修改策略

DROP POLICY :刪除策略

ALTER TABLE :用於行級安全性的啟用 / 禁用。

每個策略都有一個名字,每個表可以定義多個策略,因為策略是針對表的,所以表內的多個策略名字必須唯一,但是不同的表可以有同名的策略,當表有多個策略時,多個策略之間是 OR 的關係。

2、相關示例

新建一張表,並插入三條資料:

CREATE TABLE userlist (id text, name text);insert into userlist values(1,‘user01’);insert into userlist values(2,‘user02’);insert into userlist values(3,‘user03’);

執行查詢操作,檢視資料表中的結果

select * from userlist; id | name ——+———— 2 | user02 1 | user01 3 | user03(3 rows)

建立一個使用者,並授予其查詢許可權;

create user user01 with password ‘123456’;create user user02 with password ‘123456’;grant select ON public。userlist to user01,user02;grant insert ON public。userlist to user01,user02;grant update ON public。userlist to user01,user02;

此時user01、user02可以執行查詢操作,獲得整個表userlist的全部資料;

用例1:限制user01使用者限制只能查詢表userlist中name=‘user01’的資料

建立策略,

create policy user01_select ON userlist for select to user01 using(current_user=name);

此時查看錶結構;

\d userlist

返回結果如下:

Table “public。userlist” Column | Type | Collation | Nullable | Default ————+————+——————-+——————+————- id | text | | | name | text | | | Policies (row security disabled): POLICY “user01_select” FOR SELECT TO user01 USING (((CURRENT_USER)::text = name))

從這兒我們可以看到該策略是沒有啟用的,處於disabled狀態;

要開啟表的行級安全,需要使用ALTER TABLE命令:

alter table userlist enable row level security ;

使用賬號user01連線資料庫

\c - user01You are now connected to database “memfire” as user “user01”。

執行查詢操作,得到結果如下:

select * from userlist id | name ——+———— 1 | user01(1 row)

開啟行級許可權後,user01僅能夠查詢name=‘user01’的資料

使用賬號user02連線資料庫

\c - user02You are now connected to database “memfire” as user “user02”。

執行查詢操作,得到結果如下:

select * from userlist; id | name ——+————(0 rows)

開啟行級許可權後,user02無法查詢資料,說明策略生效了

用例2:建立新增資料策略

切換到資料表owner賬戶, 建立一個插入策略;

create policy user01_insert on userlist for insert to user01 with check(true);

執行命令,檢視已經建立的策略;

——pg_policies可以檢視已經建立的策略select * from pg_policies;

返回結果如下:

schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check ——————+——————-+————————-+——————+——————+————+————————————————-+—————— public | userlist | user01_select | PERMISSIVE | {user01} | SELECT | ((CURRENT_USER)::text = name) | public | userlist | user01_insert | PERMISSIVE | {user01} | INSERT | | true(2 rows)

使用賬號user01連線資料庫

\c - user01You are now connected to database “memfire” as user “user01”。

插入一條新資料

insert into userlist values(4,‘user01’);INSERT 0 1

執行查詢操作

select * from userlist; id | name ——+———— 4 | user01 1 | user01(2 rows)

使用賬號user02連線資料庫

\c - user02You are now connected to database “memfire” as user “user02”。

插入一條新資料

insert into userlist values(5,‘user02’);ERROR: new row violates row-level security policy for table “userlist”

採用user02無法插入資料,說明建立的策略生效。

用例3:建立刪除資料策略

切換到資料表owner賬戶, 建立一個插入策略;

create policy user01_delete on userlist for delete to user01 using(current_user=name);

執行命令,檢視已經建立的策略;

——pg_policies可以檢視已經建立的策略select * from pg_policies;

返回結果如下:

schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check ——————+——————-+————————-+——————+——————+————+————————————————-+—————— public | userlist | user01_select | PERMISSIVE | {user01} | SELECT | ((CURRENT_USER)::text = name) | public | userlist | user01_insert | PERMISSIVE | {user01} | INSERT | | true public | userlist | user01_delete | PERMISSIVE | {user01} | DELETE | ((CURRENT_USER)::text = name) | (3 rows)

執行查詢操作

select * from userlist;id | name ——+———— 2 | user02 4 | user01 1 | user01 3 | user03(4 rows)

使用賬號user01連線資料庫

\c - user01You are now connected to database “memfire” as user “user01”。

刪除資料

delete from userlist;DELETE 2

建立刪除策略後,user01僅能夠刪除name=‘user01’的資料

使用賬號user02連線資料庫

\c - user02You are now connected to database “memfire” as user “user02”。

執行刪除操作

memfire=> delete from userlist;DELETE 0

採用user02無法刪除資料,說明建立的策略生效。

樣例4. 限制user01使用者限制只能更新表userlist中name=‘user01’的資料

切換到資料表owner賬戶, 建立一個更新策略;

create policy user01_update on userlist for update to user01 using(current_user=name);

執行命令,檢視已經建立的策略;

——pg_policies可以檢視已經建立的策略select * from pg_policies;

返回結果如下:

schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check ——————+——————-+————————-+——————+——————+————+————————————————-+—————— public | userlist | user01_select | PERMISSIVE | {user01} | SELECT | ((CURRENT_USER)::text = name) | public | userlist | user01_insert | PERMISSIVE | {user01} | INSERT | | true public | userlist | user01_delete | PERMISSIVE | {user01} | DELETE | ((CURRENT_USER)::text = name) | public | userlist | user01_update | PERMISSIVE | {user01} | UPDATE | ((CURRENT_USER)::text = name) | (4 rows)

插入三條資料:

insert into userlist values(1,‘user01’);insert into userlist values(4,‘user01’);insert into userlist values(2,‘user05’);

執行查詢操作:

select * from userlist; id | name ——+———— 2 | user02 5 | user02 4 | user01 1 | user01 3 | user03

更新所有name=“user01“的資料的id更新為2

update userlist set id=2;UPDATE 2

建立刪除策略後,user01僅能夠更新name=‘user01’的資料;

更新後,切換到表userlist表owner,執行查詢操作

select * from userlist; id | name ——+———— 2 | user02 5 | user02 2 | user01 2 | user01 3 | user03

今天就介紹到這兒,更多詳細內容,可以參考行安全性策略。

參考資料

建立策略:http://postgres。cn/docs/9。5/sql-createpolicy。html

修改策略:http://postgres。cn/docs/9。5/sql-alterpolicy。html

刪除策略:http://postgres。cn/docs/9。5/sql-droppolicy。html

用於行級安全性的啟用 / 禁用:http://postgres。cn/docs/9。5/sql-altertable。html

行安全性策略:http://postgres。cn/docs/9。5/ddl-rowsecurity。html

PostgreSQL的行級安全策略(RLS)