SPIFFE 和 SPIRE 概念介绍

在第三章介绍的概念基础上,本章说明了 SPIFFE 标准。解释 SPIRE 实现的组成部分以及它们是如何结合在一起的。最后,讨论威胁模型以及如果特定组件被破坏会发生什么。

什么是 SPIFFE?

普适安全生产身份框架(SPIFFE)是一套软件身份的开源标准。为了以一种与组织和平台无关的方式实现可互操作的软件身份,SPIFFE 定义了必要的接口和文件,以完全自动化的方式获得和验证加密身份。

图 4.1:SPIFFE 组件。
图 4.1:SPIFFE 组件。

  • SPIFFE ID,代表软件服务的名称(或身份)。
  • SPIFFE 可验证身份文件(SVID),这是一个可加密验证的文件,用于向对等者证明服务的身份。
  • SPIFFE Workload API,这是一个简单的节点本地 API,服务用它来获得身份,而不需要认证。
  • SPIFFE Trust Bundle(信任包),一种代表特定 SPIFFE 发行机构使用的公钥集合的格式。
  • SPIFFE Federation,这是一个简单的机制,通过它可以共享 SPIFFE Trust Bundle。

SPIFFE 不是什么

SPIFFE 旨在识别服务器、服务和其他通过计算机网络通信的非人类实体。这些都有一个共同点,那就是这些身份必须是可以自动发出的(没有人类在其中参与)。虽然有可能使用 SPIFFE 来识别人或其他野生动物物种,但该项目特意将这些用例排除在范围之外。除了机器人和机器之外,没有其他特别的考虑。

SPIFFE 向服务提供身份和相关信息,同时管理该身份的生命周期,但它仅仅作为提供者,因为它不直接利用其提供的身份。利用 SPIFFE 身份是服务的责任。在使用 SPIFFE 身份时,有多种解决方案可以实现认证层,如端到端加密通信或服务间授权和访问控制,但是,这些功能也被认为不属于 SPIFFE 项目的范围,SPIFFE 不会直接解决这些问题。

SPIFFE ID

SPIFFE ID 是一个字符串,作为服务的唯一名称。它被模拟成一个 URI,由几个部分组成。前缀 spiffe://(作为 URI 的方案),信任域的名称(作为主机部分),以及特定工作负载的名称或身份(作为路径部分)。

一个简单的 SPIFFE ID 可能只是 spiffe://example.com/myservice

图 4.2:一个 SPIFFE ID 示例,以及它的组成。
图 4.2:一个 SPIFFE ID 示例,以及它的组成。

SPIFFE ID 的第一个组成部分是 spiffe:// URI 方案。虽然很普通,但包括它是一个重要的细节,因为它有助于将 SPIFFE ID 与 URL 或其他类型的 URL 区分开来。

SPIFFE ID 的第二个组成部分是信任域名称(example.com)。在某些情况下,整个组织只有一个信任域。在其他情况下,可能需要有许多信任域。信任域的语义将在本章后面介绍。

最后一个组成部分是工作负载本身的名称部分,由 URI 路径表示。SPIFFE ID 的这一部分的具体格式和组成是因地制宜的。各机构可以自由选择对其最有意义的命名方案。例如,我们可以选择一个既能反映组织位置又能反映工作负载目的的命名方案,如:

 spiffe://example.com/bizops/hr/taxrun/withholding

值得注意的是,SPIFFE ID 的主要目的是以一种灵活的方式来表示工作负载的身份,使人类和机器都能轻松使用。当试图在 SPIFFE ID 的格式中灌输太多的意义时,应该谨慎行事。例如,试图编纂后来被用作授权元数据的各个部分的属性,会导致互操作性和灵活性的挑战。相反,建议使用一个单独的数据库

SPIFFE 信任域

SPIFFE 规范引入了信任域的概念。信任域被用来管理组织内部和组织之间的管理和安全边界,每个 SPIFFE ID 都有其信任域的名称,如上所述。具体来说,信任域是 SPIFFE ID 命名空间的一部分,在这个命名空间中,一组特定的公钥被认为是权威的。

由于不同的信任域有不同的签发机构,一个信任域的破坏不会危及另一个信任域。这是一个重要的属性,使互不信任的各方之间能够进行安全通信,例如,在 staging 和生产之间或一个公司和另一个公司之间。

跨越多个信任域验证 SPIFFE 身份的能力被称为 SPIFFE Federation,在本章后面介绍。

SPIFFE 可验证身份文件(SVID)

SPIFFE 可验证身份文件(SVID)是一个可加密验证的身份文件,用于向对等体证明一个服务的身份。SVID 包括一个单一的 SPIFFE ID,并由代表服务所在的信任域的签发机构签署。

与其发明一种新的文件类型让软件支持,SPIFFE 选择利用那些已经被广泛使用并被充分理解的文件类型。在撰写本报告时,有两种身份文件被定义为 SPIFFE 规范中的 SVID 使用:X.509 和 JWT。

X509-SVID

X509-SVID 将 SPIFFE 身份编码为标准 X.509 证书。相应的 SPIFFE ID 被设置为主题替代名称(SAN)扩展字段中的 URI 类型。虽然 X509-SVID 上只允许设置一个 URI SAN 字段,但证书可以包含任何数量的其他类型的 SAN 字段,包括 DNS SAN。

建议尽可能使用 X509-SVID,因为它们比 JWT-SVID 有更好的安全属性。具体来说,当与 TLS 结合使用时,X.509 证书不能被中间人记录和重放。

利用 X509-SVID 可能有额外的要求,请参考 X509-SVID 规范部分

JWT-SVID

JWT-SVID 将 SPIFFE 身份编码为一个标准的 JWT—— 特别是一个 JWS。JWT-SVID 被用作承载令牌,在应用层向对等者证明身份。与 X509-SVID 不同,JWT-SVID 受到一类被称为 重放攻击的威胁,即令牌被未经授权的一方获得并重新使用。

SPIFFE 规定了三种机制来缓解这种攻击媒介。首先,JWT-SVID 必须只通过安全通道传输。其次,受众声明( aud 声明)必须被设置为与令牌的目的方严格匹配的字符串。最后,所有的 JWT-SVID 必须包括一个过期时间,限制被盗令牌的有效期限。

尤其需要注意的是,尽管有这些缓解措施,JWT-SVID 从根本上说仍然容易受到重放攻击,因此应该谨慎使用并小心处理。也就是说,它们是 SPIFFE 规范集的一个重要部分,因为它们允许 SPIFFE 认证在不可能建立端到端通信渠道的情况下发挥作用。

利用 JWT-SVID 可能有额外的要求,请参考 JWT-SVID 规范部分

SPIFFE 信任包

SPIFFE 信任包是一个包含信任域公钥的文件。每种 SVID 类型都有一个特定的方式在这个包中表示出来(例如,对于 X509-SVID,包括代表公钥的 CA 证书)。每个 SPIFFE 信任域都有一个与之相关的捆绑包,该捆绑包中的材料被用来验证声称位于该信任域中的 SVID。

由于信任包不包含任何秘密(只有公钥),它可以安全地与公众分享。尽管这一事实,它确实需要安全地分发,以保护其内容不被擅自修改。换句话说,保密性是不需要的,但完整性是需要的。

SPIFFE 捆绑包的格式是 JWK Set(或 JWKS 文档),与现有的认证技术如 OpenID Connect 兼容。JWKS 是一种灵活且被广泛采用的格式,用于表示各种类型的加密密钥和文件,在新的 SVID 格式被定义的情况下,它提供了一些未来证明。

SPIFFE Federation

通常,允许在不同信任域的服务之间进行安全通信是可取的。在许多情况下,你不能把所有的服务放在一个信任域中。一个常见的例子是两个不同的组织需要相互通信。另一个例子可能是一个组织需要建立安全边界,也许是在信任度较低的云环境和高度信任的内部服务之间。

为了能够实现这一点,每个服务必须拥有远程服务所来自的外部信任域的捆绑包(Bundle)。因此,SPIFFE 信任域必须公开或以其他方式分享其捆绑包内容,使外部信任域中的服务能够验证来自本地信任域的身份。用于共享信任域的捆绑内容的机制被称为捆绑端点(Bundle Endpoint)

捆绑端点是简单的 TLS 保护的 HTTP 服务。希望与外部信任域联合的运营商必须用外部信任域的名称和捆绑端点的 URL 来配置他们的 SPIFFE 实现,允许定期获取捆绑包的内容。

图 4.3: 有两个不同的信任域通过联邦连接的公司架构的说明。每个 SPIRE 服务器只能为自己的信任域签署 SVID。
图 4.3: 有两个不同的信任域通过联邦连接的公司架构的说明。每个 SPIRE 服务器只能为自己的信任域签署 SVID。

SPIFFE Workload API

SPIFFE Workload API 是一个本地的、非网络化的 API,工作负载用它来获取当前的身份文件、信任捆绑和相关信息。重要的是,这个 API 是未经认证的,不要求工作负载拥有任何预先存在的证书。将这一功能作为本地 API 提供,允许 SPIFFE 实现者提出创造性的解决方案,在不需要直接认证的情况下识别调用者(例如,利用操作系统提供的功能)。Workload API 以 gRPC 服务器的形式公开,并使用双向流,允许根据需要将更新推入工作负载。

Workload API 不要求调用的工作负载对自己的身份有任何了解,也不要求调用 API 时拥有任何凭证。这就避免了在工作负载旁边部署任何认证秘密的需要。

图 4.4:工作负载 API 提供信息和设施来利用 SPIFFE 的身份。
图 4.4:工作负载 API 提供信息和设施来利用 SPIFFE 的身份。

SPIFFE 工作负载 API 向工作负载提供 SVID 和信任包,并在必要时对其进行轮换。

什么是 SPIRE?

SPIFFE 运行环境(SPIRE)是 SPIFFE 规范中所有五个部分的一个生产可用的开源实现。

SPIRE 项目(以及 SPIFFE)由云原生计算基金会主办,该基金会由许多领先的基础设施技术公司成立,为有利于云原生社区的开源项目提供一个中立的家园。

SPIRE 有两个主要组成部分:服务器和代理。服务器负责验证代理和构建 SVID,而代理则负责为 SPIFFE Workload API 提供服务。这两个组件都是使用面向插件的架构编写的,因此它们可以很容易地被扩展,以适应大量不同的配置和平台。

SPIRE 架构

SPIRE 的架构由两个关键组件组成,即 SPIRE 服务器和 SPIRE 代理。

SPIRE 服务器

SPIRE 服务器管理和发布 SPIFFE 信任域中的所有身份。它使用一个数据存储来保存关于其代理和工作负载等的信息。SPIRE 服务器通过使用注册条目获知其管理的工作负载,注册条目是为节点和工作负载分配 SPIFFE ID 的灵活规则。

该服务器可以通过 API 或命令行命令进行管理。需要注意的是,由于服务器掌握着 SVID 的签名密钥,它被认为是一个重要的安全组件。在决定它的位置时应特别考虑。这一点将在本书后面讨论。

数据存储

SPIRE 服务器使用一个数据存储来跟踪其当前的注册条目,以及它所发布的 SVID 的状态。目前,支持几种不同的 SQL 数据库。SPIRE 内置 SQLite,这是一个内存中的嵌入式数据库,用于开发和测试目的。

上游机构

一个信任域中的所有 SVID 都由 SPIRE 服务器签署。默认情况下,SPIRE 服务器会生成一个自签名证书(用自己随机生成的私钥签名的证书)来签署 SVID,除非配置了一个 上游证书机构(Upstream Certificate Authority) 插件接口。上游证书授权的插件接口允许 SPIRE 从另一个证书授权机构获得其签名证书。

在许多简单的情况下,使用自签名的证书就可以了。然而,对于较大的安装,可能需要利用预先存在的证书颁发机构和 X.509 证书的分层性质,使多个 SPIRE 服务器(和其他生成 X.509 证书的软件)一起工作。

在一些组织中,上游证书颁发机构可能是一个中央证书颁发机构,你的组织在其他方面使用它。如果你有许多不同种类的证书在使用,而且你希望它们在你的基础设施中都被信任,那么这就很有用。

SPIRE 代理

SPIRE 代理只有一个功能,尽管是一个非常重要的功能:为 Workload API 服务。在完成这一壮举的过程中,它解决了一些相关的问题,如确定工作负载的身份,调用它,并安全地将自己介绍给 SPIRE 服务器。在这种安排中,它是执行所有重任的代理。

代理不需要像 SPIRE 服务器那样的主动管理。虽然它们确实需要一个配置文件,但 SPIRE 代理从 SPIRE 服务器直接接收有关本地信任域和可能调用它的工作负载的信息。在给定的信任域中定义新的工作负载时,只需在 SPIRE 服务器中定义或更新记录,有关新工作负载的信息就会自动传播给相应的代理。

图 4.5:SPIRE 代理暴露了 SPIFFE Workload API,并与 SPIRE 服务器一起工作,向调用代理的工作负载发布身份信息。
图 4.5:SPIRE 代理暴露了 SPIFFE Workload API,并与 SPIRE 服务器一起工作,向调用代理的工作负载发布身份信息。

插件架构

SPIRE 是作为一套插件建立的,因此很容易扩展,以适应新的节点验证器、工作负载验证器和上游机构。

图 4.6:SPIRE 支持的密钥插件接口说明。服务器包括 Node Attestor、KeyManager 和 Upstream Authority 插件,而 Agent 端包括 Node Attestor 和 Workload Attestor 插件。
图 4.6:SPIRE 支持的密钥插件接口说明。服务器包括 Node Attestor、KeyManager 和 Upstream Authority 插件,而 Agent 端包括 Node Attestor 和 Workload Attestor 插件。

SVID 管理

SPIRE 代理使用其在节点认证期间获得的身份,向 SPIRE 服务器进行认证,并获得其被授权管理的工作负载的 SVID。由于 SVID 是有时间限制的,代理还负责根据需要更新 SVID,并将这些更新传达给相关工作负载。信任捆绑也会轮换和接收捆绑包,这些更新由代理跟踪并传达给工作负载。代理维护所有这些信息的内存缓存,因此,即使 SPIRE 服务器停机,也可以提供 SVID,而且还可以确保 Workload API 响应的性能,因为当有人调用工作负载 API 时,不需要往返于服务器。

证明

证明是一个过程,通过这个过程可以发现和断言有关工作负载及其环境的信息。换句话说,它是一个利用现有信息作为证据证明工作负载身份的过程。

在 SPIRE 中,有两种类型的证明:节点和工作负载证明。节点证明主张描述节点的属性(例如,特定 AWS 自动扩展组的成员,或节点位于哪个 Azure 区域),而工作负载证明主张描述工作负载的属性(例如,它正在运行的 Kubernetes 服务账户,或磁盘上的二进制文件的路径)。这些属性在 SPIRE 中的表述被称为选择器(Selector)

SPIRE 支持几十种开箱即用的选择器类型,而且这个列表还在继续增加。截至本文撰写之时,节点验证器列表包括对裸机、Kubernetes、亚马逊网络服务、谷歌云平台、Azure 等的支持。工作负载验证器包括对 Docker、Kubernetes、Unix 等的支持。

此外,SPIRE 的可插拔架构允许运营商轻松扩展系统,以支持他们认为合适的其他选择器类型。

节点证明

节点认证发生在代理首次启动时。在节点认证中,代理与 SPIRE 服务器联系并进行交流,服务器旨在积极识别代理正在运行的节点及其所有相关选择器。为了实现这一目标,在代理和服务器中都运行了一个特定平台的插件。例如,在 AWS 的情况下,代理插件从 AWS 收集只有该特定节点可以访问的信息(由 AWS 密钥签署的文件),并将其传递给服务器。然后,服务器插件验证 AWS 的签名,并进一步调用 AWS 的 API,以断定该声明的准确性,并收集有关该节点的额外选择器。

成功的节点认证会导致其向有关的代理发放身份。然后,代理使用这个身份进行所有进一步的服务器通信。

图 4.7:在 AWS 中运行的节点的节点证明。
图 4.7:在 AWS 中运行的节点的节点证明。

  1. 代理收集节点的身份证明,调用 AWS 的 API。
  2. 代理将此身份证明发送给服务器。
  3. 服务器通过调用 AWS API 验证步骤 2 中获得的身份证明,然后为代理创建一个 SPIFFE ID。

工作负载证明

工作负载认证是确定工作负载身份的过程,它将导致身份文件的发布和交付。在工作负载调用并建立与 SPIFFE Workload API 的连接时(在工作负载对 API 的每一次 RPC 调用中),都会进行认证,而此后的过程则由 SPIRE 代理上的一组插件驱动。

当代理收到来自调用工作负载的新连接时,代理将利用操作系统功能来确定到底是哪个进程打开了新连接。所利用的操作系统功能将取决于代理运行的操作系统。在 Linux 的情况下,代理将进行系统调用,以检索进程 ID,用户标识符,以及在特定套接字上调用的远程系统的全局唯一标识符。在 BSD 和 Windows 中,要求的内核元数据将是不同的。反过来,代理将向验证器插件提供调用工作负载的 ID。从这里开始,验证器在其插件中扇出,提供关于调用者的额外进程信息,并以选择器的形式将其返回给代理。

每个验证器插件负责对调用者进行内省,生成一组描述调用者的选择器。例如,一个插件可以查看内核级别的细节,并生成选择器,如进程以何种身份运行的用户和组,而另一个插件可以与 Kubernetes 通信,并生成选择器,如进程运行的命名空间和服务账户。第三个插件可以与 Docker 守护进程通信,并生成 Docker 镜像 ID、Docker 标签和容器环境变量的选择器。

图 4.8: 工作负载证明。
图 4.8: 工作负载证明。

  1. 工作负载调用 Workload API 请求 SVID。
  2. 代理询问节点的内核以获得调用进程的属性。
  3. 代理得到发现的选择器。
  4. 代理通过比较发现的选择器和注册条目来确定工作负载的身份,并向工作负载返回正确的 SVID。

登记条目

为了让 SPIRE 发布工作负载身份,它必须首先了解其环境中预期或允许的工作负载;哪些工作负载应该在哪里运行,它们的 SPIFFE ID 和一般组成应该是什么。SPIRE 通过注册条目了解这些信息,注册条目是使用 SPIRE API 创建和管理的对象,包含上述信息。

对于每个注册条目,有三个核心属性。第一个被称为 Parent ID—— 这实际上是告诉 SPIRE 一个特定的工作负载应该在哪里运行(以及延伸到哪些代理被授权代表它询问 SVID)。第二个是 SPIFFE ID—— 当我们看到这个工作负载时,我们应该向它发出什么 SPIFFE ID?最后,SPIRE 需要一些信息来帮助它识别工作负载,这就是证明中选择器的作用。

图 4.9:注册条目的三个核心属性。
图 4.9:注册条目的三个核心属性。

注册条目将 SPIFFE ID 与它们所代表的节点和工作负载绑定。

注册条目既可以描述一组节点,也可以描述一个工作负载,后者通常使用 Parent ID 来引用前者。

节点条目

描述一个节点(或一组节点)的注册条目使用由节点认证产生的选择器来分配一个 SPIFFE ID,这在以后注册工作负载时可以被引用。一个节点可以被证明有一组与多个节点条目相匹配的选择器,从而允许它加入一个以上的组。在决定一个特定的工作负载被允许运行的确切位置时,这提供了很大的灵活性。

SPIRE 自带各种节点验证器可供使用,每个验证器都会生成特定平台的选择器。虽然 SPIRE 服务器支持一次加载多个节点验证器插件,但 SPIRE 代理只支持加载一个。目前可用的节点选择器包括:

  • 在谷歌云平台(GCP)上。
  • 在 Kubernetes 上,该节点所处的 Kubernetes 集群的名称。
  • 在亚马逊网络服务(AWS),节点的 AWS 安全组。

节点条目的 Parent ID 被设置为 SPIRE 服务器的 SPIFFE ID,因为是服务器在进行验证,并断言有关节点确实符合条目定义的选择器。

工作负载条目

描述工作负载的注册条目使用由工作负载证明产生的选择器,在满足一定条件的情况下为工作负载分配一个 SPIFFE ID。当 Parent ID 和选择器的条件得到满足时,工作负载可以得到一个 SPIFFE ID。

工作负载条目的 Parent ID 描述了该工作负载被授权运行的地方。其值是一个节点或一组节点的 SPIFFE ID。在节点上运行的 SPIRE 代理会收到该工作负载条目的副本,包括在为该特定条目发出 SVID 之前必须证明的选择器。

当工作负载调用代理时,代理进行工作负载验证,并将发现的选择器与条目中定义的选择器进行交叉对比。如果一个工作负载拥有整个定义的选择器集,那么条件就得到了满足,该工作负载就会得到一个带有定义的 SPIFFE ID 的 SVID。

与节点认证不同,SPIRE 代理支持同时加载许多工作负载验证器插件。这允许在工作负载条目中混合匹配选择器。例如,工作负载条目可能要求工作负载在特定的 Kubernetes 命名空间中,在其 Docker 镜像上应用特定的标签,并具有特定的 SHA 和。

SPIFFE/SPIRE 应用的概念威胁模型

SPIFFE 和 SPIRE 所面临的一系列具体威胁是情景性的。了解 SPIFFE/SPIRE 的一般威胁模式是断言你的具体需求可以得到满足的重要步骤,也是发现可能需要进一步缓解的地方。

在本节中,我们将描述 SPIFFE 和 SPIRE 的安全边界,以及系统中每个组件被破坏的影响。在本书的后面,我们将介绍不同的 SPIRE 部署模式所带来的具体安全考虑。

假设

SPIFFE 和 SPIRE 旨在作为分布式身份和认证的基础,与云原生设计架构一致。SPIRE 支持 Linux 和 BSD 系列(包括 MacOS)。目前不支持 Windows,尽管在这个领域已经做了一些早期的原型设计。

SPIRE 坚持零信任网络安全模型,其中假定网络通信是敌对的或可能完全被破坏。也就是说,还假设 SPIRE 组件运行的硬件以及其操作人员是值得信赖的。如果硬件植入或内部威胁是威胁模型的一部分,应围绕 SPIRE 服务器的物理位置和其配置参数的安全性进行仔细考虑。

根据所选择的节点和工作负载证明方法,可能进一步隐含对第三方平台或软件的信任。通过多个独立的机制来证明信任,可以提供更多的信任证明。例如,利用基于 AWS 或 GCP 的节点证明,意味着计算平台被认为是值得信赖的,而利用 Kubernetes 的工作负载证明,意味着 Kubernetes 的部署被认为是值得信赖的。由于完成证明的方式多种多样,而且 SPIRE 架构是完全可插拔的,因此本评估不考虑这些流程的安全性(和相关假设)。相反,它们应逐一进行评估。

图 4.10:作为威胁模型的一部分被考虑的组件。
图 4.10:作为威胁模型的一部分被考虑的组件。

安全边界

安全边界在形式上被理解为两个不同信任程度的区域之间的交汇线。

SPIFFE/SPIRE 定义了三个主要的安全边界:一个是工作负载和代理之间,一个是代理和服务器之间,还有一个是不同信任域的服务器之间。在这个模型中,工作负载是完全不受信任的,其他信任域中的服务器也是如此,如前所述,网络通信始终是完全不受信任的。

图 4.11:SPIFFE/SPIRE 的安全边界。
图 4.11:SPIFFE/SPIRE 的安全边界。

工作负载 | 代理边界

随着人们在系统中的移动和跨越这些边界,信任程度会慢慢增加。从工作负载开始,我们跨越安全边界进入代理。通常预计(尽管不是必须的),工作负载和代理之间存在超越 SPIRE 设计的安全机制,例如利用 Linux 用户权限和 / 或容器化。

代理不相信工作负载会提供任何形式的输入。代理对工作负载身份的所有断言都是通过带外检查做出的。在工作负载证明的背景下,这是一个重要的细节 —— 任何选择器的值可以被工作负载本身操纵,这本身就是不安全的。

代理 | 服务器边界

下一个边界存在于代理和服务器之间。代理比工作负载更值得信任,但比服务器更不值得信任。SPIRE 的一个明确的设计目标是,它应该能够在节点受到威胁的情况下存活。由于工作负载是完全不可信的,我们在任何给定的时间点上离节点只有一到两次攻击威胁。代理有能力代表工作负载创建和管理身份,但也有必要将任何特定代理的权力限制在它完成任务所严格需要的范围内(遵循最小特权原则)。

为了减轻节点(和代理)受到威胁的影响,SPIRE 需要了解特定工作负载被授权运行的地方(以 Parent ID 的形式)。代理必须能够证明注册条目的所有权,然后才能为其获得身份。因此,被攻击的代理不能获得任意的身份 —— 它们只能获得首先应该在节点上运行的工作负载的身份。

值得注意的是,在节点认证过程中,SPIRE 服务器和 SPIRE 代理之间的通信可以在不同的时间点使用 TLS 和相互 TLS,这取决于节点是否尚未被认证,或者代理是否已经拥有有效的 SVID 并可以将其用于相互 TLS,此时服务器和代理之间的所有通信是安全的。

服务器 | 服务器边界

最后的边界存在于不同信任域的服务器之间。SPIRE 服务器只被信任为在其直接管理的信任域内构造的 SVID。当 SPIRE 服务器相互联合并交换公钥信息时,它们收到的秘钥仍然是在它们所收到的信任域范围内的。与网络 PKI 不同,SPIFFE 不会简单地把所有的公钥扔到一个大的混合包里。其结果是,如果外部信任域的破坏不会导致本地信任域的 SVID 的构造能力。

应该注意的是,SPIRE 服务器没有任何多方保护。信任域中的每个 SPIRE 服务器都可以访问签名密钥,它可以用这些密钥构造 SVID。服务器之间存在的安全边界严格限于不同信任域的服务器,不适用于同一信任域内的服务器。

组件被破坏后的影响

虽然工作负载总是被认为是被破坏的,但预计代理一般不会被破坏。如果一个代理被破坏,攻击者将能够访问相应代理被授权管理的任何身份。在工作负载和代理之间存在 1:1 关系的部署中,这一点不太值得关注。在代理管理多个工作负载的部署中,这是一个需要理解的重要问题。

当代理被引用为某一身份的父代时,它们被授权管理该身份。由于这个原因,在合理的范围内,将注册条目父身份的范围尽可能地缩小是一个好主意。

在服务器被破坏的情况下,可以预计,攻击者将能够在该信任域内构造任意的身份。SPIRE 服务器无疑是整个系统中最敏感的组成部分。在管理和放置这些服务器时应小心谨慎。例如,SPIRE 解决了节点破坏的问题,因为工作负载不受信任,但如果 SPIRE 服务器与不受信任的工作负载在同一主机上运行,那么服务器就不再享有曾经由代理 / 服务器安全边界提供的保护。因此,强烈建议将 SPIRE 服务器放在与它们要管理的不受信任的工作负载不同的硬件上。

代理的注意事项

SPIRE 通过将一个代理的权限限定在它直接被授权管理的身份上,来说明节点的破坏…… 但如果攻击者可以破坏多个代理,或者也许是所有的代理,情况就明显要糟糕得多。

SPIRE 代理之间没有任何通信途径,大大限制了代理之间横向移动的可能性。这是一个重要的设计决定,旨在减轻可能的代理漏洞的影响。然而,应该理解的是,某些配置或部署选择可能部分或全部破坏这种缓解。例如,SPIRE 代理支持暴露一个 Prometheus 指标端点,然而,如果所有代理都暴露这个端点,并且那里存在漏洞,那么横向移动就变得轻而易举,除非有足够的网络级别控制。出于这个原因,我们强烈不建议将 SPIRE 代理暴露于传入的网络连接。