> 技术文档 > PostgreSQL应该怎样实现安全管控?_postgres数据安全

PostgreSQL应该怎样实现安全管控?_postgres数据安全


PostgreSQL应该怎样实现安全管控?

Whoami:5年+金融、政府、医疗领域工作经验的DBA
Certificate:OCP、PCP
Skill:Oracle、Mysql、PostgreSQL
Platform:CSDN、墨天伦、公众号(呆呆的私房菜)

业务范围:数据库安装部署、日常维护、主备切换、故障处理、性能优化、技术培训等。
需要的伙伴或者商业合作请移步 公众号【呆呆的私房菜】获取联系方式。

阅读本文可以了解到PostgreSQL数据库安全管控相关的内容,包含认证安全、数据加密、访问权限控制、安全审计、版本升级等。

01 认证安全

一、客户端认证控制:

  1. pg_hba.conf文件配置访问名单
安全建议:1. 规避trust认证方法;2. 超级用户只允许本地登录,不允许网络连接;3. 将dbname+username+ip限制到最小;4. 使用最小范围鉴权,避免使用all、0.0.0.0/0;5. 密码认证建议使用md5或scram加密方法;6. 可以配置auth_delay扩展限制用户错误密码登录次数,防止暴力破解或者DDos攻击。

二、服务端认证控制:

  1. 设置用户密码安全存储
# 如果设置了password_encryption=md5,但创建密码不加encrypted,那么密码将会明文存储create role  [[WITH ] option [ ... ] ] | [ ENCRYPTED | UNENCRYPTED ] PASSWORD \'\';
  1. 设置用户密码有效期周期
alter user rep valid until \'2024-08-10 00:00:01\';
  1. 设置密码复杂度
# 数据库安装 passwordcheck 插件create extension passwordcheck;# 创建用户或修改用户密码时,强制限制密码复杂度,限制密码不能重复使用等
  1. 设置修改密码时防止被记录到psql执行日志或集群服务日志
# 避免命令行明文密码的出现# 使用域认证或第三方认证方法
  1. pg_stat_statements扩展也会记录sql或用户密码信息
# 清空记录的sqlselect pg_stat_statements_reset();# 关闭ddl记录功能pg_stat_statements.track_utility=off

02 数据加密

一、 数据传输

1. 如果网络环境无法保证绝对安全,建议使用加密传输,例如openssl。2. 修改默认端口3. 配置防火墙策略4. 使用ssh隧道技术

二、 数据加密

1. 敏感数据加密后存储在数据库中,即使加密数据泄露,只要加解密方法没有泄露,也是相对安全的;2. 建议加解密方法放在应用端实现;3. pgcrypto模块提供了密码函数。create extension pgcrypto;

03 权限控制

一、 用户权限最小化控制

1. 使用超级用户创建所需的数据库、模式、表、索引、函数;2. 创建应用账户角色,将数据库、模式的使用权限授权给应用账户;3. 应用账户授予表的对应dml权限,函数的execute权限等,注意严格控制drop、truncate、replace等权限;4. 通过列权限或视图来限制应用账户的权限;5. 回收数据库、模式、表、函数等的public权限。revoke all on database  from public;revoke all on schema  from public;revoke all on table  from public;revoke all on function  from public;6. 回收函数语言的public权限,限制普通用户不能创建函数revoke all on language plpgsql from public;

二、行级安全控制

限制普通用户只能操作表中指定条件的记录1. PostgreSQL 9.5新增的特性,不同用户可以看到表中的不同数据postgres=# \\h CREATE POLICY命令:CREATE POLICY描述:为一个表定义一条新的行级安全性策略语法:CREATE POLICY 名称 ON 表名 [ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] [ TO { 角色名称 | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ] [ USING ( 使用表达式 ) ] [ WITH CHECK ( 检查表达式 ) ]URL: https://www.postgresql.org/docs/16/sql-createpolicy.html

三、权限控制

1. 通过事件触发器禁止应用账户执行ddl,防止被攻击后,用户drop或truncate删除对象或清空数据;CREATE OR REPLACE FUNCTION prevent_ddl()RETURNS event_trigger AS $$BEGIN -- 检查语句是否是 DDL 并且执行者是受限用户 IF TG_TAG IN (\'CREATE\', \'ALTER\', \'DROP\', \'TRUNCATE\') AND CURRENT_USER = \'受限用户名\' THEN RAISE EXCEPTION \'用户 % 不允许执行 DDL 语句\', CURRENT_USER; END IF; RETURN;END;$$ LANGUAGE plpgsql;-- 创建事件触发器CREATE EVENT TRIGGER prevent_ddl_triggerON ddl_command_startEXECUTE FUNCTION prevent_ddl();2. 防止执行不带条件的delte、update,在需要保护的表里边,新增一条dummy记录,创建行触发器,当这条记录被更新或删除时,抛出异常。

04 安全审计

审计功能一般用于排查问题,也是一种举证的手段,主要通过记录日志来实现。

审计功能建议考虑下列内容:

1. 跟踪postgresql.conf配置文件变更;2. 跟踪表的创建时间和表定义的修改时间;3. 跟踪表的记录被哪个用户插入或修改;

审计功能实现方式:

1. 基本的语句记录可以由标准日志记录工具 log_statement=all 提供;2. 可以使用pg_audit扩展来获得详细的会话或对象审计日志记录;3. 可以使用hstore扩展和触发器来跟踪表的行记录变更。

05 版本升级

PostgreSQL社区的更新速度很快,每天都会有大大小小的更新,有些是Fix patch,有些是feature,有些是性能patch;

正常情况下,我们的升级只需要跟随小版本的升级,如果没有小版本发布,说明没有很大的安全漏洞;
大版本更新会伴随着一些新特性的变化,如果进行大版本更新,需要关注是否对现有应用产生影响,相应模块是否需要更新。

版本号由主要版本和次要版本组成:
PostgreSQL 16.3 中的16是主要版本,3是次要版本。
PostgreSQL 10.0 之前的版本由3个数字组成,例如9.6.19,其中9.6是主要版本,19是次要版本。

社区bug动态跟踪:http://git.postgresql.org

数据库版本升级分为两种:

  1. 小版本升级
    一般来说,小版本升级不会改变内部的存储格式,因此总是和大版本兼容;
    对于兼容版本的升级非常简单,只需要关闭数据库服务,安装替换二进制的可执行文件,重新启动数据库服务即可。

  2. 大版本升级
    大版本的升级可能会更改内部数据的存储格式,因此需要额外的操作。
    大版本可以考虑使用pg_dump、pg_upgrade和逻辑复制的方式进行升级。

升级方法 **优点 ** 缺点 pg_dump 简单安全、比较灵活 升级时间长,仅适用于全量迁移、效率低下,应用停服时间长 pg_upgrade 1. 不拷贝数据,仅元数据升级,2. 效率高,link模式下,2TB数据升级<10s3. 默认模式(非link模式)下原实例不受影响 复杂度比dump/restore方式高,link模式下有些风险可能会丢失standby服务,默认模式下需要双倍磁盘空间 逻辑复制 最短停机时间,安全性搞,平滑割接 库级别的发布,订阅表必须有pk/uk,不支持ddl、大对象、外键和触发器,存在wal堆积风险

06 外界环境安全

这个话题比较宽泛,考虑的面会比较多,如:

  1. 应用程序、中间件是否安全;
  2. 数据库操作系统、服务器是否安全;
  3. 存储是否安全,是否冗余配置,有无容灾;
  4. 网络环境是否安全,是否做bond,是否做mac地址过滤或绑定;
  5. 机房是否安全,是否两地三中心等。

07 数据库可靠性配置

一、 资源限制

  1. 通过pg_hba.conf文件严格控制访问用户;
  2. 限制用户最大并发连接数,可具体到user和database级别;
  3. 根据应用实际情况设定合理的连接超时策略。

二、配置选项

  1. 数据库层面:最大程度保证事务都能写入到磁盘,但是这同样会带来严重的性能损耗。
1. 在事务提交时等待所有的数据都写入到磁盘,确保所有的更改都被写入到磁盘后才会向客户端返回提交成功的响应synchronous_commit = on:2. 每次写操作后调用操作系统的 fsync 函数,强制将数据从操作系统的缓存写入到磁盘fsync = on3. 将整个 8KB 的页面数据写入到磁盘,即使只有页面的一部分被修改full_page_writes = on
  1. 存储层面:
1. 关闭磁盘的write cache2. 只允许有断电保护的write cache

三、备份策略

  1. 数据库启用归档,配置良好的备份策略。

四、容灾建设

  1. 配置异地容灾,如流复制等。