一、背景
1.1 什么是零信任
零信任从根本上讲是关于信任。它是解决安全核心问题之一的模型:是否允许 X 访问 Y?换句话说,我们是否相信 X 可以访问 Y?
它是一种安全理念和架构,旨在保护计算机网络免收恶意攻击和数据泄露的威胁。零信任模型的核心理念是不相信任何用户、设备或网络。它要求在网络中的每个用户和设备都需要进行身份验证和授权,无论它们是否位于内部网络。零信任模型通过将访问控制、身份验证、权限管理和安全审计等功能应用于网络中的每个资源和工作负载,来保护敏感数据和系统。
在零信任模型中,安全策略基于多个因素,如用户身份、设备状况、行为模式、网络位置等。用户和设备必须经过身份验证,并根据其所需的访问权限进行授权。此外,网络流量和数据包也需要进行加密和验证,以确保其完整性和安全性。
零信任模型的优势在于它提供了一种更加细粒度的访问控制和更强的安全性。它可以帮助组织更好地应对内部威胁、外部攻击和数据泄露风险。通过将安全性集成到网络架构的每个层面,零信任模型有助于保护敏感数据和系统资源,提高网络的整体安全性。
1.2 什么是X.509
X.509是一种公钥基础设施(PKI)标准,用于定义数字证书的格式和验证流程。它是一种国际标准,由国际电信联盟(ITU-T)制定。
X.509证书用于实现加密通信和身份验证。它包含了一些重要的信息,包括证书的持有者(主体)的身份信息、公钥、颁发者(证书颁发机构)的身份信息以及其他相关属性。
X.509证书通常用于以下用途:
身份验证:X.509证书用于验证证书持有者的身份。通过验证证书的数字签名和颁发者的信任链,可以确保证书持有者的身份是可信的。
安全通信:X.509证书用于建立安全的通信通道,例如使用传输层安全协议(TLS/SSL)加密数据传输。通过验证服务器证书,客户端可以确保它正在与预期的受信任服务器进行通信。
数字签名:X.509证书还可用于生成和验证数字签名。证书持有者可以使用其私钥对数据进行签名,而其他人可以使用证书的公钥验证签名的有效性。
X.509证书采用了一种层次结构,其中包括了一系列的字段和扩展,如证书版本、序列号、有效期、颁发者和主体的身份信息、公钥、扩展字段等。证书通常由权威的证书颁发机构(Certificate Authority,CA)签发,以确保其可信和有效性。
总结来说,X.509是一种用于定义数字证书格式和验证流程的国际标准。它用于实现身份验证、安全通信和数字签名等安全功能,是公钥基础设施中的重要组成部分。
二、SPIFFE概念
2.1 什么是SPIFFE
Secure Production Identity Framework for Everyone 的缩写 SPIFFE,是一个软件身份标识的开源标准(CNCF 下),为了以组织和平台无关的方式实现身份标识的互操作性,SPIFFE 定义了以全自动方式获取和验证加密身份所需的接口和文档。为构建分布式系统的通用身份的控制平面提供了标准的支撑。这个控制平面就是“基础设施”。作为基础设施,需要是语言、技术栈无关的,并可以做到全自动。
2.2 结构
SPIFFE 框架包含了如下几部分:
- SPIFFE ID:
- SVID(SPIFFE Verifiable Identity Document)
- Workload API
- Trust Bundle
- SPIFFE 联盟
2.2.1 SPIFFE ID
SPIFFE的核心概念是通过为每个服务颁发全局唯一的身份标识,称为SPIFFE标识(SPIFFE ID),来确保服务之间的身份验证。SPIFFE ID是一个URL,它包含了服务的身份信息和一些其他的属性。每个SPIFFE ID都是全局唯一的,并且可以由SPIFFE提供的标识发行机构(SPIFFE CA)进行验证。
- 前缀
spiffe://
- 信任域的名字,比如
example.com
,还可以通过多级域名来表示环境、集群等信息stagging.example.com
、k8s-cluster.example.com
- 工作负载的名字或者身份标识,比如
/payment/mysql
、/payment/web-fe
、`/9eebccd2-12bf-40a6-b262-65fe0487d4'
比如 spiffe://example.com/bizops/hr/taxrun/withholding
2.2.2 SVID
SPIFFE可验证身份文件(SVID)是一种可加密验证的身份文件,用于向对等方证明服务的身份。SVID包括一个SPIFFE ID,并由代表服务所在信任域的颁发机构签名。SPIFFE选择使用已经广泛使用且广为人知的文档类型,而不是发明一种必须教授软件支持的新型文档。SPIFFE规范定义了两种类型的身份证件用作SVID:X.509和JWT
X509-SVID
X.509证书的格式,并添加了SPIFFE特定的扩展字段来表示服务的SPIFFE ID和其他相关信息。这些扩展字段包含在X.509证书的Subject Alternative Name(SAN)扩展中,以确保证书的唯一性和可性和可验证性。
总结来说,X.509 SVID是SPIFFE项目中使用的一种特定类型的X.509证书,用于验证服务身份并实现安全的服务身份验证机制。
JWT-SVID
JWT-SVID作为服务的身份验证凭证。JWT-SVID将SPIFFE SVID(SPIFFE Verifiable Identity Document)封装在JWT中,以确保服务的身份和权限。JWT-SVID通过添加SPIFFE特定的声明字段,如"spiffe_id"和"audience",提供了服务的身份信息和受众(目标服务)的信息。
使用JWT-SVID,服务可以在请求中携带该令牌,并在目标服务上进行验证。目标服务会检查JWT-SVID的签名和有效性,并提取其中的声明信息来验证请求的合法性和权限。这样可以实现服务间的可信任身份验证和安全通信。
2.2.3 Workload API
SPIFFE Workload API是一个本地非网络API,工作负载使用它来获取其当前身份文档、信任包和相关信息。重要的是,此API未经身份验证,不要求工作负载具有任何预先存在的凭据。通过将此功能作为本地API提供,SPIFFE实现可以在不需要直接身份验证的情况下(例如,通过利用操作系统提供的功能)找到或者识别调用者的创造性解决方案。工作负载API是作为gRPC服务器公开的SPIFFE workload API,它使用双向流,允许根据需要将更新推送到工作负载中。Workload API不要求调用工作负载知道自己的身份,也不要求在调用API时拥有任何凭据。这避免了在工作负载的同时部署任何身份验证机密的需要。Workload API提供了利用SPIFFE身份的信息和设施。SPIFFE Workload API向工作负载提供SVID和信任包,并根据需要进行轮换。SPIFFE运行时环境(SPIRE)是SPIFFE规范所有五个部分的一个可用于生产的开源实现。
2.2.4 Trust Bundle
SPIFFE Trust Bundle是包含信任域公钥的文档。每种SVID类型都有一种特定的方式在该捆绑包中表示(例如,对于X509-SVID,包括表示公钥的CA证书)。每个SPIFFE信任域都有一个与其关联的Bundle,该Bundle中的材料用于验证声称位于所述信任域中的SVID。由于Trust Bundle不包含任何机密(只有公钥),因此可以安全地与公众共享。尽管如此,它确实需要安全地分发,以保护其内容免受未经授权的修改。换句话说,不需要保密性,但需要完整性。SPIFFE Trust Bundle 被格式化为JWK集(或JWKS文档),并与现有的身份验证技术(如OpenID Connect)兼容(请参阅:https://openid.net/connect/)。JWKS是一种灵活且广泛采用的格式,用于表示各种类型的加密密钥和文档,它在定义新的SVID格式时提供了一些未来证明。
2.2.5 SPIFFE 联盟
SPIFFE 联盟是一种可以共享 SPIFFE 信任包的简单机制。通常我们希望允许不同信任域中的服务可以安全地进行网络通信。通信的双方检查对方提供提供的信任包,来决定是否进行通信。这是基于双方可以互相暴露或者共享信任包,这种机制被称为包端点(bundle endpoint)。
包端点是个简单的、由 TLS 保护的 HTTP 服务。SPIFFE 的实现通过暴露该端点,使得包的内容可以被获取到。
三、SPIRE
SPIRE 是 SPIFFE 运行时环境(SPIFFE Runtime Environment)的首字母,是一个生产就绪、开源的(同在 CNCF 下) SPIFFE 实现。SPIRE 实现了 SPIFFE 五个定义。
SPIRE 包含了两个主要组件:服务端和代理。服务端负责验证代理和生成 SVID,而代理负责提供 workload API,并与服务端进行通信。
这两个组件的设计都支持插件,可以很容易地扩展支持不同的配置和平台。
3.1 SPIRE 架构
3.1.1 服务端
SPIRE Server是中央管理组件,负责颁发和管理SPIFFE证书(SVIDs)以及与SPIFFE ID相关的身份和授权信息。SPIRE Server还维护着可信任的身份发行机构(CA),用于签发和验证SVIDs。
3.1.2 客户端
SPIRE Agent是在每个服务节点上运行的代理程序,它与SPIRE Server通信并接收SVIDs。SPIRE Agent负责验证服务的身份和证书的有效性,并将SVIDs提供给服务进行使用。
它只有一个功能,尽管它非常重要:为工作负载API提供服务。在完成这一过程中,它解决了一些相关的问题,如确定工作负载的身份、调用工作负载以及将自己安全地引入SPIRE服务器。在这种安排中,Agent完成了所有繁重的工作。
3.1.3 插件架构
SPIRE是作为一组插件构建的,因此它可以轻松地扩展以适应新的节点证明者、工作负载证明者和上游权威机构。
3.1.4 SIVD 管理
SPIRE代理使用其在节点证明期间获得的身份向SPIRE服务器进行身份验证,并获得其授权管理的工作负载的SVID。由于SVID是有时间限制的,代理还负责根据需要更新SVID,并将这些更新传达给相关的工作负载。Trust Bundle还轮换和接收Bundle,这些更新由代理跟踪并与工作负载通信。代理维护所有这些信息的内存缓存,因此即使SPIRE Server关闭,也可以提供SVID,并且还通过在有人调用Workload API时不需要往返服务器来确保Workload API响应的性能。
3.1.5 证明
工作负载证明发生在工作负载与 SPIRE 代理的 workload API 建立连接时。证明的过程完全由 SPIRE 代理完成,代理利用操作系统特性来确认是哪个进程创建的连接。
比如在 Linux 下通过系统调用来获取调用 socket 的对端进程 ID、用户标识和全局唯一标识。不同操作系统的内核元数据不同,拿到工作负载的 ID 之后,代理将 ID 提供给各个插件,从选择器中获取调用者的信息。
每个插件都会对调用者进行检查。比如一个插件从系统内核中获信息,生成取用户、组等选择器;一个插件则会与 Kubernetes 交互,生成命名空间、service account 等选择器;另一个与 Docker daemon 进行交互,生成 Docker 镜像 ID、标签和容器环境变量的选择器。
注册条目
SPIRE 通过注册条目获知工作负载的各种信息,比如工作负载是否应该或允许出现在环境中、应该运行的位置、SPIFFE ID 和其他信息。这些信息是通过 SPIRE API 创建和管理的。
每个注册条目包含了 3 个核心属性:
- Parent ID:告诉 SPIRE 工作负载运行在哪里,进一步感知哪些代理有权获取其 SVID。
- SPIFFE ID:工作负载可以使用的 SPIFFE ID
- 可以用来辨识工作负载的信息:也就是选择器从证明中获取到的
节点条目
描述一个节点或者一组节点的注册条目使用节点证明生成的选择器来分配 SPIFFE ID,在注册工作负载时可以引用该 ID。
一个节点可以被多个节点条目的选择器证明,因此可以存在于多个组中。
SPIRE 服务端一次可以加载多个节点证明器,而代理一次只能加载一个。
注册条目的 Pareent ID 指向的是 SPIRE 服务端的 SPIFFE ID。
工作负载条目
工作负载条目的 Parent ID 是节点(一个或者一组)的 SPIFFE ID。 表示其可以运行在哪个或哪组节点上。该节点上的 SPIRE 代理收到该工作负载的条目,包含了在颁发 SIVD 之前必须要证明的选择器。
与节点证明过程不同,SPIRE 代理一次可以加载多个工作负载证明器插件。