跳至正文
Starone

安全

零信任应用架构

零信任的含义是:没有任何请求会因为它的来源位置而获得授权。落到实处,就是工作负载身份、短期凭证,以及对每一次调用都进行的策略评估。

· 阅读约 5 分钟 · Starone 工程团队

零信任是一种架构属性,而不是一款产品。当没有任何请求会因为它所来自的网络而获得授权时,这个系统就具备了零信任。每一次调用都携带可验证的身份,每一次调用都要对照策略进行检查,某个组件被攻破后,攻击者得到的也只是该组件自身身份被允许做的事情。

我们的看法是,大部分价值来自三项并不起眼的工作:给每个工作负载一个身份,消除长期有效的密钥,把授权逻辑从散落各处的应用代码中移出来,变成可以评审的策略。网络分段仍然重要,但它是第二层防护,而不是信任的基础。

身份就是边界

边界模型假设网络内部的一切都是友好的。只要有一个 Pod、一台笔记本或一个依赖被攻破,这个假设就不成立了,因为攻击者继承了整个网段的信任。横向移动是可以预见的结果。

用身份取代位置之后,每个服务要问的问题就变了。它不再问请求是否来自内网子网,而是问调用方是谁、凭什么证明、这个调用方是否可以对这个资源执行这个操作。需要考虑的身份始终有两个:发起调用的工作负载,以及该调用所代表的最终用户。

服务身份与双向 TLS

工作负载身份应当由平台签发,而不是手工配置。SPIFFE 是通行的模型:每个工作负载获得一张短期有效的 X.509 证书,其身份由经过证明的属性推导而来,例如它的 Kubernetes service account 和 namespace。随后由服务网格或类库使用这些证书建立双向 TLS(mTLS),于是每条连接的两端都经过认证,流量也得到加密。

mTLS 经常被误认为就是全部解决方案。它证明的是哪个服务在发起调用。至于这个服务是否应当被允许调用这个端点,它什么也没说,也不携带任何关于用户的信息。只有认证而没有在其上叠加授权策略,得到的只是一张加密的扁平网络。

用短期凭证取代存储的密钥

放在环境变量里的静态 API key 会一直有效,直到有人想起来去轮换它,而且在攻击者的机器上同样好用。短期凭证把这个窗口缩短到分钟级,也免去了大部分轮换负担,因为过期本身就是轮换。

  • 通过 OIDC 与云服务商建立工作负载身份联合,取代存储的访问密钥
  • 数据库凭证按需签发并带有租约,例如使用 Vault 的动态密钥(dynamic secrets)
  • CI 流水线用签名的作业令牌换取范围受限、有时效的部署权限
  • 用户令牌采用较短的有效期和受众限制,刷新在边缘层处理

把策略决策与策略执行分开

授权由两部分组成。策略执行点拦截请求,并放行或阻断。策略决策点评估规则并返回结果。把两者分开,意味着策略只需编写一次,可以做版本管理、测试和评审,而不必在每个服务里用条件判断重新实现一遍。

实际的设计问题是决策在哪里运行。集中式的决策服务容易推理,但会给每个请求增加一次网络跳转和一个单点故障。我们的默认做法是本地评估:让 Open Policy Agent 这类引擎运行在服务旁边或网关内部,再把策略包分发给它。决策耗时在微秒级,并且在控制平面中断时仍能工作。代价是策略变更的传播存在延迟,这个延迟在撤销权限的场景下必须是可以接受的。

要提前决定当决策无法做出时该怎么办。对于任何会改变状态或暴露数据的操作,失败时拒绝(fail closed)是正确的。对于可用性更重要的低风险读路径,失败时放行(fail open)偶尔也说得过去,但这种例外应当写成文档,而不是在事故中才被发现。

最小权限必须延伸到数据层

一个常见的缺口是:前面是认证完善的服务网格,后面的服务却都以同一个高权限用户连接数据库。大门口的检查是真实的,但在它后面,每个服务都是一个什么都能读的混淆代理人(confused deputy)。

补上这个缺口,意味着把最终用户的上下文沿调用链传递下去,并在每一跳收窄它。令牌交换让服务可以把收到的令牌换成一个仅限于它所需的那一个下游受众的令牌。每个服务拥有自己的数据库角色,只能访问自己的表;在数据模型允许的地方,再由行级策略应用用户或租户上下文。

  • 每个服务一个身份,绝不使用共享的平台账号
  • 令牌限定受众,使被窃取的令牌无法在别处重放
  • 服务之间默认拒绝,每条允许的路径都显式声明

为什么 VPN 不是零信任

VPN 对设备认证一次,然后把它放进一个网络。从这个网络能访问到的一切,在会话持续期间也都能从这台设备访问到。这仍然是边界模型,只不过网线更长了。它还让 VPN 集中器成为一个高价值的单一目标。

身份感知代理把这件事反了过来。每个应用单独发布,每个请求都经过认证和授权,设备状态也可以成为决策的一部分。获得某一个内部工具的访问权,并不附带其他任何权限。对于无法放到代理后面的遗留协议,VPN 仍然是合理的选择,前提是把它当作传输通道,而不是授权手段。

从哪里开始,以及什么时候不必做

零信任有实实在在的成本:证书基础设施、策略工具链、更多需要排查的活动部件,以及一支必须理解这一切的工程团队。对于只有一个数据库、团队规模不大的单个模块化单体来说,一整套服务网格加上逐请求的策略评估并不相称。强用户认证、托管的密钥存储和相互独立的数据库角色,就能带来大部分收益。

对于服务众多、涉及多个团队或处理敏感数据的系统,我们会从工作负载身份和清除静态密钥入手,然后以审计模式引入策略,先观察哪些调用会被拒绝,再开始强制执行。在一个没人度量过真实调用图的系统上直接强制执行默认拒绝策略,正是宕机的由来。

正在做类似的事情

我们很乐意交流心得。欢迎与撰写本文的工程师聊聊。