Skip to content

本文为 SPIRE 官方文档 plugin_server_nodeattestor_x509pop.md 的中文译本,以英文原文为准。 🔗 穿越源码分析:Server 详解 · NodeAttestor

Server 插件:NodeAttestor "x509pop"

必须与 Agent 侧 x509pop 插件配合使用

x509pop 插件用于对那些通过带外(out-of-band)机制预置了 x509 身份的节点进行认证。它会验证证书是否根植于一组受信任的 CA,并向 agent 插件发起一次基于签名的持有性证明(proof-of-possession,PoP)挑战,以验证该节点确实持有对应的私钥。

插件生成的 SPIFFE ID 基于证书指纹(certificate fingerprint),该指纹定义为身份证书的 ASN.1 DER 编码的 SHA1 哈希。SPIFFE ID 的格式为:

xml
spiffe://<trust_domain>/spire/agent/x509pop/<fingerprint>
ConfigurationDescriptionDefault
mode若为 spiffe,则使用 spire server 自身的信任 bundle 进行校验;若为 external_pki,则使用指定的 CA。external_pki
svid_prefix用于匹配有效 SVID 并将其兑换为 Node SVID 的 SVID 前缀。/spire-exchange
ca_bundle_path磁盘上受信任 CA bundle 的路径。该文件必须包含一个或多个 PEM 块,构成用于信任链(chain-of-trust)校验的受信任根 CA 集合。如果 CA 证书分布在多个文件中,请改用 ca_bundle_paths
ca_bundle_paths磁盘上多个受信任 CA bundle 的路径列表。这些文件必须包含一个或多个 PEM 块,构成用于信任链校验的受信任根 CA 集合。
agent_path_templateAgent SPIFFE ID 的 URL 路径部分格式,以 text/template 格式描述。详见 Agent 路径模板(Agent Path Template)
max_intermediates证书链中允许的中间证书(intermediate certificate)的最大数量。该上限有助于防止资源耗尽(resource exhaustion)攻击。4
max_rsa_key_size证书中允许的 RSA 密钥的最大位数(bits)。该上限有助于防止来自超大密钥的资源耗尽攻击。8192
verify_client_ip若为 true,则将连接对端(peer)的 IP 与叶子证书的 IP SAN 进行校验。如果没有任何 SAN 匹配,认证将失败。此处反映的是直接对端,在负载均衡器之后可能并不代表真实的客户端来源。false

一份示例配置:

hcl
    NodeAttestor "x509pop" {
        plugin_data {
            ca_bundle_path = "/opt/spire/conf/server/agent-cacert.pem"

            # 修改 agent 的 SPIFFE ID 格式
            # agent_path_template = "/cn/{{ .Subject.CommonName }}"

            # 可选:中间证书的最大数量(默认:4)
            # max_intermediates = 4

            # 可选:RSA 密钥的最大位数(默认:8192)
            # max_rsa_key_size = 8192
        }
    }

Selectors(选择器)

SelectorExampleDescription
Common Namex509pop:subject:cn:example.org主体(Subject)的通用名(Common Name)(参见 X.500 可辨别名称 Distinguished Names)
SHA1 Fingerprintx509pop:ca:fingerprint:0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33PoP 链中每个证书(不含叶子证书)的 SHA1 指纹,以十六进制字符串表示。
SerialNumberx509pop:serialnumber:0a1b2c3d4e5f叶子证书的序列号,以小写十六进制字符串表示。
Sanx509pop:san:<key>:<value>叶子证书上的 SAN selector。URI SAN 的预期格式为 x509pop://<trust_domain>/<key>/<value>。每个符合 x509pop URI 方案(scheme)的 URI SAN 都会暴露一个 selector。

SVID 路径前缀(SVID Path Prefix)

mode="spiffe" 时,被兑换的 SPIFFE ID 必须带有所指定的 svid_prefix 前缀。在传递给 agent 路径模板之前,该前缀会从 .SVIDPathTrimmed 属性中被去除。如果 svid_prefix 设为 "",则允许所有前缀,此时限制逻辑必须在 agent_path_template 中自行实现。

示例: 如果你的信任域是 example.com,svid_prefix 设为其默认值 /spire-exchange,并且 agent_path_template 也保持默认,那么来自 x509 身份 spiffe://example.com/spire-exchange/testhost 的 SPIFFE ID 将被兑换为 spiffe://example.com/spire/agent/x509pop/testhost。如果给定的 SPIFFE ID 带有不同的前缀,例如 spiffe://example.com/other/testhost,则它与 svid_prefix 不匹配,将被拒绝。

Agent 路径模板(Agent Path Template)

指定 agent_path_template 的值提供了一种自定义 agent SPIFFE ID 生成格式的方式。每种 mode 的默认格式如下所示:

modeagent_path_template
spiffe{{ .PluginName }}/{{ .SVIDPathTrimmed }}
external_pki{{ .PluginName }}/{{ .Fingerprint }}

模板格式化器采用 Golang text/template 约定。它可以引用插件提供的值,或 golang x509.Certificate 中的值。关于模板引擎的详情,见模板引擎文档

一些有用的值包括:

ValueDescription
.PluginName插件名称
.Fingerprintagent x509 证书的 SHA1 指纹
.TrustDomain所配置的信任域
.Subject.CommonNameagent x509 证书的通用名(common name)字段
.SerialNumberHexagent x509 证书的序列号字段,以小写十六进制表示
.SVIDPathTrimmed去除 SVID 前缀后的 SVID 路径
.URISanSelectors.<key>键为 <key> 的 URI SAN selector 的值