2022年4月8日 星期五

Postgres 資料庫帳號權限管理與 Default Privilege


這次來分享如何在 PostgreSQL 上進行權限管控。

PostgreSQL 主要的權限管控為以下五個,都是針對 User 所擁有的權限進行管控:

pg_hba 規則、資料庫全域的權限、Database 權限、Schema 權限、Objects 權限

下面會針對這些權限的管理進行介紹。



1. pg_hba 規則:

資料庫內部防火牆,管控使用者能從哪個 IP 進行登入那些資料庫,僅透過設定檔進行管控,並非資料庫內部權限。

此規則設定在資料庫目錄下設定檔案  $PGDATA/pg_hba.conf

下面為一個簡單的範例,使用者在登入的時候必須要符合下面條件才可進行登入,規則由上往下檢查需要注意順序,調整完設定後會許要執行 Reload 來生效,若是使用者登入時報錯 no pg_hba.conf entry 代表著 pg_hba 規則可能有寫錯或漏寫。

注意此檔案若有填寫錯誤可能導致資料庫無法正常啟動。

TYPE:

可選擇 local 或是 host。

local 代表著透過本地的 socket 進行連線,若選擇 local 則不需要設置 ADDRESS,通常為本地 psql 等指令工具連入資料庫使用。

host 代表著透過網路進行連線登入。

DATABASE:

可登入的資料庫,replication 為 replication 同步與pg_basebackup等備份相關的連線會需要額外開啟的規則。

USER:

可登入的 User。

ADDRESS:

允許連線的來源 IP 或是 hostname,若使指定 IP 必須要完整填寫網路遮罩不然不會生效。

METHOD:

登入的驗證方法,主要常見的有以下幾種

peer:從本地登入時,會驗證登入的 DB User 與 OS User 名稱是否相同,若相同則允許登入。

trust:信任,無須驗證即可登入。

md5/scram-sha-256:驗證密碼登入,在比較新的版本預設都使用 scram-sha-256 為較安全驗證方式,除非 AP 端連線程式無法支援不然建議使用此方法,需注意資料庫內密碼的加密方式(password_encryption)需要對應,注意如果有修改密碼的加密方式,需要重新 alter password 才會將原本的密碼修改為新的加密方式。

另外也支援使用 SSL 和 LADP 等驗證方式,這兩個會需要額外進行設置。


2. 資料庫全域的權限:

使用者是否為 Superuser,是否可登入等等。 

透過 \du 進行查詢,另外透過系統表 pg_roles 可以查看詳細資訊。

一般使用者擁有的權限為 Profile default (inherhit, canlogin)

其餘依據需求給予 Superuser、Replication 等等權限,另外 Cannot Login 的 User 可以做為 role(group) 的角色進行權限管控。



3. Database 權限:

三種權限類型,透過 \l 以及查詢系統表 pg_database 可檢視

C:Create Schema

T:Create TEMPORARY Table

c:Connect to database

這邊簡單說明一下 Access Privileges 如何解讀,在 Schema 以及 Objects 也是相同解讀方式。

被授予權限的帳號 =擁有權限 / 授予此權限的人

每一行代表著一條規則,

以 =c/enterprisedb 為例,前面留空代表著 PUBLIC (所有使用者),c 代表著這些帳號可以連線,最後的 enterprisedb 代表此權限是 enterprisedb 所授予的。

補充:此處是 User 對於 Database 的權限,Database 本身另外有設定可以管控是否能登入,像是 template0 就是不可登入的資料庫,除非有特殊維運需求也不建議調整開啟登入,另外 template1 是模板資料庫,執行 CREATE DATABASE 的時候都會從 template1 複製出來。


4. Schema 權限:

透過 \dn+ 可以檢視整體狀況,以及檢視系統表 pg_namespace 查看詳細資訊


有兩種權限類型

U:USAGE 對 Schema 內物件的存取權限,但還要有對應物件的權限才能進行相關查詢

C:CREATE 允許在 Schema 下建立新物件,例如 Table、Function、Procedure 等


Create 權限允許在該 Schema 下創建 Table 等物件與刪除自己擁有的 Table 物件,不能刪除別人擁有的 Table 物件。

但有一種特殊的情況,Schema Owner 預設沒有權限訪問別人的創建的 Table ,但是可以刪除別人創建的 Table。

預設所有使用者擁有 public Schema 的 CREATE + USAGE 權限,預計在 PostgreSQL 15 開始會改成預設所有使用者擁有 public Schema 的 USAGE 權限。



5. Objects 權限:

透過 \dp 查看目前 search_path 下有能看到的表格 (必須要有 Schema USAGE 權限)

補充對 search_path  進行說明,search_path 表列目前連線所能看到的 Schema,透過調整 search_path 可以方便檢視不同 Schema 下的物件內容,不在 search_path 匡列範圍內的 Schema 底下物件依然可以透過 schema.table 的方式進行存取。

下面列出幾種權限類型 arwdDxtX

a:INSERT

r:SELECT

w:UPDATE

d:DELETE

D:TRUNCATE

x:REFERENCES -- allow create Foreign Key 

t:TRIGGER

X:Execute

此處提醒需要注意到,預設情況下,當一個 Function/Procedure 被建立的時候,所有 User 都擁有執行此 SP 的權限(需要有該 Schema 的 USAGE 權限才能看到此 SP ),但如果 SP 內有使用到一些物件有權限不足依然會執行失敗,如果想要避免這樣的行為就需要透過 Schema USAGE 權限或是調整 Default Privilege 來改變。


6. 額外補充

除了上面列出幾個比較重要的權限,另外還有些分別的物件會需要管理權限,像是 Tablespace、Language、Foreign Server 等等,以及特定物件像是 Database 會有自己的屬性控制能不能使用/登入等等。

其中關於 Tablspace 權限,此權限只影響使用者是否能在此 tablspace 下建立物件,不影響 DML 操作,其中有一點比較特別的是,所有使用者預設會擁有該連線 Database 的 default_tablespace 的使用權限。


7. Predifined roles (https://www.postgresql.org/docs/14/predefined-roles.html)

在 PostgreSQL 中 User 和 Role 是完全一樣的,只是在管理上的概念會有區分,一般 User 指會登入的使用者,role 用來指管控權限的群組,可透過 grant role_A to user_B 的方式來將特定帳號所擁有的權限賦予給其他人,藉此能做到統一管理權限,將一個設定好權限的 user 權限 grant 給許多人進行管控。

在 PostgreSQL 中有一些預設的 role 可使用,在舊版本稱為 default roles,從 PostgreSQL 14 開始改稱為 Predifined roles,這些 role 可以幫助我們較方便的賦予一些管理權限。

像是在 PostgreSQL 14 開始新增以下兩個重要的 role:

pg_read_all_data:能讀取所有資料。

pg_write_all_data:能寫入任何表格。

在此之間只能透過手動賦予全部表格權限的方式來達成,或是透過調整 Default Privilege 權限來達成,但都需要一定的成本來達到。


8. Default Privilege (https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)

PostgreSQL 中可以設定預設建立的物件權限,此處不多介紹可以參考手冊語法說明,僅提醒注意此設定僅能 By User 進行設定,若有多個帳號有此需求必須個別設定,因此使用上還是有一定的困難在。

可以透過一些兜 SQL 的方式來達到快速調整所有帳號預設權限。

select format('alter default privileges for role %s revoke execute on functions from PUBLIC;',rolname) from pg_roles where rolcanlogin = 't';

\gexec