Skip to content

PostgreSQL 证书认证

概述

证书认证(Certificate Authentication)是 PostgreSQL 提供的一种基于 SSL 客户端证书的身份验证方法。这种认证方式通过验证客户端提供的 SSL 证书来确认用户身份,提供了高安全性的连接方式。

INFO

证书认证只能在 SSL 连接上使用,因此在配置证书认证之前,必须先正确配置 SSL 连接。

工作原理

证书认证的工作流程如下:

认证过程详解

  1. SSL 连接建立:客户端与服务器建立 SSL 连接
  2. 证书请求:服务器要求客户端提供有效的 SSL 证书
  3. 证书验证:服务器验证证书的有效性和信任关系
  4. 用户名匹配:提取证书的 CN(Common Name)字段,与请求的数据库用户名进行比较
  5. 认证决策:如果 CN 匹配用户名或通过用户名映射验证,则允许登录

配置方法

1. pg_hba.conf 配置

pg_hba.conf文件中配置证书认证:

bash
# TYPE  DATABASE        USER            ADDRESS                 METHOD
hostssl all             all             192.168.1.0/24          cert
hostssl mydb            certuser        0.0.0.0/0               cert map=certmap
bash
# 允许所有用户通过证书认证连接所有数据库
hostssl all all 0.0.0.0/0 cert
bash
# 只允许特定用户通过证书认证
hostssl mydb certuser 192.168.1.0/24 cert
bash
# 使用用户名映射的证书认证
hostssl all all 0.0.0.0/0 cert map=certmap

2. 用户名映射配置

当证书的 CN 字段与数据库用户名不同时,可以使用用户名映射:

bash
# pg_ident.conf
# MAPNAME       SYSTEM-USERNAME         PG-USERNAME
certmap         john.doe                johnuser
certmap         admin.cert              postgres
certmap         /^(.*)\.dev$            \1

3. 配置选项

证书认证支持以下配置选项:

选项描述示例
map指定用户名映射cert map=certmap

实际应用示例

示例 1:基本证书认证配置

场景:为公司内部应用配置证书认证,确保只有持有有效证书的客户端能够连接数据库。

问题陈述:需要为一个包含敏感数据的 PostgreSQL 数据库配置高安全性的客户端认证。

解决方案

bash
# 在pg_hba.conf中添加证书认证规则
hostssl financialdb all 10.0.0.0/8 cert
bash
# 生成客户端私钥
openssl genrsa -out client.key 2048

# 生成证书签名请求
openssl req -new -key client.key -out client.csr \
    -subj "/CN=dbuser/O=Company/C=US"

# 使用CA签名证书
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
    -CAcreateserial -out client.crt -days 365
bash
# 使用证书连接数据库
psql "host=dbserver dbname=financialdb user=dbuser \
      sslmode=require sslcert=client.crt sslkey=client.key \
      sslrootcert=ca.crt"

分析过程

  • SSL 连接确保数据传输加密
  • 证书验证确保客户端身份可信
  • CN 字段"dbuser"必须与 PostgreSQL 用户名匹配
  • 无需密码,基于证书的强认证

输入和输出

输入:客户端证书(CN=dbuser)

Certificate:
    Subject: CN=dbuser, O=Company, C=US
    Issuer: CN=Company CA, O=Company, C=US
    Validity: Not Before: 2024-01-01, Not After: 2025-01-01

输出:成功连接

psql (14.5)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384)
Type "help" for help.

financialdb=>

示例 2:使用用户名映射的证书认证

场景:企业环境中,员工证书的 CN 字段包含完整的员工信息,需要映射到简化的数据库用户名。

问题陈述:证书 CN 为"[email protected]",但数据库用户名为"john",需要建立映射关系。

解决方案

bash
# 使用用户名映射的证书认证
hostssl companydb all 0.0.0.0/0 cert map=employee_map
bash
# 员工证书到数据库用户的映射
employee_map    [email protected]    john
employee_map    [email protected]  jane
employee_map    [email protected]       postgres
# 使用正则表达式进行模式匹配
employee_map    /^(.+)@company\.com$    \1
bash
# 重新加载PostgreSQL配置
SELECT pg_reload_conf();

分析过程

  1. 映射查找:服务器在 pg_ident.conf 中查找匹配的映射规则
  2. 模式匹配:支持正则表达式进行灵活的用户名转换
  3. 认证决策:映射成功后,使用映射后的数据库用户名进行权限检查

输入和输出

输入:证书 CN = "[email protected]"

Certificate Subject: [email protected], O=Company Inc, C=US

映射过程:

[email protected] → john (通过employee_map映射)

输出:以用户"john"身份连接成功

companydb=> SELECT current_user;
 current_user
--------------
 john
(1 row)

安全考虑

证书管理最佳实践

WARNING

证书认证的安全性完全依赖于证书基础设施的安全性。确保:

  • CA 私钥的安全存储
  • 证书的定期轮换
  • 撤销列表(CRL)的维护

1. 证书生命周期管理

2. 安全配置检查表

检查项重要性配置建议
SSL 版本🔴 高仅允许 TLS 1.2+
证书有效期🟡 中建议 1 年或更短
CA 证书保护🔴 高离线存储,硬件安全模块
证书撤销🟡 中维护 CRL 或使用 OCSP
密钥强度🔴 高至少 2048 位 RSA 或 256 位 ECC

故障排除

常见错误和解决方案

Details

证书验证失败 错误信息certificate verify failed

可能原因

  • 证书链不完整
  • CA 证书未正确配置
  • 证书已过期

解决方案

bash
# 检查证书有效性
openssl x509 -in client.crt -text -noout

# 验证证书链
openssl verify -CAfile ca.crt client.crt

# 检查服务器SSL配置
openssl s_client -connect dbserver:5432 -cert client.crt -key client.key
Details

用户名映射失败 错误信息certificate authentication failed for user "username"

可能原因

  • pg_ident.conf 映射规则错误
  • 映射名称在 pg_hba.conf 中未正确指定
  • 正则表达式语法错误

解决方案

bash
# 检查映射配置
cat $PGDATA/pg_ident.conf | grep mapname

# 测试正则表达式
echo "[email protected]" | grep -E "^(.+)@company\.com$"

# 查看认证日志
tail -f $PGDATA/log/postgresql-*.log | grep FATAL

性能考量

证书认证性能特点

性能优化建议

  1. 连接池使用:减少频繁的 SSL 握手开销
  2. 证书缓存:服务器端缓存已验证的证书
  3. 简化映射规则:避免复杂的正则表达式

TIP

证书认证比密码认证在连接建立时有更高的 CPU 开销,但提供了更强的安全性。对于高频连接的应用,建议使用连接池。

与其他认证方法的比较

认证方法安全性复杂性性能适用场景
cert🔴 很高🟡 中等🟡 中等企业级应用,高安全要求
md5/scram🟡 中等🟢 低🟢 高一般 web 应用
trust🔴 无🟢 最低🟢 最高开发环境
ldap🟡 中等🟡 中等🟡 中等企业目录集成

::: important 选择认证方法时,需要在安全性、管理复杂性和性能之间找到平衡。证书认证适合对安全性要求极高的企业环境。

:::

相关配置参数

SSL 相关参数

sql
-- 查看当前SSL配置
SHOW ssl;
SHOW ssl_cert_file;
SHOW ssl_key_file;
SHOW ssl_ca_file;

-- 查看连接的SSL信息
SELECT * FROM pg_stat_ssl WHERE pid = pg_backend_pid();

重要配置文件路径

bash
# PostgreSQL配置文件位置
$PGDATA/postgresql.conf    # 主配置文件
$PGDATA/pg_hba.conf        # 客户端认证配置
$PGDATA/pg_ident.conf      # 用户名映射配置

通过合理配置证书认证,您可以为 PostgreSQL 数据库建立一个高安全性的访问控制机制,特别适用于企业级环境和对安全性有严格要求的应用场景。