2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1

F.40. sepgsql — 基於 SELinux 標籤的強制訪問控制 (MAC) 安全模組 #

sepgsql 是一個可載入模組,它支援基於 SELinux 安全策略的標籤式強制訪問控制 (MAC)。

警告

當前實現存在顯著限制,並且不能強制執行所有操作的強制訪問控制。請參閱 第 F.40.7 節

F.40.1. 概述 #

該模組與 SELinux 整合,在 PostgreSQL 通常提供的安全檢查之上增加了額外的安全層。從 SELinux 的角度來看,該模組允許 PostgreSQL 作為使用者空間物件管理器執行。透過 DML 查詢發起的每個表或函式訪問都會根據系統的安全策略進行檢查。此檢查是 PostgreSQL 執行的常規 SQL 許可權檢查的補充。

SELinux 訪問控制決策是使用安全標籤做出的,這些標籤表示為字串,例如 system_u:object_r:sepgsql_table_t:s0。每個訪問控制決策都涉及兩個標籤:嘗試執行操作的主體的標籤,以及要執行操作的物件的標籤。由於這些標籤可以應用於任何型別的物件,因此儲存在資料庫內的物件的訪問控制決策可以(並且使用此模組,已經被)受到與任何其他型別物件(如檔案)相同的通用標準。此設計旨在允許一個集中的安全策略保護資訊資產,而不考慮這些資產的儲存方式。

SECURITY LABEL 語句允許將安全標籤分配給資料庫物件。

F.40.2. 安裝 #

sepgsql 只能在啟用 SELinuxLinux 2.6.28 或更高版本上使用。在任何其他平臺上均不可用。您還需要 libselinux 2.1.10 或更高版本以及 selinux-policy 3.9.13 或更高版本(儘管某些發行版可能會將必要的規則回溯到較舊的策略版本)。

sestatus 命令允許您檢查 SELinux 的狀態。典型的顯示如下:

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

如果 SELinux 已停用或未安裝,您必須先設定該產品,然後才能安裝此模組。

要構建此模組,請在配置 PostgreSQL 時指定 --with-selinux(使用 make 和 autoconf 時)或 -Dselinux={ auto | enabled | disabled }(使用 Meson 時)。請確保在構建時已安裝 libselinux-devel RPM。

要使用此模組,您必須在 postgresql.confshared_preload_libraries 引數中包含 sepgsql。如果以任何其他方式載入該模組,它將無法正常工作。模組載入後,您應該在每個資料庫中執行 sepgsql.sql。這將安裝安全標籤管理所需的功能,並分配初始安全標籤。

這是一個示例,展示瞭如何使用安裝的 sepgsql 函式和安全標籤來初始化一個新的資料庫叢集。請根據您的安裝情況調整顯示的路徑。

$ export PGDATA=/path/to/data/directory
$ initdb
$ vi $PGDATA/postgresql.conf
  change
    #shared_preload_libraries = ''                # (change requires restart)
  to
    shared_preload_libraries = 'sepgsql'          # (change requires restart)
$ for DBNAME in template0 template1 postgres; do
    postgres --single -F -c exit_on_error=true $DBNAME \
      </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
  done

請注意,根據您使用的 libselinuxselinux-policy 的特定版本,您可能會看到以下一個或多個通知。

/etc/selinux/targeted/contexts/sepgsql_contexts:  line 33 has invalid object type db_blobs
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 36 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 37 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 38 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 39 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 40 has invalid object type db_language

這些訊息是無害的,應予以忽略。

如果安裝過程沒有錯誤地完成,您現在可以正常啟動伺服器。

F.40.3. 迴歸測試 #

如果 PG_TEST_EXTRA 包含 sepgsql(請參閱 第 31.1.3 節),則會執行 sepgsql 測試套件。此方法適用於 PostgreSQL 的開發過程中。或者,有一種方法可以執行測試來檢查資料庫例項是否已正確設定 sepgsql

鑑於 SELinux 的性質,執行 sepgsql 的迴歸測試需要幾個額外的配置步驟,其中一些必須以 root 身份完成。

手動測試必須在已配置的 PostgreSQL 構建樹的 contrib/sepgsql 目錄中執行。雖然它們需要構建樹,但測試設計用於針對已安裝的伺服器執行,也就是說,它們類似於 make installcheck 而不是 make check

首先,根據 第 F.40.2 節 中的說明,在工作資料庫中設定 sepgsql。請注意,當前的作業系統使用者必須能夠以超級使用者身份無密碼連線到資料庫。

其次,構建並安裝回歸測試的策略包。 sepgsql-regtest 策略是一個專用策略包,它提供了一組在迴歸測試期間允許的規則。它應從策略原始檔 sepgsql-regtest.te 構建,使用 SELinux 提供的 Makefile 來完成。您需要找到系統中合適的 Makefile;下面顯示的路徑僅為示例。(此 Makefile 通常由 selinux-policy-develselinux-policy RPM 提供。)構建完成後,使用 semodule 命令安裝此策略包,該命令會將提供的策略包載入到核心中。如果包已正確安裝,semodule -l 應將 sepgsql-regtest 列為可用的策略包。

$ cd .../contrib/sepgsql
$ make -f /usr/share/selinux/devel/Makefile
$ sudo semodule -u sepgsql-regtest.pp
$ sudo semodule -l | grep sepgsql
sepgsql-regtest 1.07

第三,開啟 sepgsql_regression_test_mode。出於安全原因,sepgsql-regtest 中的規則預設不啟用;sepgsql_regression_test_mode 引數會啟用啟動迴歸測試所需的規則。可以使用 setsebool 命令將其開啟。

$ sudo setsebool sepgsql_regression_test_mode on
$ getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on

第四,驗證您的 shell 是否在 unconfined_t 域中執行。

$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

如果需要,請參閱 第 F.40.8 節 以瞭解調整工作域的詳細資訊。

最後,執行迴歸測試指令碼。

$ ./test_sepgsql

此指令碼將嘗試驗證您是否已正確完成所有配置步驟,然後它將執行 sepgsql 模組的迴歸測試。

完成測試後,建議您停用 sepgsql_regression_test_mode 引數。

$ sudo setsebool sepgsql_regression_test_mode off

您可能更傾向於完全刪除 sepgsql-regtest 策略。

$ sudo semodule -r sepgsql-regtest

F.40.4. GUC 引數 #

sepgsql.permissive (boolean) #

此引數使 sepgsql 能夠以允許模式執行,無論系統設定如何。預設值為關閉。此引數只能在 postgresql.conf 檔案或伺服器命令列中設定。

當此引數開啟時,即使 SELinux 通常處於強制模式,sepgsql 也會以允許模式執行。此引數主要用於測試目的。

sepgsql.debug_audit (boolean) #

此引數會強制列印審計訊息,無論系統策略設定如何。預設值為關閉,這意味著訊息將根據系統設定進行列印。

SELinux 的安全策略也包含規則來控制特定訪問是否被記錄。預設情況下,會記錄訪問違規,但不記錄允許的訪問。

此引數強制開啟所有可能的日誌記錄,無論系統策略如何。

F.40.5. 功能 #

F.40.5.1. 受控制的物件類別 #

SELinux 的安全模型將所有訪問控制規則描述為主體實體(通常是資料庫的客戶端)和物件實體(例如資料庫物件)之間的關係,每個實體都由一個安全標籤標識。如果嘗試訪問未標記的物件,則該物件將被視為分配了 unlabeled_t 標籤。

當前,sepgsql 允許將安全標籤分配給模式、表、列、序列、檢視和函式。當使用 sepgsql 時,支援的資料庫物件在建立時會自動分配安全標籤。此標籤稱為預設安全標籤,根據系統安全策略決定,該策略以建立者的標籤、分配給新物件父物件的標籤以及可選的物件名稱作為輸入。

一個新的資料庫物件基本上繼承了父物件(例如,對於模式,父物件是當前資料庫;對於表、序列、檢視和函式,它是包含它們的模式;對於列,它是包含它們的表)的安全標籤,除非安全策略有特殊的規則(稱為型別轉換規則),在這種情況下可能會應用不同的標籤。

F.40.5.2. DML 許可權 #

對於表,會根據語句的型別檢查所有引用的目標表的 db_table:selectdb_table:insertdb_table:updatedb_table:delete;此外,對於包含在 WHERERETURNING 子句中引用的所有表,也會檢查 db_table:select,作為 UPDATE 等的 DML 資料來源。

還會對每個引用的列檢查列級別的許可權。 db_column:select 會在不僅讀取的列(使用 SELECT),還包括在其他 DML 語句中引用的列上進行檢查;db_column:updatedb_column:insert 也會在由 UPDATEINSERT 修改的列上進行檢查。

例如,考慮以下語句:

UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100;

在此,db_column:update 將在 t1.x 上進行檢查,因為它正在被更新;db_column:{select update} 將在 t1.y 上進行檢查,因為它被更新和引用;db_column:select 將在 t1.z 上進行檢查,因為它僅被引用。 db_table:{select update} 也將在表級別進行檢查。

對於序列,當使用 SELECT 引用序列物件時,會檢查 db_sequence:get_value;但是請注意,我們目前不檢查執行相應函式(如 lastval())的許可權。

對於檢視,將檢查 db_view:expand,然後將單獨檢查檢視展開的物件的其他所需許可權。

對於函式,當用戶嘗試作為查詢的一部分執行函式或使用快速路徑呼叫時,將檢查 db_procedure:{execute}。如果該函式是受信任的過程,它還會檢查 db_procedure:{entrypoint} 許可權,以確定它是否可以作為受信任過程的入口點。

為了訪問任何模式物件,需要在包含模式上擁有 db_schema:search 許可權。當在沒有模式限定的情況下引用物件時,沒有此許可權的模式將不會被搜尋(就像使用者沒有模式的 USAGE 特權一樣)。如果存在顯式的模式限定,當用戶對指定模式沒有所需許可權時,將發生錯誤。

客戶端必須能夠訪問所有引用的表和列,即使它們來自稍後被展開的檢視,這樣我們才能應用與引用表內容的方式無關的一致訪問控制規則。

預設的資料庫特權系統允許資料庫超級使用者使用 DML 命令修改系統目錄,並引用或修改 toast 表。當啟用 sepgsql 時,這些操作是被禁止的。

F.40.5.3. DDL 許可權 #

SELinux 為每種物件型別定義了幾個許可權來控制常見操作;例如,建立、修改、刪除和重新標記安全標籤。此外,幾種物件型別具有特殊許可權來控制其特徵操作;例如,在特定模式中新增或刪除名稱條目。

建立新資料庫物件需要 create 許可權。 SELinux 將根據客戶端的安全標籤和新物件的建議安全標籤來授予或拒絕此許可權。在某些情況下,還需要額外的特權。

  • CREATE DATABASE 此外還需要源資料庫或模板資料庫的 getattr 許可權。

  • 建立模式物件需要對父模式的 add_name 許可權。

  • 建立表需要建立每個單獨表列的許可權,就像每個表列都是獨立的頂層物件一樣。

  • 建立標記為 LEAKPROOF 的函式需要 install 許可權。(當為現有函式設定 LEAKPROOF 時,也會檢查此許可權。)

當執行 DROP 命令時,將檢查被刪除物件上的 drop 許可權。對於透過 CASCADE 間接刪除的物件,也會檢查許可權。刪除特定模式內的物件(表、檢視、序列和過程)還需要模式上的 remove_name 許可權。

當執行 ALTER 命令時,對於每種物件型別,都將在被修改物件上檢查 setattr,但對於表等物件的輔助物件(如索引或觸發器),許可權將改為在父物件上檢查。在某些情況下,需要額外的許可權。

  • 將物件移動到新模式需要舊模式的 remove_name 許可權和新模式的 add_name 許可權。

  • 設定函式的 LEAKPROOF 屬性需要 install 許可權。

  • 對物件使用 SECURITY LABEL 還需要物件與其舊安全標籤結合的 relabelfrom 許可權,以及物件與其新安全標籤結合的 relabelto 許可權。(在安裝了多個標籤提供者並且使用者嘗試設定安全標籤,但該標籤未被 SELinux 管理的情況下,此處應只檢查 setattr。由於實現限制,目前尚未實現。)

F.40.5.4. 受信任的過程 #

受信任的過程類似於安全定義函式或 setuid 命令。 SELinux 提供了一項功能,允許受信任的程式碼使用不同於客戶端的安全標籤執行,通常是為了提供對敏感資料的嚴格控制訪問(例如,可能會省略行,或者儲存值的精度可能會降低)。函式是否充當受信任的過程由其安全標籤和作業系統安全策略控制。例如:

postgres=# CREATE TABLE customer (
               cid     int primary key,
               cname   text,
               credit  text
           );
CREATE TABLE
postgres=# SECURITY LABEL ON COLUMN customer.credit
               IS 'system_u:object_r:sepgsql_secret_table_t:s0';
SECURITY LABEL
postgres=# CREATE FUNCTION show_credit(int) RETURNS text
             AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
                        FROM customer WHERE cid = $1'
           LANGUAGE sql;
CREATE FUNCTION
postgres=# SECURITY LABEL ON FUNCTION show_credit(int)
               IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL

上述操作應由管理員使用者執行。

postgres=# SELECT * FROM customer;
ERROR:  SELinux: security policy violation
postgres=# SELECT cid, cname, show_credit(cid) FROM customer;
 cid | cname  |     show_credit
-----+--------+---------------------
   1 | taro   | 1111-2222-3333-xxxx
   2 | hanako | 5555-6666-7777-xxxx
(2 rows)

在這種情況下,普通使用者無法直接引用 customer.credit,但受信任的過程 show_credit 允許使用者列印客戶的信用卡號碼,其中部分數字已遮蔽。

F.40.5.5. 動態域轉換 #

如果安全策略允許,可以使用 SELinux 的動態域轉換功能將客戶端程序(客戶端域)的安全標籤切換到新的上下文。

應仔細考慮動態域轉換,因為它們允許使用者根據自己的選擇切換其標籤,從而切換其許可權,而不是(如受信任的過程那樣)由系統強制執行。因此,僅當用於切換到許可權集小於原始集的域時,dyntransition 許可權才被認為是安全的。例如:

regression=# select sepgsql_getcon();
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
 sepgsql_setcon
----------------
 t
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
ERROR:  SELinux: security policy violation

在上例中,我們被允許從較大的 MCS 範圍 c1.c1023 切換到較小的範圍 c1.c4,但切換回被拒絕。

動態域轉換和受信任過程的組合啟用了一個有趣的使用場景,該場景符合連線池軟體典型的程序生命週期。即使您的連線池軟體不允許執行大多數 SQL 命令,您也可以允許它透過受信任過程中的 sepgsql_setcon() 函式來切換客戶端的安全標籤;這需要一些憑據來授權切換客戶端標籤的請求。之後,此會話將擁有目標使用者的特權,而不是連線池器的特權。連線池器稍後可以透過再次使用 sepgsql_setcon() 並將引數設定為 NULL 來恢復安全標籤更改,同樣從受信任的過程(具有適當的許可權檢查)中呼叫。關鍵在於,只有受信任的過程實際上有權更改有效安全標籤,並且僅在獲得適當的憑據時才這樣做。當然,為了安全執行,憑據儲存(表、過程定義或任何其他內容)必須受到保護,免受未經授權的訪問。

F.40.5.6. 雜項 #

我們全面拒絕 LOAD 命令,因為任何載入的模組都可能輕易規避安全策略的執行。

F.40.6. Sepgsql 函式 #

表 F.32 顯示了可用的函式。

表 F.32. Sepgsql 函式

函式

描述

sepgsql_getcon () → text

返回客戶端域,即客戶端的當前安全標籤。

sepgsql_setcon ( text ) → boolean

如果安全策略允許,將當前會話的客戶端域切換到新域。它還接受 NULL 輸入,作為切換到客戶端原始域的請求。

sepgsql_mcstrans_in ( text ) → text

如果 mcstrans 守護程序正在執行,則將給定的合格 MLS/MCS 範圍轉換為原始格式。

sepgsql_mcstrans_out ( text ) → text

如果 mcstrans 守護程序正在執行,則將給定的原始 MLS/MCS 範圍轉換為合格格式。

sepgsql_restorecon ( text ) → boolean

為當前資料庫中的所有物件設定初始安全標籤。引數可以是 NULL,或者是一個用作系統預設值替代的 specfile 的名稱。


F.40.7. 限制 #

資料定義語言 (DDL) 許可權

由於實現限制,某些 DDL 操作不檢查許可權。

資料控制語言 (DCL) 許可權

由於實現限制,DCL 操作不檢查許可權。

行級訪問控制

PostgreSQL 支援行級訪問,但 sepgsql 不支援。

隱蔽通道

sepgsql 不會嘗試隱藏某個物件的存在,即使使用者不允許引用它。例如,由於主鍵衝突、外部索引鍵違規等原因,我們可以推斷出不可見物件的存在,即使我們無法獲取物件的內容。絕密表的名稱無法隱藏;我們只希望隱藏其內容。

F.40.8. 外部資源 #

SE-PostgreSQL 簡介

此 wiki 頁面提供了一個簡要概述、安全設計、架構、管理和即將推出的功能。

SELinux 使用者和管理員指南

本文件提供了廣泛的知識來管理您系統上的 SELinux。它主要關注 Red Hat 作業系統,但並不限於它們。

Fedora SELinux FAQ

本文件回答了關於 SELinux 的常見問題。它主要關注 Fedora,但並不限於 Fedora。

F.40.9. 作者 #

KaiGai Kohei

提交更正

如果您在文件中看到任何不正確、與您對特定功能的實際經驗不符或需要進一步闡述的內容,請使用 此表格 報告文件問題。