Skip to content

第 9 章 与其他安全技术的对比

原书:Chapter 9. Comparing SPIFFE to Other Security Technologies(p.159–167) 翻译策略:技术直译 + 段落重排;专有项目名、协议名、API 名、CLI 命令、配置字段、证书/加密术语一律保留英文;首次出现的关键概念以"中文(English)"形式给出,后续沿用英文。术语对照见 TERMS.md

章节导言

本章把 SPIFFE 与其他解决类似问题的技术做对比。

引言

SPIFFE 和 SPIRE 解决的问题并不新任何分布式系统都必须有某种形式的身份才能保证安全——比如 Web PKI、Kerberos / Active Directory、OAuth、秘密仓库、以及服务网格**。

然而,这些既有的身份形式并不适合用于标识组织内部的"服务"Web PKI 实现起来很复杂、对典型内部部署来说也不够安全Kerberos(Active Directory 的认证组件)要求一个永远在线的 Ticket Granting Server,并且没有任何对等的证明机制服务网格、秘密管理工具、以及覆盖网络都只解决了"服务身份"这个谜题的一部分——是不完整的SPIFFE 和 SPIRE 是目前唯一对"服务身份问题"给出完整解答的方案

Web PKI

Web PKI 是我们用于"从浏览器连接到安全网站"的一种广泛使用的方法。它利用 X.509 证书来声明"用户正与他/她打算访问的网站相连"由于你可能对这种模式很熟悉,合理的问题就是:为什么我们不能用 Web PKI 来标识组织内部的服务?

在传统的 Web PKI 中,证书的签发与续期完全是手工流程这些手工流程对现代基础设施来说并不合适——在现代基础设施里,服务实例可能随时动态地增减然而,最近几年,Web PKI 已经转向一种自动化的证书签发与续期流程——叫做 Domain Validation(DV)

在 DV 中,CA 向证书申请者发送一个 token证书申请者通过 HTTP server 共享这个 tokenCA 访问这个 token、验证它、然后签发证书

这种安排的首要问题是:内部服务通常没有独立的 DNS 名或 IP 地址如果你想在所有服务之间做互信 TLS,那么连客户端都需要 DNS 名才能拿到证书——这配置起来很麻烦给同一台 host 上跑的多个服务分配身份也要求不同的 DNS 名——这同样很麻烦

关键洞察一个更微妙的问题是:任何能成功响应"对 token 的请求"的人,都能成功获得一张证书这可能是跑在同一台 server 上的另一个服务,甚至是能篡改本地 Layer 2 网络的、不同 server 上的服务

总体来说,Web PKI 在互联网上的安全网站用得很好,但不适合做服务身份许多需要证书的内部服务根本没有 DNS 名当前可用的"做证书校验"的流程,在攻击者成功渗透本地网络上的任何服务时,都很容易被攻破

Active Directory(AD)与 Kerberos

Kerberos 是 1980 年代末在 MIT 最初开发的一种认证协议。最初它被设计为:用一个集中化的用户数据库,实现"人到服务"的认证后来 Kerberos 被扩展为支持"服务到服务"认证,以及使用机器账户(除了用户账户之外)Kerberos 协议本身与账户数据库无关然而,Kerberos 最常见的用途是:在 Windows 域里使用 Active Directory(AD)作为账户数据库进行认证

Kerberos 的核心凭据叫做 ticketticket 是一种凭据——一个客户端可以用它来访问一个资源客户端通过调用 Ticket Granting Service(TGS)来获得 ticket客户端访问的每个资源都需要一张新的 ticket这种设计让协议非常"话痨"——也降低了可靠性

所有服务都与 TGS 有一个信任关系当一个服务向 TGS 注册时,它与 TGS 共享密钥材料(对称密钥或公钥)TGS 用这些密钥材料来签发对服务进行认证的 ticket轮换密钥材料需要服务与 TGS 之间的协调服务必须接受并保持对"前一份密钥材料"的感知——这样现有 ticket 才能保持有效

SPIRE 如何缓解 Kerberos 与 AD 的短板

在 SPIRE 中,每个客户端与资源都会调用一次 SPIRE Server 来获取自己的凭据(SVID)——而所有资源可以在该 Trust Domain(以及联邦 Trust Domain)内认证这些凭据——无需再调用 SPIRE ServerSPIRE 的架构避免了"为每个要访问的资源去获取新凭据"的所有开销

基于 PKI 的认证机制(比如 SPIRE)让凭据轮换更简单——因为服务和集中式认证方之间不再有这种"协调密钥材料"的过程

最后,值得注意:Kerberos 协议把服务与主机名紧密耦合在一起,这让"每台 host 跑多个服务"以及"集群"变得复杂而 SPIRE 很容易支持"每个工作负载多份 SVID"以及集群它也支持把同一份 SVID 分配给多个工作负载这些特性提供了一种既健壮又高度可扩展的身份方案

OAuth 与 OpenID Connect(OIDC)

OAuth 是被设计用于启用访问委托(access delegation)的协议,本身并不是直接用于启用身份认证的协议。OIDC 的主要目的是:允许人类允许一个次级网站(或移动 app)"代表他/她"去访问一个不同的主网站实践中,该协议使得"次级网站能对用户进行认证"成为可能——因为被委托的访问凭据(在 OAuth 协议里就是 access token)来自主网站的"该用户已在我这里认证过"的证明

如果主网站包含用户信息、或提供一种使用 access token 检索用户信息的方法,次级网站就可以使用主网站的 token 来认证用户OpenID Connect 是 OAuth 的一种带观点的子类型,是一个很好的例子

OAuth 是为人设计的,而不是为"非人类实体"设计的OAuth 的登录过程要求一次浏览器跳转、并需要交互式密码OAuth 2.0 与前代类似,并支持非人类实体——通常通过创建 service account(即"代表工作负载而不是人的"用户身份)来实现

当一个工作负载想要获取一个 OAuth access token 去访问一个远程系统时,它必须使用一个 OAuth client secret、密码或 refresh token 来向 OAuth 提供方做认证、并接收 access token工作负载应该各自拥有独立的凭据——以便让工作负载身份具有高粒度这些凭据的管理很快就会变得复杂、对弹性计算来说也很困难——因为每个工作负载和身份都必须向 OAuth 提供方注册长期凭据在需要被吊销时会带来进一步的复杂性由于轮换,凭据在你的环境里四处传播会降低基础设施的灵活性——在某些情况下,如果开发者手工管理凭据,它甚至可能成为一条攻击向量

SPIFFE 和 SPIRE 如何缓解 OAuth 与 OIDC 的复杂度

对工作负载的认证依赖一个"预先存在"的凭据(比如 OAuth client secret 或 refresh token)——这并没有解决"底部的乌龟"问题(如第 1 章所述)在这些场景中把 SPIRE 作为身份提供方,可以在联系 OAuth 基础设施之前签发 bootstrap 凭据、或"底部的乌龟"

SPIRE 显著提升了安全性——因为不再需要把长期静态凭据与工作负载一起部署SPIFFE 可以作为 OAuth 的补充它消除了"直接管理 OAuth 客户端凭据"的需要——应用可以在需要时用它们自己的 SPIFFE ID 向 OAuth 提供方做认证事实上,OAuth access token 本身也可以是 SVID——让用户能够以和工作负载相同的方式,去认证 SPIFFE 生态中的服务详见与 OIDC 的集成

秘密管理工具(Secrets Managers)

秘密管理工具通常代表工作负载或管理员,控制、审计并安全地存储敏感信息(通常是密码这类共享秘密)有些秘密管理工具还能执行其他功能——比如数据的加解密许多秘密管理工具共有的一个特性是:集中式存储,也就是"vault"——它对静态数据进行加密工作负载必须在执行"取秘密"或"解密数据"等动作前单独向 vault 认证

部署秘密管理工具时一个典型的架构挑战是:如何安全地存储"工作负载用来向秘密管理工具自身做认证"的那个凭据这有时被称为"零号凭据(credential zero)"、"bootstrap 凭据",或者更广义地叫"安全引入(secure introduction)"

使用秘密管理工具能大幅改善"依赖共享秘密"的系统的安全姿态——它提供了一种"那些秘密可以被存储、取出、轮换和撤销的安全位置"然而,过度使用秘密管理工具会延续"使用共享秘密"的模式,而不是用强身份

SPIFFE 和 SPIRE 如何缓解秘密管理工具的挑战

如果你确实需要使用秘密管理工具,可以把它配置为使用 SPIFFE 证书做认证这让你能用同一份 SPIFFE 证书来既做"服务间直接认证"、又做"取秘密来与不支持 SPIFFE 的服务通信"

服务网格

服务网格通过提供自动认证、授权、以及在工作负载之间强制互信 TLS,来简化工作负载之间的通信服务网格通常提供集成化的工具

  • 识别工作负载
  • 调节工作负载之间的通信——通常通过部署在每个工作负载旁边的代理(side-car 模式)
  • 确保每个旁边的代理执行一致的认证与授权策略(通常通过一个授权策略引擎)

所有主流的服务网格产品都包含一个原生的、平台特定的服务认证机制

虽然服务网格可以在没有加密身份平面的情况下工作,但不可避免地会创造出"弱形态"的身份——来允许服务到服务的通信和服务发现以这种方式实现的服务网格既不提供安全功能、也没有解决之前讨论的"信任根"身份问题

许多服务网格产品实现了自己的加密身份平面,或与现有的身份方案集成——以同时提供"传输通信安全"与"信任根"大多数服务网格产品实现了 SPIFFE 或其中的一部分许多服务网格实现采用了 SPIFFE 规范的部分实现(包括 Istio 与 Consul,参考 www.consul.io),可以被视作 SPIFFE 身份提供方有些则把 SPIRE 作为其方案的组件(比如 Grey Matter 或 Network Service Mesh)

举例来说,Istio 使用 SPIFFE 做节点识别——但它的身份模型与 Kubernetes 特定的原语紧密耦合、且完全基于这些原语没有办法基于 Kubernetes 之外的属性在 Istio 中识别服务IBM 解释了为什么当前的 Istio 机制还不够developer.ibm.com/articles/istio-identity-spiff...)。这给 Istio 带来了一种约束——相比 SPIRE 这样的通用身份控制平面,当需要更丰富的证明机制、或当服务需要在 Istio 之外用一套通用身份系统做"off-mesh"认证时,Istio 就显得局限用 SPIRE 做工作负载身份的另一个额外好处是:它可以保护那些不受服务网格控制的通信出于这些原因,组织有时会把 SPIRE 与 Istio 集成、并使用 SPIFFE 身份来代替 Istio 内置的身份IBM 在这里发布了一个示例github.com/IBM/istio-spire

服务网格不是 SPIFFE / SPIRE 的直接替代品——它们是互补的,SPIFFE / SPIRE 在网格内充当高层抽象的身份方案

具体实现了 SPIFFE Workload API 的服务网格方案,支持任何期望该 API 可用的软件能够把 SVID 下发给工作负载、并支持 SPIFFE Federation API 的服务网格方案,能自动在"被网格识别的工作负载"和"跑 SPIRE 的工作负载"、以及"跑在不同网格实现上的工作负载"之间建立信任

覆盖网络

覆盖网络(overlay network)在多个平台上为服务模拟出一个统一的网络。与服务网格不同,覆盖网络使用标准的网络概念(比如 IP 地址和路由表)来连接服务数据被封装并跨其他网络路由——在现有网络之上构建出一张由节点和逻辑链路组成的虚拟网络

虽然最常见的覆盖网络没有任何认证功能,但最新的一些已经有了然而,它们在允许服务连接之前仍然不对服务的身份进行证明通常,它们依赖一份"预先存在的"证书SPIFFE 很适合为覆盖网络的节点提供证书


下一章:第 10 章 从业者故事

基于 VitePress 构建