權限分類
實例權限
pg_hba.conf
實例級別的權限由pg_hba.conf來控制
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all trust
host all all 0.0.0.0/0 md5
TYPE:
-
local:表示是unix-domain的socket連接
-
host:TCP/IP socket
注意:要使用該選項你要在postgresql.conf文件里設置listen_address選項,不在listen_address里的IP地址是無法匹配到的。因為默認的行為是只在localhost上監聽本地連接。
-
hostssl:SSL加密的TCP/IP socket
-
hostnossl:非SSL
DATABASE:
- 數據庫名,可以是"all", "sameuser", "samerole", "replication"。all表示所有,但不包括replication。多個數據庫用“,”隔開。
USER:
- 用戶名,可以為"all",表示所有,也可以具體指定一個用戶。多個用戶用“,”隔開。和DATABASE一樣,也可以將配置放到文件中,文件名加上前綴@
ADDRESS:
- 可以是為一個主機名,或者由IP地址和CIDR掩碼組成。掩碼可以為0-32(IPv4)或者0-128(IPv6)間的一個整數,32表示子網掩碼為255.255.255.255,24表示子網掩碼為255.255.255.0。主機名以“.”開頭。samehost可以匹配所有主機、samenet可以匹配同一個掩碼內的所有主機。
METHOD:
- trust:無條件的允許連接,不需要任何口令,即使口令是錯誤的
- reject:無條件拒絕連接,常用於拒絕某些用戶訪問,常見的拒絕用戶連接template1
- md5:使用md5加密的口令進行認證
- password:和md5一樣,但是口令是以明文形式在網絡上傳遞,比較危險
- scram-sha-256:pg10新增,這是當前提供的方法中最安全的方法,但是較舊的客戶端庫不支持此方法
- md5和scram-sha-256會以對應的方式加密再發送密碼
- ident:映射關系pg_ident.conf文件中
- perr:該模式使用連接發起端的操作系統名進行身份驗證。僅限於Linux、BSD、Mac OS X和Solaris,並且僅可用於本地服務器發起的連接。
pg_hba.conf中可以配置那些用戶,以及那些ip地址可以通過何種方式來訪問那些數據庫
-
參數配置如下
# TYPE DATABASE USER ADDRESS METHOD host all all 0.0.0.0/0 md5 host表示tcp/ip的方式,第一個all表示該主機上的所有數據庫實例,第二個all表示所有的用戶,ip地址是所有的ip地址,md5表示密碼驗證方式
使用方法
允許所有的用戶,能夠以tcp/ip方式訪問所有的數據庫,密碼認證方式md5
host all all 0.0.0.0/0 md5
不允許所有的用戶以tcp/ip方式訪問template1模板庫
host template1 all 0.0.0.0/0 reject
[postgres@localhost ~]$ psql -Usa template1
psql (11.1)
Type "help" for help.
template1=# \q
[postgres@localhost ~]$ psql -Usa template1 -h 192.168.1.2
psql: 致命錯誤: pg_hba.conf 記錄拒絕來自主機"192.168.1.2", 用戶"sa", 數據庫"template1", SSL 關閉的復制連接
允許本地所有用戶可以無密碼訪問任何數據庫
local all all trust
數據庫權限
GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }
ON DATABASE database_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
賦予用戶在指定數據庫下connect或者創建schema權限
默認情況下數據庫在創建后,允許public角色連接,既允許任何人連接
只能是超級用戶和owner才能在數據庫中創建schema
數據庫創建后會默認創建public的schema,這個schema的all權限已經賦予給public角色,即任何人在里面創建對象
postgres=# create database test;
CREATE DATABASE
postgres=# create user ceshi;
CREATE ROLE
postgres=# \c test ceshi
You are now connected to database "test" as user "ceshi".
test=> \dn
List of schemas
Name | Owner
--------+-------
public | sa
(1 row)
test=> create table public.test(id int);
CREATE TABLE
test=>
test=> select * from INFORMATION_SCHEMA.role_table_grants where table_catalog = 'test' and grantee = 'ceshi'
test-> ;
grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy
---------+---------+---------------+--------------+------------+----------------+--------------+----------------
ceshi | ceshi | test | public | test | INSERT | YES | NO
ceshi | ceshi | test | public | test | SELECT | YES | YES
ceshi | ceshi | test | public | test | UPDATE | YES | NO
ceshi | ceshi | test | public | test | DELETE | YES | NO
ceshi | ceshi | test | public | test | TRUNCATE | YES | NO
ceshi | ceshi | test | public | test | REFERENCES | YES | NO
ceshi | ceshi | test | public | test | TRIGGER | YES | NO
(7 rows)
schema權限
GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
ON SCHEMA schema_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
包括允許查看schema中的對象,允許在schema中創建對象
新建的schema只有超級用戶和owner有權限在該shcmea下查看或者新建對象
注意
According to the SQL standard, the owner of a schema always owns all objects within it. PostgreSQL allows schemas to contain objects owned by users other than the schema owner. This can happen only if the schema owner grants the CREATE privilege on his schema to someone else, or a superuser chooses to create objects in it.
schema的owner默認是該schema下的所有對象的owner。
同時PostgreSQL還允許用戶在別人的schema下創建對象(賦權后),所以一個對象可能屬於”兩個”owner。 更”糟糕”的是schema
的owner有 drop該schema下面的所有對象的權限。或者直接drop schema cascade來刪除整個schema.
test=# create role r1 login;
CREATE ROLE
test=# create role r2 login;
CREATE ROLE
test=# grant all on database test to r1;
GRANT
test=# grant all on database test to r2;
GRANT
test=# \c test r1
You are now connected to database "test" as user "r1".
test=> create schema r1;
CREATE SCHEMA
test=> grant all on schema r1 to r2;
GRANT
test=> \c test r2;
You are now connected to database "test" as user "r2".
test=> create table r1.t(id int);
CREATE TABLE
test=> \c test sa
You are now connected to database "test" as user "sa".
test=# create table r1.t1(id int);
CREATE TABLE
postgres=> \c test r1
You are now connected to database "test" as user "r1".
test=> drop table r1.t;
DROP TABLE
test=> drop table r1.t1;
DROP TABLE
上面的例子就是schema的owner刪除了其他賬號建的對象
對於database的owner也存在這個問題,它同樣具有刪除database中任何其他用戶創建的對象的權力。
postgres=# alter user r1 createdb;
ALTER ROLE
postgres=# \c postgres r1;
You are now connected to database "postgres" as user "r1".
postgres=> create database db1;
CREATE DATABASE
postgres=> grant all on database db1 to r2;
GRANT
postgres=> \c db1 r2
You are now connected to database "db1" as user "r2".
db1=> create schema r2;
CREATE SCHEMA
db1=> create table r2.t(id int);
CREATE TABLE
db1=> insert into t select generate_series(1,100);
INSERT 0 100
db1=> \c db1 sa
You are now connected to database "db1" as user "sa".
db1=# create table t(id int);
CREATE TABLE
db1=# insert into t select generate_series(1,100);
INSERT 0 100
db1=# \c db1 r1
You are now connected to database "db1" as user "r1".
db1=> drop table r2.t;
錯誤: 對模式 r2 權限不夠
db1=> drop table public.t;
錯誤: must be owner of table t
db1=> drop schema r2;
錯誤: 必須是模式 r2 的屬主
db1=> drop schema public;
錯誤: 必須是模式 public 的屬主
db1=> \c postgres r1
You are now connected to database "postgres" as user "r1".
postgres=> drop database db1;
DROP DATABASE
owner雖然不能刪除database下面其他用戶創建的schema和表,但是可以直接刪除database
所以要么開始就各個數據庫各自管理,不要將混合起來管理。另外一個辦法就是database和schema有創建等權限,但是普通用戶只有對象的讀寫等權限
owner能否訪問其他用戶創建的表數據呢?
postgres=> \c test r2;
You are now connected to database "test" as user "r2".
test=> create table r1.t(id int);
CREATE TABLE
test=> insert into r1.t select generate_series(1,100);
INSERT 0 100
test=> \c test r1
You are now connected to database "test" as user "r1".
test=> select * from r1.t;
錯誤: permission denied for table t
用戶r1雖然是r1的owner但是卻沒有訪問其他用戶在該schema下面創建的對象的權限
public權限
public權限單獨處理,巡檢過程中為什么要回收public權限?
新創建的數據庫都有一個public的schema,正常情況下,普通用戶創建的表都在public下面。默認情況下普通用戶是有在public下創建表的權限。
--創建角色role_b
postgres=# create user role_b with password '123456';
CREATE ROLE
--賦予connect權限database
postgres=# grant connect on database postgres to role_b;
GRANT
postgres=# \c postgres role_b
psql (9.6.4, server 9.5.3)
You are now connected to database "postgres" as user "role_b".
--沒有創建schema權限
postgres=> create schema tbb;
ERROR: permission denied for database postgres
postgres=> select current_schema;
current_schema
----------------
public
(1 row)
--但是有創建表和刪除表的權限
postgres=> create table test1(id int);
CREATE TABLE
postgres=> drop table test1;
DROP TABLE
--回收schmea的public權限
postgres=> \c postgres sa
psql (9.6.4, server 9.5.3)
You are now connected to database "postgres" as user "sa".
postgres=# revoke all on schema public from public;
REVOKE
postgres=# \c postgres role_b
psql (9.6.4, server 9.5.3)
You are now connected to database "postgres" as user "role_b".
postgres=>
postgres=> create table test1(id int);
ERROR: no schema has been selected to create in
LINE 1: create table test1(id int);
object權限
用戶(user),角色(role),組(group)在pg中都是一個概念
create user是create role的一個別名,唯一的區別是create user中的login權限被作為默認值,而create role默認為nologin
public角色,代表所有人的意思
在數據庫權限新建的test庫,可以看到dual表的grantee為PUBLIC
test=> \c test sa
You are now connected to database "test" as user "sa".
test=# select * from INFORMATION_SCHEMA.role_table_grants where table_catalog = 'test' and table_name = 'dual' and grantee = 'PUBLIC';
grantor | grantee | table_catalog | table_schema | table_name | privilege_type | is_grantable | with_hierarchy
---------+---------+---------------+--------------+------------+----------------+--------------+----------------
sa | PUBLIC | test | public | dual | INSERT | NO | NO
sa | PUBLIC | test | public | dual | SELECT | NO | YES
sa | PUBLIC | test | public | dual | UPDATE | NO | NO
sa | PUBLIC | test | public | dual | DELETE | NO | NO
sa | PUBLIC | test | public | dual | TRUNCATE | NO | NO
sa | PUBLIC | test | public | dual | REFERENCES | NO | NO
sa | PUBLIC | test | public | dual | TRIGGER | NO | NO
(7 rows)
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
TO role_specification [, ...] [ WITH GRANT OPTION ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( column_name [, ...] )
[, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) }
ON [ TABLE ] table_name [, ...]
TO role_specification [, ...] [ WITH GRANT OPTION ]
新建用戶然后給表賦權限
test=> \c postgres sa
You are now connected to database "postgres" as user "sa".
postgres=# create table test(id int);
CREATE TABLE
postgres=# drop table test;
DROP TABLE
postgres=# create schema schema1;
CREATE SCHEMA
postgres=# set search_path=schema1;
SET
postgres=# create table schema1.test(id int);
CREATE TABLE
postgres=# insert into schema1.test select generate_series(1,10);
INSERT 0 10
postgres=#
postgres=# create role role_a with password '123456' login;
CREATE ROLE
--直接grant database后是沒有權限訪問下面的表的
postgres=# grant all on database postgres to role_a;
GRANT
postgres=# \c postgres role_a
You are now connected to database "postgres" as user "role_a".
postgres=> select * from schema1.test;
錯誤: 對模式 schema1 權限不夠
LINE 1: select * from schema1.test;
^
--all tables in schema還是不行
postgres=> \c postgres sa
You are now connected to database "postgres" as user "sa".
postgres=# grant select on all tables in schema schema1 to role_a;
GRANT
postgres=# \c postgres role_a
You are now connected to database "postgres" as user "role_a".
postgres=> select * from schema1.test;
錯誤: 對模式 schema1 權限不夠
LINE 1: select * from schema1.test;
^
--on schema后能正常訪問
postgres=> \c postgres sa
You are now connected to database "postgres" as user "sa".
postgres=# grant all on schema schema1 to role_a;
GRANT
postgres=# \c postgres role_a
You are now connected to database "postgres" as user "role_a".
postgres=> select * from schema1.test limit 1;
id
----
1
(1 row)
回收掉all tables in schema權限后,role_a便不能查詢該表
postgres=> \c postgres sa
You are now connected to database "postgres" as user "sa".
postgres=# revoke all on all tables in schema schema1 from role_a;
REVOKE
postgres=# \c postgres role_a;
You are now connected to database "postgres" as user "role_a".
postgres=> select * from schema1.test limit 1;
錯誤: permission denied for table test
如果用普通賬號回收權限會報下面的警告
postgres=> select current_user;
current_user
--------------
role_a
(1 row)
postgres=> revoke select on all tables in schema schema1 from role_a cascade;
警告: 不能為"test"撤銷權限
警告: 不能從關系"test"的列"tableoid"上撤銷權限
警告: 不能從關系"test"的列"cmax"上撤銷權限
警告: 不能從關系"test"的列"xmax"上撤銷權限
警告: 不能從關系"test"的列"cmin"上撤銷權限
警告: 不能從關系"test"的列"xmin"上撤銷權限
警告: 不能從關系"test"的列"ctid"上撤銷權限
警告: 不能從關系"test"的列"id"上撤銷權限
REVOKE
