MathJax

MathJax-2

MathJax-3

Google Code Prettify

置頂入手筆記

EnterproseDB Quickstart — 快速入門筆記

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

2019年5月9日 星期四

(安全的)在 PGSQL 11 裡面查看主機目錄內容

PGSQL 有提供一個函數 pg_ls_dir(),用來查看主機底下的目錄內容,一直以來
沒什麼太大用途的感覺。。不過,PGSQL 在 v11 幫這個函數導入一個新功能~
方便我們在綁手綁腳的情況底下(例如,僅能透過 pgAdmin 等 UI 看資料庫,不能
夠使用 SSH 登入主機進行管理、操作),一窺主機的狀況。

話先說在前頭,這個強效新特性是需要特殊權限才能操作,不要誤認成漏洞了~!


這邊用 Linux 上面的 EDB 企業版作示範(原生 PGSQL 也一樣適用)。

在 PGSQL 10 與之前的版本,pg_ls_dir() 是只有限制在查看資料目錄($PGDATA)
裡面的內容物,這之外的目錄是不能查看的。以下是 EDB 10 的狀況:
edb=# select version();
                                                   version                                                    
--------------------------------------------------------------------------------------------------------------
 EnterpriseDB 10.7.15 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36), 64-bit
(1 row)

edb=# -- DB Session 當前目錄就位在 $PGDATA 下,這邊以相對目錄語法 ./ 查看
edb=# select pg_ls_dir('.');
                pg_ls_dir                 
------------------------------------------
 pg_tblspc
 global
 pg_commit_ts
 pg_dynshmem
 pg_notify
 pg_serial
 pg_snapshots
 pg_subtrans
 pg_twophase
 pg_multixact
 base
 pg_replslot
 pg_stat
 pg_stat_tmp
 pg_xact
 pg_logical
 PG_VERSION
 postgresql.conf
 postgresql.auto.conf
 pg_ident.conf
 log
 pg_hba.conf
 pg_wal
 postmaster.opts
 dbms_pipe
 postmaster.pid
 current_logfiles
 backup_label.old
 recovery.done
(29 rows)

edb=# -- 查看上一層目錄 ../
edb=# select pg_ls_dir('..');
ERROR:  path must be in or below the current directory
edb=# 

到了 PGSQL 11,pg_ls_dir() 的功能擴充了,只要使用足夠權限的帳號(DB Superuser 或是身處 pg_read_server_files 群組),開始可以看到 DB 運作的 OS 帳號可以觸碰的目錄內容了。以下是 EDB 11 的狀況:
edb=# select version();
                                                                    version                                                                    
-----------------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 11.1 (EnterpriseDB Advanced Server 11.1.7) on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16), 64-bit
(1 row)

edb=# select pg_ls_dir('.');
      pg_ls_dir       
----------------------
 pg_wal
 global
 pg_commit_ts
 pg_dynshmem
 pg_notify
 pg_serial
 pg_snapshots
 pg_subtrans
 pg_twophase
 pg_multixact
 base
 pg_replslot
 pg_tblspc
 pg_stat
 pg_stat_tmp
 pg_xact
 pg_logical
 PG_VERSION
 postgresql.auto.conf
 pg_ident.conf
 log
 postmaster.opts
 edb_wait_states
 traces
 pg_hba.conf
 postgresql.conf
 postmaster.pid
 dbms_pipe
 current_logfiles
(29 rows)

edb=# select pg_ls_dir('..');
   pg_ls_dir   
---------------
 backups
 data
 initdb.log
 archived_wals
(4 rows)

edb=# 

這個功能,可以處碰到的地方,以 DB Process Owner 可以觸及的目錄位置為限。以下示範去查看 /root 目錄內容,但是會被拒絕
edb=# select pg_ls_dir('/root');
ERROR:  could not open directory "/root": Permission denied
edb=# 

從這可以看到,這就是為什麼 PostgreSQL 不允許用 root 帳號去啟動資料庫的理由了。


允許這樣查看的 DB 帳號,需要是 pg_read_server_files 這個群組的成員才行。不然,就還是舊版的行為,只能檢視資料目錄裡面的內容物。

這邊直接建立一個普通帳號來觀察:
edb=# \du
                                         List of roles
       Role name       |                         Attributes                         | Member of 
-----------------------+------------------------------------------------------------+-----------
 aaa                   | Profile default                                            | {}
 aq_administrator_role | No inheritance, Cannot login                              +| {}
                       | Profile default                                            | 
 enterprisedb          | Superuser, Create role, Create DB, Replication, Bypass RLS+| {}
                       | Profile default                                            | 

edb=# \c edb aaa
You are now connected to database "edb" as user "aaa".
edb=> select pg_ls_dir('..');
ERROR:  permission denied for function pg_ls_dir
edb=> select pg_ls_dir('.');
ERROR:  permission denied for function pg_ls_dir
edb=> 

就算是不小心把這個函數的執行權限賦予帳號 aaa,也是看不到 $PGDATA 的外面
edb=# \df pg_ls_dir
                             List of functions
   Schema   |   Name    | Result data type |  Argument data types   | Type 
------------+-----------+------------------+------------------------+------
 pg_catalog | pg_ls_dir | SETOF text       | text                   | func
 pg_catalog | pg_ls_dir | SETOF text       | text, boolean, boolean | func
(2 rows)

edb=# 
edb=# grant EXECUTE on FUNCTION pg_ls_dir(text) to aaa ;
GRANT
edb=# grant EXECUTE on FUNCTION pg_ls_dir(text,boolean,boolean) to aaa ;
GRANT
edb=# \c edb aaa
You are now connected to database "edb" as user "aaa".
edb=> select pg_ls_dir('.');
      pg_ls_dir       
----------------------
 pg_wal
 global
 pg_commit_ts
 pg_dynshmem
 pg_notify
 pg_serial
 pg_snapshots
 pg_subtrans
 pg_twophase
 pg_multixact
 base
 pg_replslot
 pg_tblspc
 pg_stat
 pg_stat_tmp
 pg_xact
 pg_logical
 PG_VERSION
 postgresql.auto.conf
 pg_ident.conf
 log
 postmaster.opts
 edb_wait_states
 traces
 pg_hba.conf
 postgresql.conf
 postmaster.pid
 dbms_pipe
 current_logfiles
(29 rows)

edb=> 
edb=> select pg_ls_dir('..');
ERROR:  path must be in or below the current directory
edb=> 



所以,有適當的帳戶管理的狀況下,這是不用困擾的。


若是在無法以 SSH 登入主機的情況,這功能在檢查環境與異常問題還蠻重要的~
一個實際的案例,就是檢查 WAL 備份目錄的存取權限:如果沒有辦法存取,會在 pg_stat_archiver 出現 failed  arhcived WAL 的狀態。


在 PGSQL 11 版,還有其他功能比較強大的群組,用來擴增應用、管理的彈性。不過,事情總是有好有壞:有了這些比較強效的功能,就更需要注意帳戶管理以及 HBA 控制,免得好功能變成被鑽的漏洞,那就麻煩了。


參考資料
以下是這陣子很流行的假訊息(虛實參雜)的紀錄:事後官方有澄清了喔


沒有留言:

張貼留言