MathJax

MathJax-2

MathJax-3

Google Code Prettify

置頂入手筆記

EnterproseDB Quickstart — 快速入門筆記

由於考慮採用 EnterpriseDB 或是直接用 PostgreSQL 的人,通常需要一些入手的資料。這邊紀錄便提供相關快速上手的簡單筆記 ~ 這篇筆記以 資料庫安裝完畢後的快速使用 為目標,基本紀錄登入使用的範例:

2017年9月19日 星期二

在 Postgres 透過 SET ROLE 實現類似 sudoer 的功能

Postgres 裡面的有絕對控制權的帳戶權限叫做 Superuser。一般在 Postgres 預設狀況下,除非特別指定,執行 initdb 的作業系統帳戶會擁有因此產生的 Postgres 資料庫服務(Postgres instance),並且預設資料庫內的同名帳戶是資料庫的 Superuser。

不過通常都以預設的配置,產生出以 postgres(企業版為 enterprisedb)為 Superuser 的資料庫服務。

除了預設的 Superuser 帳戶之外,Superuser 的權限也可以手動賦予其他新的資料庫帳戶。

更進一步,甚至可以類似 Linux 底下的 sudo 功能,使一個一般帳戶加入一個「Superuser 群組」:平常這些帳戶不能執行 Superuser 權限的動作;但在必要時,便能類似 sudo 一樣,切換身份,暫時成為 Superuser。

那要怎麼設定呢?

在 Postgres 中的帳戶系統中,資料庫這些物件都稱作角色(role);並且可以將角色(role)進一部分成群組(group)和帳戶(user)
群組這種資料庫腳色不能登入,在建立時可以用 NOLOGIN 來設定
postgres=# CREATE ROLE my_superuser SUPERUSER NOLOGIN;

嘗試登入會被禁止,就算 pg_hba.conf 中允許也一樣
postgres=# \c postgres my_superuser
FATAL:  role "my_superuser" is not permitted to log in
Previous connection kept

接著是一般帳戶的建立,以及加入群組。通常一個帳戶可以繼承多個角色,也就是可以加入多個群組的意思(Note:一般帳戶也可以被繼承~)。一般的權限劃上,我們可以使帳戶繼承某些群組,然後在群組上作 GRANT/REVOKE,這麼一來,就不用逐一針對個別帳戶,一個個去配置權限,達到簡化帳戶權限管理的功能。

以下便建立一個普通帳戶,使它加入上面所建立的群組:
postgres=# CREATE USER usual_admin IN ROLE my_superuser NOINHERIT;

現在可見,共有三個帳戶了
postgres=# \du
                                    List of roles
  Role name   |                      Attributes                         |   Member of    
--------------+------------------------------------------------------------+----------------
 my_superuser | Superuser, Cannot login                                    | {}
 postgres     | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 usual_admin  | No inheritance                                             | {my_superuser}

接著登入這個一般帳戶
postgres=# \c postgres usual_admin
You are now connected to database "postgres" as user "usual_admin".
postgres=>

然後開始進行測試。我們利用 pg_shadow 這個系統表的存取來示範。一般狀況下,不是 Superuser 沒辦法存取這個表格,因為這個表格記載帳號密碼資訊。
postgres=> \c
You are now connected to database "postgres" as user "usual_admin".
postgres=> select * from pg_shadow;
ERROR:  permission denied for relation pg_shadow

上面顯示,一般狀況下,普通帳戶沒辦法存取 pg_shadow。接著我們便要暫時切換成 Superuser 來存取 pg_shadow。

我們示範 SET ROLE 指令,分別切換當前帳戶為資料庫內建的 Superuser 或成為他所屬群組來作比較。以下所示,目前帳戶沒有繼承預設的 Superuser,因此不能切換過去。然而可以切換到剛剛建立的 Superuser 群組
postgres=> SET ROLE postgres;
ERROR:  permission denied to set role "postgres"
postgres=> SET ROLE my_superuser;
SET
postgres=# SELECT session_user, current_user;
 session_user | current_user
--------------+--------------
 usual_admin  | my_superuser
(1 row)
 
postgres=# select * from pg_shadow;
   usename   | usesysid | usecreatedb | usesuper | userepl | usebypassrls | passwd | valuntil | useconfig
-------------+----------+-------------+----------+---------+--------------+--------+----------+-----------
 postgres    |       10 | t           | t        | t       | t            |        |          |
 usual_admin | 16386   | f           | f        | f       | f            |        |          |
(2 rows)
 
postgres=# 

上面查詢了兩個參數,session_user 與 current_user,分別顯示原本這個 Session 的帳戶,以及目前取得的帳戶身份(也就是群組)。我們可以看到這樣會直接切換成 my_superuser 來執行。要中止的話,可以用 RESET ROLE
postgres=# SELECT session_user, current_user;
 session_user | current_user
--------------+--------------
 usual_admin  | my_superuser
(1 row)
 
postgres=# RESET ROLE;
RESET
postgres=> SELECT session_user, current_user;
 session_user | current_user
--------------+--------------
 usual_admin  | usual_admin
(1 row)

由上對照可見,session role 仍然一樣,只是執行時的 current role 的暫時變動,以取得相關帳戶的執行權限。


有了這種類似 Sudo 的功能,我們就能放心的在 pg_hba.conf 中「凍結」預設 Superuser 的登入,避免不必要的直接登入、使用,降低被攻擊的可能(因為十之八九都是 port 5432 搭配 postgres Superuser,或是 port 5444 搭配 enterprisedb Superuser);一般管理者也能在必要時用自己的帳戶執行 Superuser 指令,又可以減低因為手殘而誤打指令的風險。

可惜的是,在 SET ROLE 時,沒辦法再跳出打密碼確認的功能,因為在 Postgres 登入認證(Authentication)完畢後,就已經是合法的連線,不會再因為特定 SQL 指令而要求用密碼確認權限(Authorisation)。這樣比較像是 No Password Sudoer~

最後一提,SET SESSION AUTHORIZATION 是另一種不一樣的行為:這個指令是從 Superuser 暫時降階到比較普通權限的帳戶。由於該指令能夠連 session 的帳戶都暫且變更掉(請直接參考手冊內範例),相當於重新用其他帳號登入資料庫,這與 SET ROLE 是不一樣的行為。


參考資料:

沒有留言:

張貼留言