PostgreSQL 16 新增了 gss_accept_delegation:服务器可以接收客户端委派的 Kerberos/GSSAPI 凭据,并在访问其他服务时代表该用户完成认证。这解决了多跳认证中的一个老问题,但默认值仍是 off,因为一旦接受委派,数据库会临时持有足以代表用户行动的凭据,安全边界也随之改变。
它解决的是“第二跳”认证
普通 Kerberos 登录只证明“客户端是谁”。假设 Alice 使用 GSSAPI 连接数据库 A,数据库 A 随后还要访问数据库 B、文件服务或其他支持 Kerberos 的后端,问题就出现了:A 已经知道 Alice 的身份,却没有可用于第二跳的 Alice 凭据。
凭据委派补上了这一环:
Alice 的客户端
│ 连接时请求委派
▼
PostgreSQL A(接受委派凭据)
│ 代表 Alice 发起后续认证
▼
PostgreSQL B 或其他 Kerberos 服务
这里需要双方同时同意:客户端必须主动请求委派,PostgreSQL 16 服务器也必须开启 gss_accept_delegation。只改服务器配置不会让所有 Kerberos 连接自动获得可转用的用户凭据。
可以这样配置和验证
下面是一个可改造的最小操作流程。它假设 Kerberos realm、数据库服务主体、keytab 和 GSSAPI 登录已经配置完成;请将主机名、realm 和数据库名替换为实际值。
在接收委派凭据的 PostgreSQL 16 实例上执行:
psql -d postgres -v ON_ERROR_STOP=1 <<'SQL'
ALTER SYSTEM SET gss_accept_delegation = on;
SELECT pg_reload_conf();
SHOW gss_accept_delegation;
SQL
预期最后一条语句返回 on。也可以直接在 postgresql.conf 中配置:
gss_accept_delegation = on
认证入口仍需允许 GSSAPI。以下是可按环境调整的 pg_hba.conf 示例:
# TYPE DATABASE USER ADDRESS METHOD OPTIONS
hostgssenc all all 10.20.0.0/16 gss include_realm=0
重新加载认证配置:
psql -d postgres -c 'SELECT pg_reload_conf();'
客户端连接时需要明确请求委派。libpq/psql 可以这样实践:
kinit alice@EXAMPLE.COM
psql "host=db-a.example.com dbname=app user=alice gssencmode=require gssdelegation=1" \
-c 'SELECT current_user, session_user;'
gssdelegation=1 表示客户端愿意转交凭据,gssencmode=require 则要求使用 GSS 加密连接。两者解决的问题不同:前者控制是否委派身份能力,后者控制连接是否使用 GSS 加密。
如果连接失败,可以先拆开检查 Kerberos 和 PostgreSQL 两层状态:
klist
psql "host=db-a.example.com dbname=app user=alice gssencmode=require" -c 'SELECT version();'
psql "host=db-a.example.com dbname=app user=alice gssencmode=require gssdelegation=1" -c 'SHOW gss_accept_delegation;'
这组命令先确认票据存在,再确认普通 GSSAPI 连接可用,最后才加入委派选项。这样更容易区分 DNS、服务主体、keytab、加密协商和委派策略问题。
默认关闭不是保守过度
密码通常只在认证瞬间被验证,而可委派 Kerberos 凭据能够在有效期内代表用户访问其他服务。开启该参数后,需要重新审视几条边界:
- 数据库主机的可信级别提高了。 能读取服务器进程内存、凭据缓存或劫持数据库进程的攻击者,可能利用被委派的身份。
- 下游权限会放大影响。 如果用户在文件服务、其他数据库或内部 API 上权限很大,数据库 A 被攻陷后的横向移动范围也会扩大。
- 委派链路必须可审计。 下游日志应保留实际 Kerberos principal,而不是只记录一个共享服务账号。
- 票据生命周期不等于会话生命周期。 长连接、连接池和票据过期的组合需要单独测试,不能假设一次成功连接会永久获得下游访问能力。
- 接受委派不等于自动使用委派。 具体扩展、外部数据访问组件或应用代码仍需支持使用这些凭据访问目标服务。
上线时把范围缩到真正需要的地方
gss_accept_delegation 适合必须保留最终用户身份的多跳架构,例如数据库中转访问另一个 Kerberos 服务。若只是让 PostgreSQL 用固定身份读取下游系统,独立服务主体通常更容易隔离和审计,不一定需要用户凭据委派。
上线前可以按以下清单检查:
- 仅在确实承担第二跳认证的 PostgreSQL 实例上启用。
- 限制可连接网段,并收紧操作系统、数据库超级用户和备份系统权限。
- 在 Kerberos 策略层只允许必要的委派范围,避免无边界委派。
- 使用低权限测试 principal 验证客户端请求、服务器接受和下游认证三个阶段。
- 测试票据过期、连接池复用、数据库故障转移及下游不可用时的行为。
- 确认 PostgreSQL、Kerberos KDC 和下游服务日志能够串起同一次用户操作。
这个参数的价值不在于少配置一个服务账号,而在于让用户身份穿过数据库继续生效。也正因为如此,启用它应当被视为一次信任模型调整,而不是普通的连接参数优化。