本文為您介紹在Hologres中,如何基于PostgreSQL標準模型(專家權限模型)進行授權的最佳實踐。幫助您簡化授權操作并使用更細粒度的權限管理。
背景信息
Hologres兼容PostgreSQL生態,支持PostgreSQL的標準權限模型(簡稱專家權限模型)。同時,Hologres提供了一套簡單權限模型的授權模式,詳情請參見簡單權限模型概述。
簡單權限模型的權限劃分粒度比較粗,不太適用于細粒度的權限管理場景。PostgreSQL的標準授權對于權限的劃分非常細致,如果您需要使用更細粒度的權限管理,請參照本文基于PostgreSQL授權的最佳實踐進行操作。
PostgreSQL權限模型簡介
標準PostgreSQL授權擁有詳細的權限管理體系,詳情請參見Postgresql授權。
PostgreSQL授權的限制如下:
PostgreSQL授權僅支持對現有對象授權,對未來的對象不生效。示例如下。
User1執行了
GRANT SELECT ON ALL TABLES IN SCHEMA public TO User2;
語句對User2授予了public Schema中所有表的SELECT權限。User1在public Schema中創建了一張新表table_new。
User2執行
SELECT * FROM table_new
語句時顯示報錯Permission denied
。由于User1對User2授予SELECT權限時,僅包含授權時刻public Schema中的所有表,而不包含未來在public Schema中創建的表,因此會產生上述報錯。
您可以使用
ALTER DEFAULT PRIVILEGES
語句,對未來對象設置默認權限,詳情請參見ALTER DEFAULT PRIVILEGES。該權限僅對未來對象生效。示例語句如下。ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO PUBLIC; --當前授權的人對在public Schema中新創建的表具有讀權限。
您也可以使用
ALTER DEFAULT PRIVILEGES FOR ROLE xxx
語句,為其他角色創建默認權限。當前用戶和xxx滿足以下關系時才能成功設置默認權限:當前用戶是xxx組的成員。
當前用戶是超級用戶(Superuser)時,xxx可以為用戶或組。
您可以使用psql命令
\ddp
查看(系統表為pg_catalog.pg_default_acl
)ALTER DEFAULT PRIVILEGES
是否設置成功。ALTER DEFAULT PRIVILEGES
類似于一個觸發器。創建新表時,Hologres會使用當前用戶和Schema去檢查pg_catalog.pg_default_acl
系統表中是否有匹配項。如果存在匹配項,則系統自動添加匹配項規則。說明您只能使用當前用戶與匹配項規則進行匹配,不能使用當前用戶的用戶組去匹配。
alter default privileges
規則匹配只能在創建表時執行,在創建表之后修改表Owner(alter table tablename owner to
)不會觸發alter default privileges
。
例如,用戶User1屬于Group1,如果要給Group1匹配規則,授予未來表全權限。情況如下:
如果當前用戶是User1,則創建表時匹配不到規則。
如果創建表之前先執行
set session role group1;
,改變當前用戶為Group1,則創建表時就可以匹配到規則,系統自動為新創建的表授權。
只有表Owner才可以刪除表。
在標準的PostgreSQL授權語句中,您需要根據Ownership來判斷是否可以刪除表??梢詣h除表的角色如下:
表的Owner(即建表者)。
表所在Schema的Owner。
Superuser
在PostgreSQL中,系統會默認創建表的用戶為表的Owner,擁有該表的所有權限,包括刪除表的權限。
修改表Owner,示例如下語句。
ALTER TABLE <tablename> OWNER TO user2; //將表Owner由User1修改為User2。 ALTER TABLE <tablename> OWNER TO group1;//將表Owner修改為Group1。
修改表Owner的操作限制如下:
User1為表的Owner。
User1必須是Group1的直接或者間接成員。
例如,User1是Group1的成員,或User1是Group1中某個組的成員。
Group1必須在表所在的Schema中有創建表的權限。
Superuser可以修改任意表的表Owner。
PostgreSQL權限模型規劃
標準的PostgreSQL(專家權限模型)權限粒度劃分比較細致,在使用之前需要對現有實例對象做如下權限規劃:
總共有多少個權限組。
每個組的作用是什么。
每個組包含哪些用戶。
哪些角色在什么時候可以刪除表。
每個組在哪些Schema中工作。
建議您執行如下操作,規劃實例對象:
確定權限組以及組的作用。
權限組分為以下類型:
XX_DEV_GROUP:表的Owner,擁有表的所有操作權限。
XX_WRITE_GROUP:表的寫入權限,可以寫入數據至相應表。
XX_VIEW_GROUP:查看表數據權限,可以查看相應表的數據。
XX表示一個項目。例如PROJ1項目的權限組包括PROJ1_DEV_GROUP、 PROJ1_WRITE_GROUP及PROJ1_VIEW_GROUP。
說明組名的命名規范僅為建議參考,不做強制要求。
確定權限組所在的Schema。
推薦每個項目的權限組使用一個Schema。
一個DEV_GROUP可以擁有多張表,但每張表只能屬于一個DEV_GROUP。例如,表TABLE1屬于PROJ1_DEV_GROUP,則該表就不屬于PROJ2_DEV_GROUP。
一個用戶可以屬于多個DEV_GROUP。例如,User1可以既是PROJ1_DEV_GROUP的成員,也可以是PROJ2_DEV_GROUP的成員。
Hologres專家權限模型最佳實踐一
本次實踐以表對象為例,您也可以選用其他對象進行實驗。
表的Owner是對應的XXX_DEV_GROUP權限組,因此,DEV_GROUP組中的任意成員都可以管理或刪除該表。
例如,用戶被添加到PROJ1_DEV_GROUP用戶組之后,就擁有PROJ1項目中表的管理或刪除權限。具體操作步驟如下:
創建用戶組。
您可以根據業務需求劃分權限模型,由Superuser創建相應的用戶組,以PROJ1項目為例,示例語句如下。
CREATE ROLE PROJ1_DEV_GROUP; //表的Owner,擁有表的所有操作權限。 CREATE ROLE PROJ1_WRITE_GROUP; //表的寫入權限,可以寫入數據至相應表。 CREATE ROLE PROJ1_VIEW_GROUP; //查看表數據權限,可以查看相應表的數據。
授權用戶組Schema的權限。
您需要授予創建完成的用戶組Schema的權限,示例項目PROJ1可以在Schema1中工作,語句如下。
授權PROJ1擁有SCHEMA1中的相關權限。 GRANT CREATE,usage ON schema SCHEMA1 TO PROJ1_DEV_GROUP; GRANT usage ON schema SCHEMA1 TO PROJ1_WRITE_GROUP; GRANT usage ON schema SCHEMA1 TO PROJ1_VIEW_GROUP;
說明一個項目可以對應多個Schema,一個Schema也可以對應多個項目。
默認public Schema中所有用戶都有CREATE和USAGE權限。
創建用戶并管理用戶組。
授權用戶組Schema權限后,Superuser需要創建用戶并添加用戶至對應的用戶組,示例語句如下。
CREATE USER "USER1"; GRANT PROJ1_DEV_GROUP TO "USER1"; CREATE USER "USER2"; GRANT PROJ1_VIEW_GROUP TO "USER2";
創建表并授權。
創建表等對象時,由表的創建者(必須為PROJ1_DEVE_GROUP的成員)或Superuser執行相應的授權語句(假設新創建的表為TABLE1)。 示例如下。
GRANT ALL ON TABLE SCHEMA1.TABLE1 TO PROJ1_WRITE_GROUP; //授予PROJ1_WRITE_GROUP寫入數據至TABLE1的權限。 GRANT SELECT ON TABLE SCHEMA1.TABLE1 TO PROJ1_VIEW_GROUP; //授予PROJ1_VIEW_GROUP TABLE1的SELECT權限。 ALTER TABLE SCHEMA1.TABLE1 owner TO PROJ1_DEV_GROUP; //修改TABLE1的Owner為PROJ1_DEV_GROUP。
Hologres專家權限模型最佳實踐二
本次實踐,使用ALTER DEFAULT PRIVILEGES
語句簡化對每張表的授權操作。
您需要提前確定創建的表默認屬于哪個項目。具體操作步驟如下:
創建用戶組。
您可以根據業務需求劃分權限模型,由Superuser創建相應的用戶組,以PROJ1項目為例,示例語句如下。
CREATE ROLE PROJ1_DEV_GROUP; //表的Owner,擁有表的所有操作權限。 CREATE ROLE PROJ1_WRITE_GROUP; //表的寫入權限,可以寫入數據至相應表。 CREATE ROLE PROJ1_VIEW_GROUP; //查看表數據權限,可以查看相應表的數據。
授權用戶組Schema的權限。
您需要授予創建完成的用戶組Schema的權限,示例項目PROJ1可以在Schema1中工作,語句如下。
--授權PROJ1擁有SCHEMA1中的相關權限。 GRANT CREATE,USAGE ON SCHEMA SCHEMA1 TO PROJ1_DEV_GROUP; GRANT USAGE ON SCHEMA SCHEMA1 TO PROJ1_WRITE_GROUP; GRANT USAGE ON SCHEMA SCHEMA1 TO PROJ1_VIEW_GROUP;
說明一個項目可以對應多個Schema,一個Schema也可以對應多個項目。
默認public Schema中所有用戶都有CREATE和USAGE權限。
創建用戶并設置默認授權。
完成Schema授權后,需要Superuser創建用戶并添加用戶至相應的組中,同時設置該用戶創建表時擁有的默認權限。
USER1創建的表默認屬于PROJ1_DEV_GROUP,并且USER1為合法的阿里云賬號。示例設置授權語句如下。
CREATE USER "USER1"; ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT ALL ON TABLES TO PROJ1_DEV_GROUP; //設置USER1創建的表,PROJ1_DEV_GROUP默認都有讀寫權限。 ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT ALL ON TABLES TO PROJ1_WRITE_GROUP; //設置USER1創建的表,PROJ1_WRITE_GROUP默認都有讀寫權限。 ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT SELECT ON TABLES TO PROJ1_VIEW_GROUP; //設置USER1創建的表,PROJ1_VIEW_GROUP默認都有讀權限。 GRANT PROJ1_DEV_GROUP TO "USER1"; //添加USER1至PROJ1_DEV_GROUP。
修改表的Owner。
如果您希望DEV_GROUP中的其他用戶也可以管理或刪除創建的表,則可以修改表的Owner為對應項目的DEV_GROUP,例如PROJ1_DEV_GROUP。
修改表Owner的語句必須由表的創建者或Superuser執行。例如,示例中表的創建者必須是PROJ1_DEV_GROUP的成員。假設新創建的表為TABLE1。示例修改表Owner的語句如下。
ALTER TABLE SCHEMA1.TABLE1 OWNER TO PROJ1_DEV_GROUP; //修改TABLE1的Owner為PROJ1_DEV_GROUP。
如下情況,您可以修改表的Owner:
新創建的表,由Superuser定期修改表Owner。
在需要管理或刪除表之前修改表Owner。
說明如果您可以確認表的管理或刪除操作是由表的創建者或Superuser執行的,您也可以不執行上述命令。
修改用戶的默認項目。
調整用戶的默認項目,需要Superuser或用戶本人執行
alter default privileges
命令,撤銷已設置的缺省權限后,使用新的alter default privileges
創建默認授權。將USER1的默認項目由PROJ1改為PROJ2,該操作不影響現有的表。示例語句如下。
取消原有默認授權。 ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" REVOKE ALL ON TABLES FROM PROJ1_DEV_GROUP; ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" REVOKE ALL ON TABLES FROM PROJ1_WRITE_GROUP; ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" REVOKE SELECT ON TABLES FROM PROJ1_VIEW_GROUP; 創建新的默認授權。 ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT ALL ON TABLES TO PROJ2_DEV_GROUP; ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT ALL ON TABLES TO PROJ2_WRITE_GROUP; ALTER DEFAULT PRIVILEGES FOR ROLE "USER1" GRANT SELECT ON TABLES TO PROJ2_VIEW_GROUP;