选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1
历史版本PostgreSQL 9.1 已于 2016 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

F.38. sepgsql — 基于 SELinux 标签的强制访问控制(MAC)安全模块 #

sepgsql 是一个可加载模块,支持基于 SELinux 安全策略和安全标签的强制访问控制(MAC)。

警告

当前实现存在重大限制,并不会对所有操作实施强制访问控制。详见 第 F.38.6 节

F.38.1. 概述 #

该模块与 SELinux 集成,在 PostgreSQL 通常提供的安全检查之外再增加一层 安全检查。从 SELinux 的角度看,该模块使 PostgreSQL 能够充当用户空间对象管理器。由 DML 查询发起的每一次表或函数访问,都会依据系统安全策略进行检查。这种检查是 对 PostgreSQL 常规 SQL 权限检查的补充。

SELinux 的访问控制决策通过安全标签作出,安全标签 以 system_u:object_r:sepgsql_table_t:s0 这样的字符串表示。 每个访问控制决策都涉及两个标签:尝试执行操作的主体标签,以及要执行该操 作的对象标签。由于这些标签可以应用到任意类型的对象,数据库中存储对象的 访问控制决策也可以与文件等其他类型对象一样,遵循同一套一般性标准;使 用该模块时也确实如此。这样的设计旨在让集中式安全策略能够保护信息资产, 而不受这些资产具体存储方式的影响。

SECURITY LABEL 语句允许为数据库对象分配安全标签。

F.38.2. 安装 #

sepgsql 只能用于启用了 SELinuxLinux 2.6.28 或更高版本。它在任何其他平台上都不可用。 You will also need libselinux 2.0.93 or higher and selinux-policy 3.9.13 or higher (although some distributions may backport the necessary rules into older policy versions).

可以使用 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 被禁用或尚未安装,则必须先安装并配置 它,之后才能安装本模块。

要构建此模块,请将选项 --with-selinux 加入 PostgreSQL 的 configure 命令中。还要确保构建时已经安装 libselinux-devel RPM。

要使用此模块,必须将 sepgsql 包含在 shared_preload_libraries 参数中,该参数位于 postgresql.conf 内。如果以其他任何方式加载该模块,它都 无法正确工作。 模块加载后,应在每个数据库中执行 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.38.3. 回归测试 #

由于 SELinux 的特性,运行 sepgsql 的回归测试需要额外执行若干配置步骤,其中部分步骤必须以 root 身份完成。普通的 make checkmake installcheck 命令不会运行这些回归测试;必须完成配置,然后手工调用测试脚本。这些测试必须在已配置的 PostgreSQL 构建树的 contrib/sepgsql 目录中运行。虽然需要构建树,但这些测试是为已安装的服务器设计的,也就是说,它们类似于 make installcheck 而不是 make check

首先,在一个正常工作的数据库中设置 sepgsql,具体请按照 第 F.38.2 节 中的说明操作。注意,当前操作系统用户必须能够不经密码认证就以超级用户身份连接数据库。

其次,为回归测试构建并安装策略包。sepgsql-regtest 策略是一个特殊用途的策略包,它提供回归测试期间允许的一组规则。它应当从策略源文件 sepgsql-regtest.te 构建,使用 SELinux 提供的 Makefile 通过 make 完成。 You will need to locate the appropriate Makefile on your system; the path shown below is only an example. Once built, install this policy package using the semodule command, which loads supplied policy packages into the kernel. If the package is correctly installed, semodule -l should list sepgsql-regtest as an available policy package:

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

第三,打开 sepgsql_regression_test_mode。为了你系统的安全,默认不启用 sepgsql-regtest 中的所有规则。 The sepgsql_regression_test_mode parameter enables the rules needed to launch the regression tests. It can be turned on using the setsebool command:

$ 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.38.7 节,了解如何调整工作域。

最后,运行回归测试脚本:

$ ./test_sepgsql

该脚本会尝试验证是否已正确完成全部配置步骤,然后运行 sepgsql 模块的回归测试。

完成测试后,建议关闭 sepgsql_regression_test_mode 参数:

$ sudo setsebool sepgsql_regression_test_mode off

也可以选择彻底移除 sepgsql-regtest 策略:

$ sudo semodule -r sepgsql-regtest

F.38.4. GUC 参数 #

sepgsql.permissive (boolean) #

该参数使 sepgsql 无论系统设置如何都以宽容模式运行。 默认值为关闭。该参数只能在 postgresql.conf 文件中 或服务器命令行上设置。

当该参数打开时,sepgsql 会以宽容模式运行,即使 SELinux 整体处于强制模式也是如此。该参数主要用于测试。

sepgsql.debug_audit (boolean) #

该参数会在不考虑系统策略设置的情况下启用审计消息输出。 默认值为关闭,这意味着消息将按系统设置输出。

SELinux 的安全策略本身也有规则来控制是否记录特 定的访问。默认情况下,访问违例会被记录,而被允许的访问不会被记录。

该参数会在不考虑系统策略的情况下,强制打开所有可能的日志记录。

F.38.5. 特性 #

F.38.5.1. 受控对象类

SELinux 的安全模型把所有访问控制规则描述为主体实体(通常是数据库的客户端)与客体实体(例如数据库对象)之间的关系,二者各由一个安全标签标识。 If access to an unlabelled object is attempted, the object is treated as if it were assigned the label unlabeled_t.

目前,sepgsql 允许把安全标签指派给模式、表、列、序列、视图和函数。 When sepgsql is in use, security labels are automatically assigned to supported database objects at creation time. This label is called a default security label, and is decided according to the system security policy, which takes as input the creator's label and the label assigned to the new object's parent object.

新数据库对象基本上会继承父对象的安全标签,但如果安全策略中存在称为类型 转换规则的特殊规则,则可能会应用不同的标签。对于模式,父对象是当前数据 库;对于表、序列、视图和函数,父对象是其所在模式;对于列,父对象是其所 在表。

F.38.5.2. DML 权限

对于表,根据语句的种类,对所有被引用的目标表检查 db_table:selectdb_table:insertdb_table:updatedb_table:delete;此外,还对每条 DML 语句中引用的表检查 db_table:select is also checked for all the tables that contain the columns referenced in the WHERE or RETURNING clause, as a data source of UPDATE, and so on. For example, consider:

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

In this case we must have db_table:select in addition to db_table:update, because t1.a is referenced within the WHERE clause. Column-level permissions will also be checked for each referenced column.

对于列,不仅在用 SELECT 读取的列上检查 db_column:select,在其他 DML 语句引用的列上也做检查。 Of course, it also checks db_column:update or db_column:insert on columns being modified by UPDATE or INSERT.

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

在这个例子中,对被更新的列 t1.x 检查 db_column:update;对既被更新又被引用的列 t1.y 检查 db_column:{select update};对列 t1.z 检查 db_column:select,因为它只在 WHERE 子句中被引用。此外还会在表级检查 db_table:{select update}

对于序列,当使用 SELECT 引用序列对象时,会检查 db_sequence:get_value;但请注意,当前不会检查执行相 应函数(如 lastval())的权限。

对于视图,会先检查 db_view:expand,然后对由该视图展 开得到的各个对象分别检查所需的其他权限。

对于函数,虽然定义了 db_procedure:{execute},但在这个版本中不进行检查。

客户端必须被允许访问所有被引用的表和列,即使这些表和列最初来自随后被展 开的视图也是如此,这样我们才能在不受表内容引用方式影响的情况下,应用一 致的访问控制规则。

默认数据库权限系统允许数据库超级用户使用 DML 命令修改系统目录,也允许引 用或修改 TOAST 表。启用 sepgsql 后,这些操作都会被禁 止。

F.38.5.3. DDL 权限

当执行 SECURITY LABEL 时,会在被重新标记的对象上用其旧安全标签检查 setattrrelabelfrom,然后用所提供的新安全标签检查 relabelto

在安装了多个标签提供者且用户尝试设置一个不由 SELinux 管理的安全标签的情况下,这里只应检查 setattr。由于实现上的限制,目前没有这样做。

F.38.5.4. 受信任过程

可信过程类似于安全定义者函数或 set-uid 命令。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.38.5.5. 杂项

我们一律拒绝 LOAD 命令,因为装入任意模块都可能轻易绕过安 全策略的强制执行。

F.38.6. 限制 #

Data Definition Language (DDL) Permissions

由于实现上的限制,不检查 DDL 权限。

Data Control Language (DCL) Permissions

由于实现上的限制,不检查 DCL 权限。

Row-level access control

PostgreSQL 不支持行级访问;因此, sepgsql 也不支持。

Covert channels

sepgsql 不会试图隐藏某个对象的存在,即使用户无权引用 它也是如此。例如,即便我们无法取得一个不可见对象的内容,也仍然可以从主 键冲突、外键违例等结果中推断出它的存在。绝密表的存在无法隐藏;我们只希 望隐藏其内容。

F.38.7. 外部资源 #

SE-PostgreSQL Introduction

该 wiki 页面提供了简要概述,并介绍了安全设计、体系结构、管理以及未来特 性。

Fedora SELinux User Guide

该文档提供了在系统上管理 SELinux 所需的广泛知 识。它主要聚焦于 Fedora,但并不限于 Fedora。

Fedora SELinux FAQ

该文档回答了关于 SELinux 的常见问题。它主要 聚焦于 Fedora,但并不限于 Fedora。

F.38.8. 作者 #

KaiGai Kohei

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。