第十四章:安全配置
最后更新: 2024-01-01
作者: PostgreSQL Team
页面目录
第十四章:安全配置
14.1 认证配置
14.1.1 pg_hba.conf 认证方法
# TYPE DATABASE USER ADDRESS METHOD
# 本地 Unix socket(信任)
local all postgres trust
local all all peer
# 本地 TCP/IP(scram-sha-256,推荐)
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
# 内网(md5 或 scram-sha-256)
host all all 192.168.1.0/24 scram-sha-256
# 外网(scram-sha-256 + IP 白名单)
host all admin 10.0.0.0/8 scram-sha-256
host all all 0.0.0.0/0 reject
# 复制连接
host replication replicator 192.168.1.0/24 scram-sha-256
14.1.2 认证方法说明
| 方法 | 说明 | 安全性 |
|---|---|---|
| trust | 无条件信任 | 低(仅本地) |
| reject | 拒绝连接 | - |
| md5 | MD5 加密 | 中 |
| scram-sha-256 | SCRAM-SHA-256(推荐) | 高 |
| peer | OS 用户名匹配 | 中(仅本地) |
| ldap | LDAP 认证 | 高 |
| gssapi | Kerberos | 高 |
| cert | SSL 证书 | 高 |
14.2 用户与角色管理
14.2.1 创建角色
-- 创建登录角色
CREATE ROLE readonly;
CREATE ROLE readwrite WITH LOGIN PASSWORD 'strong_password';
-- 创建超级用户
CREATE ROLE dba WITH SUPERUSER CREATEDB CREATEROLE BYPASSRLS;
-- 创建带有效期的角色
CREATE ROLE temp_user WITH LOGIN PASSWORD 'temp123' VALID UNTIL '2024-12-31';
-- 创建带连接数限制的角色
CREATE ROLE app_user WITH LOGIN PASSWORD 'app_password' CONNECTION LIMIT 10;
14.2.2 角色继承与组成员
-- 创建角色组
CREATE ROLE analyst;
CREATE ROLE developer;
-- 创建权限组
CREATE ROLE read_only;
GRANT CONNECT ON DATABASE mydb TO read_only;
GRANT USAGE ON SCHEMA public TO read_only;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only;
-- 添加成员
GRANT read_only TO analyst;
GRANT read_only TO developer;
-- 添加带继承的角色
GRANT developer TO analyst WITH ADMIN TRUE;
-- 查看角色成员
SELECT
r.rolname AS role_name,
m.rolname AS member_name
FROM pg_auth_members rm
JOIN pg_roles r ON rm.roleid = r.oid
JOIN pg_roles m ON rm.member = m.oid;
14.2.3 密码管理
-- 修改密码
ALTER USER username WITH PASSWORD 'new_strong_password';
-- 设置密码有效期
ALTER USER username VALID UNTIL '2025-01-01';
-- 移除密码
ALTER USER username WITH PASSWORD NULL;
-- 密码策略(通过配置文件)
# password_encryption = scram-sha-256
# password_min_length = 12
# password_complexity = on
14.3 权限管理
14.3.1 对象权限
-- 数据库权限
GRANT CONNECT, TEMPORARY ON DATABASE mydb TO readwrite;
GRANT USAGE ON DATABASE mydb TO readonly;
-- 模式权限
GRANT USAGE ON SCHEMA public TO readonly;
GRANT CREATE ON SCHEMA public TO developer;
-- 表权限
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO readwrite;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
-- 序列权限(需要授予才能使用自增)
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO readwrite;
-- 函数权限
GRANT EXECUTE ON FUNCTION calculate_total(INTEGER, INTEGER) TO developer;
-- 默认权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO readwrite;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO readwrite;
14.3.2 行级安全 (RLS)
-- 启用 RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
-- 创建策略
CREATE POLICY user_orders_policy ON orders
FOR ALL
TO authenticated
USING (user_id = current_user_id());
CREATE POLICY sensitive_data_policy ON sensitive_data
FOR SELECT
TO public
USING (
-- 用户只能看到自己的数据
user_id = current_setting('app.current_user_id')::INTEGER
-- 或基于角色
OR current_user IN ('admin', 'manager')
);
-- 测试策略
SET app.current_user_id = '1';
SELECT * FROM sensitive_data;
-- 查看策略
SELECT schemaname, tablename, policyname, permissive, roles, cmd, qual
FROM pg_policies;
14.3.3 撤销权限
-- 撤销表权限
REVOKE DELETE ON orders FROM readwrite;
-- 撤销所有权限
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM public;
-- 撤销默认权限
ALTER DEFAULT PRIVILEGES IN SCHEMA public
REVOKE ALL ON TABLES FROM public;
14.4 加密配置
14.4.1 SSL 配置
# postgresql.conf
# 启用 SSL
ssl = on
ssl_cert_file = '/etc/ssl/certs/server.crt'
ssl_key_file = '/etc/ssl/private/server.key'
ssl_ca_file = '/etc/ssl/certs/ca.crt'
# SSL 模式
ssl_prefer_server_ciphers = on
ssl_min_protocol_version = 'TLSv1.2'
14.4.2 生成 SSL 证书
# 生成自签名证书
openssl req -new -x509 -days 365 -nodes \
-text -out server.crt \
-keyout server.key \
-subj "/CN=postgres"
# 设置权限
chmod 600 server.key
chown postgres:postgres server.crt server.key
14.4.3 数据加密
-- pgcrypto 扩展提供加密函数
CREATE EXTENSION pgcrypto;
-- 加密数据
INSERT INTO passwords (username, password_hash)
VALUES ('user1', crypt('user_password', gen_salt('bf')));
-- 验证密码
SELECT * FROM passwords
WHERE username = 'user1'
AND password_hash = crypt('input_password', password_hash);
-- 加密字段(对称加密)
INSERT INTO secrets (data)
VALUES (pgp_sym_encrypt('sensitive data', 'encryption_key'));
-- 解密字段
SELECT pgp_sym_decrypt(data, 'encryption_key')
FROM secrets;
-- 哈希函数
SELECT md5('password');
SELECT sha256('password');
SELECT digest('password', 'sha256'); -- 需要 pgcrypto
14.5 网络安全
14.5.1 防火墙配置
# Ubuntu/Debian
sudo ufw allow from 192.168.1.0/24 to any port 5432
# CentOS/RHEL
sudo firewall-cmd --permanent --add-source=192.168.1.0/24 --zone=trusted
sudo firewall-cmd --permanent --add-port=5432/tcp
sudo firewall-cmd --reload
14.5.2 连接限制
# postgresql.conf
# 最大连接数
max_connections = 200
# 预留连接给超级用户
reserved_connections = 3
# 空闲会话超时
idle_session_timeout = 60min
# 语句超时(毫秒)
statement_timeout = 30000 # 30 秒
14.5.3 IP 访问控制
# 监听地址
listen_addresses = 'localhost,192.168.1.100'
# 允许特定 IP
host all all 192.168.1.0/24 scram-sha-256
# 拒绝所有外部访问
host all all 0.0.0.0/0 reject
14.6 审计日志
14.6.1 配置审计日志
# postgresql.conf
# 启用日志
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'
log_rotation_age = 1d
log_rotation_size = 100MB
# 记录内容
log_statement = 'ddl' # 记录 DDL
log_min_duration_statement = 1000 # 记录超过 1 秒的查询
log_connections = on
log_disconnections = on
log_hostname = on
# 记录用户
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h'
14.6.2 pgaudit 扩展
-- 安装 pgaudit
CREATE EXTENSION pgaudit;
-- 配置审计
ALTER SYSTEM SET shared_preload_libraries = 'pgaudit';
-- 审计会话
ALTER DATABASE mydb SET pgaudit.log = 'READ, WRITE, DDL';
ALTER DATABASE mydb SET pgaudit.log_catalog = off;
-- 审计特定表
ALTER TABLE orders SET pgaudit.log = 'ALL';
14.6.3 审计查询
-- 查看最近的 DDL 操作
SELECT
current_timestamp,
session_start,
usename,
datname,
query
FROM pg_stat_activity
WHERE state = 'active'
AND query ILIKE '%CREATE%'
AND query ILIKE '%TABLE%';
-- 查看连接历史
SELECT
event_time,
user_name,
database_name,
connection_from,
session_role,
command_tag
FROM pg_logicalcapabilities;
14.7 安全最佳实践
┌─────────────────────────────────────────────────────────────┐
│ 安全检查清单 │
├─────────────────────────────────────────────────────────────┤
│ □ 使用 scram-sha-256 认证 │
│ □ 启用 SSL 加密连接 │
│ □ 配置强密码策略 │
│ □ 最小权限原则 │
│ □ 启用 Row-Level Security │
│ □ 配置审计日志 │
│ □ 定期更新 PostgreSQL │
│ □ 网络隔离和防火墙 │
│ □ 定期备份 │
└─────────────────────────────────────────────────────────────┘
14.8 本章小结
PostgreSQL 安全配置要点:
| 主题 | 关键措施 |
|---|---|
| 认证 | scram-sha-256, LDAP, SSL 证书 |
| 授权 | 最小权限, RLS, 默认权限 |
| 加密 | SSL, pgcrypto, 密码哈希 |
| 网络 | 防火墙, IP 白名单, 连接限制 |
| 审计 | 日志记录, pgaudit |
📌 下一章预告
下一章将介绍 PostgreSQL 的运维管理和日常维护任务。