有人提议把 PostgreSQL 登录直接交给客户,好让报销申请端到端加密传输。数据库管理员需要的是真正的 SQL 会话,而另一些人又提议改用网页表单。两种提议都解决错了问题,因为它们都没有从客户实际执行的操作出发。按顺序走完这三个决定,TLS 能否替代 VPN 这个问题自然就有答案。

从客户需要的操作出发

先写下客户要完成什么。提交报销、读取报表中的一行、执行临时查询,是三种风险特征不同的操作。

再写下谁在发起请求。客户、支持人员和数据库管理员即使动的是同一张表,也不能彼此替换。这个差别决定了客户到底应该看到多少查询语言。

这两个答案一同决定接口。此后的一切都是实现,而多数关于加密的争论其实是关于选了哪个接口的争论。

三种控制,三个决定

经过认证的 TLS 保护连接,并决定接受哪些 TLS 身份。 网络入口决定哪些来源能够到达监听端。数据库授权决定某个角色可以使用哪些对象和操作。

三者中没有任何一个可以替代另外两个,表格把这一点写得很清楚。

ControlWhat it decidesWhat it leaves open
Authenticated TLSConnection protection and which TLS identities are acceptedWhich tables a database user may touch
Restricted network entryWhich sources reach the listenerWhether an authenticated user should run a given statement
Database authorizationWhich objects and actions a role may useWhether the connection arrived by an approved path

在删掉另一行之前,先读清楚你所依赖的那一行。这类设计大多失败,是因为某个控制被假定存在,而不是被真正配置。

直连 SQL 让数据库策略继续负责

在获批的直连场景里,服务身份的校验和预期的访问策略都要保留。打开 TLS 只是让加密连接可用;除非访问配置通过 hostssl 条目明确要求,它并不会拒绝未加密的连接。

这个区别值得在运行中的配置里核对,而不是在模板里。一个提供 TLS 却接受明文的服务器,并不是多数人以为自己部署的方案。读一遍访问规则,看看哪些条目真的要求加密。仅这一项检查,就能把能加密的服务器与只加密的服务器区分开。

只给角色分配工作所需的权限,并复查所有权、继承成员身份和过宽的授权。 PostgreSQL 权限模型 是数据库对象的权限边界。

VPN 可以在数据库认证之前限制哪些设备能到达服务,访问网关也能做类似的事。两者都不消除维护对外组件、管理凭据和限制资源使用的必要。

客户端证书是一种凭据,不是 ACL

客户端证书可以在连接时增加一项要求。 clientcert 设置可以要求受信任的证书,在更严格的模式下还要求证书名与数据库用户之间存在对应关系。

这是更强的凭据。它不是授权列表,也不会让服务器隐身,因为接受连接的那个组件仍然要处理网络流量和握手。把证书当成访问列表,实际权限一点没变。它还往往扩大证书的分发范围,于是引出下一个问题。

把一个强证书绑在权限过大的角色上,得到的是一个认证得很好的管理员。在庆祝证书之前,先检查角色。

合适时就选更窄的接口

对报销来说,一个接收申请、执行业务规则并返回该用户被允许看到的结果的应用端点,比一个通用 SQL 账号更能代表这项操作。

然后应用使用自己受限的数据库身份,客户始终不会把查询语言当成一项功能拿到。这是更小的暴露面,出错的方式也更少。

这是一种设计选择,而不是说应用代码就自动更安全。那段代码同样要认证调用方、为每个动作授权并校验输入,它自己的数据库权限依然重要。

对获批工作需要直连 SQL 的人和工具来说,直连依然正确。用角色、网络范围和运维限制为这种设计划界,让其他客户端保留更窄的接口。把两类人混在一个角色里,正是争论开始的地方。

相关文章