目前PostgreSQL並不能像MySQL一樣直接對某個數據庫賦予只讀權限,現實中有研發需要新建一個用戶然后賦予對某個數據庫只讀權限。
舉例說明如何創建
用edbstore用戶連接edbstore數據庫,並創建一個測試schema
$ psql -U edbstore edbstore psql (9.6.4) Type "help" for help. edbstore=> create schema ota_data; CREATE SCHEMA edbstore=> \dn ota_data List of schemas Name | Owner ----------+---------- ota_data | edbstore (1 row)
在測試schema下創建一張測試表並插入部分數據
edbstore=> set search_path to ota_data ; SET edbstore=> show search_path ; search_path ------------- ota_data (1 row) edbstore=> create table tb1(name varchar,age int); CREATE TABLE edbstore=> insert into tb1 values('chris',23); INSERT 0 1 edbstore=> insert into tb1 values('tonny',25); INSERT 0 1 edbstore=> select * from tb1; name | age -------+----- chris | 23 tonny | 25 (2 rows)
現在新建一個readonly用戶並嘗試訪問edbstore用戶下新建的測試數據
postgres=# create role readonly password 'readonly' login; CREATE ROLE
$ export PGPASSWORD=readonly $ psql -h 172.16.101.66 -U readonly edbstore psql (9.6.4) Type "help" for help. edbstore=> set search_path to ota_data ; SET edbstore=> \d No relations found.
可以看到默認情況下新用戶readonly是無法看到edbstore用戶下的數據的,現在賦予用戶readonly查看schema對象的權限
edbstore=> GRANT USAGE ON SCHEMA ota_data TO readonly; GRANT
readonly用戶再次查看
edbstore=> \d List of relations Schema | Name | Type | Owner ----------+------+-------+---------- ota_data | tb1 | table | edbstore (1 row) edbstore=> select * from tb1 ; ERROR: permission denied for relation tb1
可以看到雖然用戶可以查看到該對象,但是沒用select權限,現在進行賦權
edbstore=> \dp Access privileges Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+-------+-------------------+-------------------+---------- ota_data | tb1 | table | | | (1 row) edbstore=> GRANT SELECT ON ALL TABLES IN SCHEMA ota_data TO readonly; GRANT edbstore=> \dp Access privileges Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+-------+---------------------------+-------------------+---------- ota_data | tb1 | table | edbstore=arwdDxt/edbstore+| | | | | readonly=r/edbstore | | (1 row)
readonly用戶再次查看
edbstore=> select * from tb1 ; name | age -------+----- chris | 23 tonny | 25 (2 rows) edbstore=> insert into tb1 values('tina',19); ERROR: permission denied for relation tb1
該命令只能對已經存在的對象(表,視圖等)賦權,新建立的表,readonly用戶是無法查看的,新建一張表
edbstore=> create table tb2 as select * from tb1; SELECT 2 edbstore=> \dp Access privileges Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+-------+---------------------------+-------------------+---------- ota_data | tb1 | table | edbstore=arwdDxt/edbstore+| | | | | readonly=r/edbstore | | ota_data | tb2 | table | | | (2 rows)
readonly用戶再次查看
edbstore=> \d List of relations Schema | Name | Type | Owner ----------+------+-------+---------- ota_data | tb1 | table | edbstore ota_data | tb2 | table | edbstore (2 rows) edbstore=> select * from tb2; ERROR: permission denied for relation tb2
為了讓readonly用戶可以有權限繼續查看新建的表,需要為該新建的schema指定default權限
edbstore=> ALTER DEFAULT PRIVILEGES IN SCHEMA ota_data GRANT SELECT ON TABLES TO readonly; ALTER DEFAULT PRIVILEGES edbstore=> \ddp Default access privileges Owner | Schema | Type | Access privileges ----------+----------+-------+--------------------- edbstore | ota_data | table | readonly=r/edbstore (1 row) edbstore=> create table tb3 as select * from tb1; SELECT 2 edbstore=> \dp Access privileges Schema | Name | Type | Access privileges | Column privileges | Policies ----------+------+-------+---------------------------+-------------------+---------- ota_data | tb1 | table | edbstore=arwdDxt/edbstore+| | | | | readonly=r/edbstore | | ota_data | tb2 | table | | | ota_data | tb3 | table | edbstore=arwdDxt/edbstore+| | | | | readonly=r/edbstore | | (3 rows)
可以看到新建的表tb3會自動繼承我們給該schema下的表預定義的select權限。
edbstore=> select * from information_schema.role_table_grants where grantee='readonly'; grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy ----------+----------+---------------+--------------+------------+----------------+--------------+---------------- edbstore | readonly | edbstore | ota_data | tb1 | SELECT | NO | YES edbstore | readonly | edbstore | ota_data | tb3 | SELECT | NO | YES (2 rows)
如何取消該權限
alter default privileges in schema public revoke select on tables from readonly ;
關於如何對整個輸幾局所有schema添加權限可以參考如下命令:
select 'grant usage on schema '|| schema_name || ' to readonly ;' from information_schema.schemata; select 'GRANT SELECT ON ALL TABLES IN SCHEMA '|| schema_name || ' TO readonly ;' from information_schema.schemata; select 'ALTER DEFAULT PRIVILEGES IN SCHEMA '|| schema_name || ' GRANT SELECT ON TABLES TO readonly ;' from information_schema.schemata;