本文补充 了 Service Fabric 群集安全性简介,并详细介绍了 Service Fabric 群集中基于证书的身份验证。 假设读者熟悉基本安全概念,还熟悉 Service Fabric 公开的控件来控制群集的安全性。
此标题下涵盖的主题:
- 基于证书的身份验证基础知识
- 标识及其各自的角色
- 证书配置规则
- 故障排除和常见问题解答
作为一个简要回顾,在安全性领域,证书是一种工具,旨在将有关实体(主体)的信息与其拥有的一对非对称加密密钥绑定,因此构成了公钥加密的核心组成部分。 证书表示的密钥可用于保护数据,或用于证明密钥持有者的身份:与公钥基础结构(PKI)系统结合使用时,证书可以表示其主体的其他特征,例如 Internet 域的所有权,或证书颁发者授予的某些特权(称为证书颁发机构或 CA)。 证书的常见应用程序支持传输层安全性(TLS)加密协议,允许通过计算机网络进行安全通信。 具体而言,客户端和服务器使用证书来确保其通信的隐私和完整性,并执行相互身份验证。
在 Service Fabric 中,群集的基本层(联邦)还依赖于 TLS(以及其他协议)来构建可靠且安全的参与节点网络。 通过 Service Fabric 客户端 API 连接到群集时,使用 TLS 来保护流量,以及建立参与方的标识。 具体而言,在 Service Fabric 中用于身份验证时,证书可用于证明以下声明:a) 证书凭据的演示者拥有证书的私钥 b)证书的 SHA-1 哈希('指纹')与群集定义中包含的声明匹配,或 c) 证书的可分辨使用者公用名与群集定义中包含的声明匹配, 证书的颁发者已知或受信任。
在上面的列表中,“b”通俗地称为“指纹固定”;在这种情况下,声明是指特定的证书,身份验证方案的强度依赖于这样的前提:在计算上是不可能伪造出一个证书,使其生成与另一个证书相同的哈希值,同时在所有其他方面仍然是一个有效且格式良好的对象。 项“c”表示声明证书的替代形式,其中方案强度取决于证书主体和证书颁发机构的组合。 在这种情况下,声明是指一类证书 - 任何具有相同特征的两个证书都被视为完全等效。
以下部分将深入说明 Service Fabric 运行时如何使用和验证证书来确保群集安全性。
在深入了解身份验证或保护通信通道的详细信息之前,请务必列出参与参与者及其在群集中扮演的相应角色:
- Service Fabric 运行时,被称为“system”,是提供群集抽象和功能的一组服务。 在提到系统实例之间的群集内通信时,我们将使用术语“群集标识”;将群集称为来自群集外部的流量的接收方/目标时,我们将使用术语“服务器标识”。
- 托管的应用程序,称为“applications”:群集所有者提供的代码,该代码在群集中协调和执行
- 客户端:根据群集配置,允许实体连接到群集并执行功能。 我们分别区分两个级别的特权 -“user”和“admin”。 “用户”客户端主要限制为只读作(但并非所有只读功能),而“管理员”客户端对群集功能的访问权限不受限制。 (有关更多详细信息,请参阅 Service Fabric 群集中的安全角色。
- (仅限 Azure)Service Fabric 服务用于协调和公开操作和管理 Service Fabric 群集的控件,简称为“服务”。 根据环境,“服务”可能引用 Azure Service Fabric 资源提供程序,或者 Service Fabric 团队拥有和运营的其他资源提供程序。
在安全集群中,可以为每个角色配置其独特的标识,这些标识声明为预定义角色名称及其相应凭据的配对。 Service Fabric 支持将凭据声明为证书或基于域的服务主体。 (也支持基于 Windows/Kerberos 的标识,但超出了本文的范围;请参阅 Service Fabric 群集中基于 Windows 的安全性。在 Azure 群集中,客户端角色也可以声明为 Microsoft基于 Entra ID 的标识。
如上所述,Service Fabric 运行时在群集中定义了两个级别的特权:“admin”和“user”。 管理员客户端和“系统”组件都使用“管理员”权限运行,因此彼此之间不可区分。 在群集中建立连接后,经过身份验证的调用方将由 Service Fabric 运行时授予两个角色之一,作为后续授权的基础。 我们将在以下部分中深入探讨身份验证。
Service Fabric 群集的安全设置原则上描述了以下几个方面:
- 身份验证类型;这是群集的创建时不可变特征。 此类设置的示例包括“ClusterCredentialType”、“ServerCredentialType”和允许的值为“none”、“x509”或“windows”。 本文重点介绍 x509 类型身份验证。
- (身份验证)校验规则:这些设置由群集所有者定义,描述可接受于特定角色的凭证类型。 下面将深入探讨示例。
- 用于调整或巧妙地更改身份验证结果的设置;此处的示例包括限制或取消强制实施证书吊销列表等的标志。
注意
下面提供的群集配置示例是从群集清单中以 XML 格式摘录的,它是直接支持本文中所述 Service Fabric 功能的最简化格式。 相同的设置可以直接在群集定义的 JSON 表示形式(无论是独立 json 群集清单还是 Azure 资源管理模板)中表示。
证书验证规则包含以下元素:
- 相应的角色:客户端、管理员客户端(特权角色)
- 通过指纹或主体公用名声明而被接受的角色凭证
对于基于指纹的验证规则,调用方请求连接群集时所提供的凭据将按如下所示进行验证:
- 凭据是一个有效且结构良好的证书:其链可以生成,签名能够匹配。
- 证书的有效时段是(NotBefore <= 当前时间 < NotAfter)
- 证书的 SHA-1 哈希与声明匹配,进行不区分大小写且不包含空格的字符串比较。
对于基于指纹的声明,链生成或验证期间遇到的任何信任错误都将被抑制,除了证书已过期之外——尽管对于这种情况也有相关的预配。 具体而言,吊销状态未知或脱机、不受信任的根、无效的密钥使用、部分链被视为非致命错误;在本例中,前提是证书只是密钥对的信封,安全性在于集群所有者已设置措施来保护私钥。
群集清单中的以下摘录演示了一组基于指纹的验证规则:
<Section Name="Security">
<Parameter Name="ClusterCredentialType" Value="X509" />
<Parameter Name="ServerAuthCredentialType" Value="X509" />
<Parameter Name="AdminClientCertThumbprints" Value="d5ec...4264" />
<Parameter Name="ClientCertThumbprints" Value="7c8f...01b0" />
<Parameter Name="ClusterCertThumbprints" Value="abcd...1234,ef01...5678" />
<Parameter Name="ServerCertThumbprints" Value="ef01...5678" />
</Section>
上述每个条目都引用前面所述的特定标识;每个条目还允许指定多个值,以逗号分隔的字符串列表。 在此示例中,成功验证传入凭据后,持有 SHA-1 指纹“d5ec...4264”证书的持有者将被授予“管理员”角色;相反,使用证书“7c8f...01b0”进行身份验证的调用方将被授予“用户”角色,仅限于执行主要的只读操作。 入站呼叫者呈现其指纹为 "abcd...1234" 或 "ef01...5678" 的证书时,将被接受为集群中的对等节点。 最后,连接到群集管理终结点的客户端会期望服务器证书的指纹为“ef01...5678”。
如前面提到的,Service Fabric 确实提供了机制来接受过期证书;原因是证书的生存期有限,当通过指纹(是指特定的证书实例)声明时,如果允许证书过期,可能会导致无法连接到集群,或导致集群完全崩溃。 忘记或忽视轮换使用以指纹加密的证书是非常容易的,遗憾的是,从这种情况中恢复是困难的。
为此,群集所有者可以显式声明指纹声明的自签名证书应被视为有效,如下所示:
<Section Name="Security">
<Parameter Name="AcceptExpiredPinnedClusterCertificate" Value="true" />
</Section>
此行为不会扩展到 CA 颁发的证书;如果是这种情况,那么,在 CA 的证书吊销列表中不再显示证书吊销列表中不再出现安全风险时,已吊销的已知to-be已泄露的过期证书可能会“有效”。 使用自签名证书时,群集所有者被视为唯一负责保护证书私钥的方,这与 CA 颁发的证书不一样,群集所有者可能不知道其证书被声明为已泄露的方式或时间。
基于通用名称的声明采用以下形式之一:
- 主体公用名(仅)
- 主题常用名与颁发者绑定
让我们首先考虑一个来自群集声明的摘录,其中展示了这两种声明风格:
<Section Name="Security/ServerX509Names">
<Parameter Name="server.demo.system.servicefabric.azure-int" Value="" />
</Section>
<Section Name="Security/ClusterX509Names">
<Parameter Name="cluster.demo.system.servicefabric.azure-int" Value="1b45...844d,d7fe...26c8,3ac7...6960,96ea...fb5e" />
</Section>
声明分别引用服务器和群集标识;请注意,基于 CN 的声明在群集清单中有自己的部分,独立于标准“安全性”。 在这两个声明中,“名称”表示证书的可分辨使用者公用名,“值”字段表示预期的颁发者,如下所示:
- 在第一种情况下,声明指出服务器证书的识别主题的公用名元素应与字符串“server.demo.system.servicefabric.azure-int”相匹配;“值”字段为空表示期望在进行服务器证书验证的该节点/计算机上信任证书链的根;在 Windows 上,这意味着证书可以与安装在“受信任的根 CA”存储中的任一证书建立链接。
- 在第二种情况下,声明规定,如果证书的公用名与字符串“cluster.demo.system.servicefabric.azure-int”匹配,证书的提交者将被接纳为集群中的对等节点,并且 直接颁发证书的实体的指纹与“值”字段中逗号分隔的某一条目匹配。 (此规则类型俗称为‘具有颁发者钉扎的通用名称’。)
在任何情况下,证书链都是建立的,并且应该没有错误;也就是说,证书撤销错误、部分链错误或时间无效信任错误被视为致命,证书校验将会失败。 将颁发者固定在系统中将导致将“不可信根”状态视为非致命错误;尽管这种错误不会显得严重,但这实际上是一种更严格的验证形式,因为它允许集群管理员将授权/接受的颁发者限制为其自身的公钥基础设施(PKI)。
生成证书链后,它会根据标准 TLS/SSL 策略进行验证,并将声明的使用者作为远程名称进行验证;如果证书的使用者公用名或其任何使用者可选名称与群集清单中的 CN 声明匹配,则证书将被视为匹配项。 在这种情况下支持通配符,字符串匹配不区分大小写。
(我们应该澄清,上述序列可以针对证书声明的每种密钥用法执行;如果证书指定客户端身份验证密钥用法,则首先为客户端角色生成并评估链。如果成功,则评估完成并验证成功。如果证书没有客户端身份验证用法或验证失败,Service Fabric 运行时将生成并评估服务器身份验证链。
为了完成这个示例,以下摘录说明如何通过通用名来声明客户端证书:
<Section Name="Security/AdminClientX509Names">
<Parameter Name="admin.demo.client.servicefabric.azure-int" Value="1b45...844d,d7fe...26c8,3ac7...6960,96ea...fb5e" />
</Section>
<Section Name="Security/ClientX509Names">
<Parameter Name="user.demo.client.servicefabric.azure-int" Value="1b45...844d,d7fe...26c8,3ac7...6960,96ea...fb5e" />
</Section>
上述声明分别对应于管理员和用户标识;验证以这种方式声明的证书与前面的群集和服务器证书示例完全一样。
注意
基于公用名的声明旨在简化证书的轮换,并且一般情况下有助于管理群集证书。 但是,建议遵循以下建议,以确保群集的持续可用性和安全性:
- 更倾向于使用发行者绑定而非依赖受信任的根证书
- 避免混合来自不同 PKI 的颁发者
- 确保证书声明上列出了所有预期的颁发者;不匹配的颁发者将导致验证失败
- 确保 PKI 的证书策略终结点可发现、可用和可访问 - 这意味着 AIA、CRL 或 OCSP 终结点在叶证书上声明,并且可访问这些终结点,以便证书链生成可以完成。
在收到使用 X.509 证书保护的群集中的连接请求后,Service Fabric 运行时将使用群集的安全设置来验证远程方的凭据,如上所述:如果成功,则调用方/远程方被视为经过身份验证。 如果凭据匹配多个验证规则,运行时将向调用方授予任何匹配规则的最高特权角色。
上一部分介绍了身份验证在受证书保护的群集中的工作原理;本部分将介绍 Service Fabric 运行时本身如何发现和加载它用于群集内通信的证书;我们将这些“演示文稿”规则称为“演示文稿”。
与验证规则一样,呈现规则指定角色和关联的凭据声明,以指纹或公用名表示。 与验证规则不同,基于公用名称的声明没有颁发者固定的预配;这样可以提高灵活性并提高性能。 对于每个不同的节点类型,在群集清单的“NodeType”部分(s)中声明呈现规则;设置从群集的安全部分拆分,以允许每个节点类型在单个部分中具有其完整配置。 在 Azure Service Fabric 群集中,节点类型证书声明默认为群集定义的“安全”部分中相应的设置。
如前所述,Service Fabric 运行时将其角色区分为群集中的其他节点的对等节点,以及作为群集管理操作的服务器。 原则上,这些设置可以分别配置,但在实践中它们往往保持一致。 对于本文的其余部分,为了简化,我们将假定这些设置是匹配的。
让我们考虑群集清单中的以下摘录:
<NodeTypes>
<NodeType Name="nt1vm">
<Certificates>
<ClusterCertificate X509FindType="FindByThumbprint" X509FindValue="cc71...1984" X509FindValueSecondary="49e2...19d6" X509StoreName="my" Name="ClusterCertificate" />
<ServerCertificate X509FindValue="cc71...1984" Name="ServerCertificate" />
<ClientCertificate X509FindValue="cc71...1984" Name="ClientCertificate" />
</Certificates>
</NodeType>
</NodeTypes>
“ClusterCertificate”元素展示完整架构,包括可选参数(“X509FindValueSecondary”)或具有适当默认值的参数(“X509StoreName”);其他声明则展示简化形式。 上述群集证书声明指出,类型为“nt1vm”的节点安全设置已使用证书“cc71..1984”作为主要证书进行初始化,而使用证书“49e2..19d6”作为辅助证书;这两个证书应在 LocalMachine'My' 证书存储(或 Linux 等效路径 var/lib/sfcerts)中找到。
节点类型证书也可以按使用者公用名声明,如下所示:
<NodeTypes>
<NodeType Name="nt1vm">
<Certificates>
<ClusterCertificate X509FindType="FindBySubjectName" X509FindValue="demo.cluster.azuredocpr.system.servicefabric.azure-int" Name="ClusterCertificate" />
</Certificates>
</NodeType>
</NodeTypes>
对于任一类型的声明,Service Fabric 节点将在启动时读取配置,找到并加载指定的证书,并按 NotBefore 属性的降序对其进行排序;将忽略过期的证书,并将列表的第一个元素选为此节点尝试的任何 Service Fabric 连接的客户端凭据。 (实际上,Service Fabric 支持最近颁发的证书。
注意
在版本 7.2.445(7.2 CU4)之前,Service Fabric 选择了最远过期的证书(具有最远的“NotAfter”属性的证书)
请注意,对于基于公用名的声明,如果证书的使用者公用名等于声明中的 X509FindValue(或 X509FindValueSecondary)字段,并且是区分大小写的确切字符串比较,则该证书被视为匹配。 这与支持通配符匹配的验证规则以及不区分大小写的字符串比较形成鲜明对比。
前面提到,Service Fabric 群集的安全设置还允许巧妙地更改身份验证代码的行为。 虽然 有关 Service Fabric 群集设置 的文章代表了设置的全面和最新的列表,但我们将在此处展开一些安全设置的含义,以完成基于证书的身份验证的完整公开。 对于每个设置,我们将介绍意向、默认值/行为、影响身份验证的方式以及可接受的值。
如上所述,证书验证始终意味着生成和评估证书的链。 对于 CA 颁发的证书,这显然简单的 OS API 调用通常需要对颁发 PKI 的各种终结点进行多个出站调用、响应缓存等。 鉴于在 Service Fabric 群集中频繁发生证书验证调用,PKI 终结点的任何问题都可能导致群集的可用性降低或完全崩溃。 虽然无法取消出站调用(请参阅常见问题解答部分中的下面部分,了解详细信息),但以下设置可用于屏蔽因 CRL 调用失败而导致的验证错误。
- CrlCheckingFlag - 在“安全”部分下,字符串转换为 UINT。 Service Fabric 使用此设置的值,通过调整链构建的方式来掩盖证书链状态错误,它作为“dwFlags”参数传递给 Win32 CryptoAPI CertGetCertificateChain 调用,并且可以设置为该函数所接受的任意有效标志组合。 值为 0 会强制 Service Fabric 运行时忽略任何信任状态错误 - 不建议这样做,因为它的使用将构成严重的安全泄露。 默认值为0x40000000(CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT)。
何时使用:用于本地测试,例如使用自签名证书或开发者证书,这些证书未完全形成或没有适当的公钥基础设施来支持。 在 PPI 之间转换期间,还可以在空隙环境中用作缓解措施。
如何使用:我们将举一个例子,演示如何强制吊销检查只能访问缓存的 URL。 若:
#define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY 0x80000000
然后,群集清单中的声明变为:
<Section Name="Security">
<Parameter Name="CrlCheckingFlag" Value="0x80000000" />
</Section>
- 在“安全”部分下,IgnoreCrlOfflineError 是一个默认值为“false”的布尔值。 表示用于抑制“吊销脱机”链构建错误状态(或随后的链策略验证错误状态)的快捷方式。
何时使用:本地测试或未受到适当 PKI 支持的开发者证书。 在空隙环境中或已知无法访问 PKI 时用作缓解措施。
如何使用:
<Section Name="Security">
<Parameter Name="IgnoreCrlOfflineError" Value="true" />
</Section>
其他值得注意的设置(全部在“安全”部分下):
- AcceptExpiredPinnedClusterCertificate - 在专用于基于指纹的证书验证部分中讨论;允许接受过期的自签名群集证书。
- CertificateExpirySafetyMargin - 在证书的 NotAfter 时间戳之前以分钟为单位表示的间隔,该间隔内的证书被视为有过期风险。 Service Fabric 监视群集证书,并定期发出有关这些证书剩余可用性的运行状况报告。 在“安全”间隔内,这些健康报告被提升至“警告”状态。 默认值为 30 天。
- CertificateHealthReportingInterval - 控制有关群集证书剩余有效时间的运行状况报告的频率。 仅按此间隔发出一次报告。 该值以秒为单位表示,默认值为 8 小时。
- EnforcePrevalidationOnSecurityChanges - 布尔值,用于在检测到安全性设置更改时,控制对群集升级进行预先验证的行为。 如果设置为“true”,群集升级会设法确保至少一个与任何显示规则匹配的证书能够通过相应的验证规则。 在将新设置应用到任何节点之前执行预验证,但在启动升级时,仅在托管群集管理器服务主副本的节点上运行。 从本文开始,该设置的默认值为“false”,对于从 7.1 开始的运行时版本的新 Azure Service Fabric 群集,该设置将设置为“true”。
我们已经了解了演示规则、验证规则和调整标志,但这一切如何协同工作? 在本部分中,我们将完成两个端到端示例,演示如何利用安全设置进行安全群集升级。 请注意,这不是有关 Service Fabric 中正确证书管理的综合论文,请查找有关该主题的配套文章。
呈现和验证规则的分离提出了一个明显的问题(或关注),即它们能否分裂,以及后果是什么。 事实上,节点选择身份验证证书可能不会通过另一个节点的验证规则。 事实上,这种差异是身份验证相关事件的主要原因。 同时,这些规则的分离允许群集在升级期间继续运行,从而更改群集的安全设置。 请考虑,首先扩充验证规则作为第一步,所有群集节点将在新设置上达到统一,同时仍使用当前凭据。
回想一下,在 Service Fabric 群集中,升级通过(最多 5 个)“升级域”或 UD 进行。 仅在给定时间升级/更改当前 UD 中的节点,并且仅当群集的可用性允许它时,升级才会转到下一个 UD。 有关更多详细信息,请参阅与同一主题相关的 Service Fabric 群集升级 和其他文章。证书/安全更改风险较大,因为它们可能导致节点与群集隔离,或者使群集处于几乎失去仲裁的状态。
我们将使用以下表示法来描述节点的安全设置:
Nk: {P:{TP=A}, V:{TP=A}},其中:
- “Nk”表示升级域 k 中的节点
- “P”表示节点的当前呈现规则(假设我们仅引用群集证书):
- “V”表示节点的当前验证规则(仅限群集证书)
- “TP=A”表示基于指纹的声明(TP),其中“A”是证书指纹
- “CN=B”表示基于公用名的声明(CN),“B”是证书的使用者公用名
以下序列介绍了如何使用 2 阶段升级安全地引入指纹声明的辅助群集证书;第一阶段在验证规则中引入新的证书声明,第二阶段在演示规则中引入它:
- 初始状态:N0 = {P:{TP=A}, V:{TP=A}}, ...Nk = {P:{TP=A}, V:{TP=A}} - 群集处于静态状态,所有节点共享通用配置
- 完成升级域 0 后: N0 = {P:{TP=A}, V:{TP=A, TP=B}}, ...Nk = {P:{TP=A}, V:{TP=A}} - UD0 中的节点将显示证书 A,并接受证书 A 或 B;所有其他节点仅提供并接受证书 A
- 完成最后一个升级域后:N0 = {P:{TP=A}, V:{TP=A, TP=B}},...Nk = {P:{TP=A}, V:{TP=A, TP=B}} - 所有节点都存在证书 A,所有节点都将接受证书 A 或 B
此时,群集再次处于均衡状态,升级/更改安全设置的第二阶段可以开始:
- 完成升级域 0: N0 = {P:{TP=A, TP=B}, V:{TP=A, TP=B}}, ...Nk = {P:{TP=A}, V:{TP=A, TP=B}} - UD0 中的节点将开始显示 B,群集中的任何其他节点都接受该 B。
- 完成最后一个升级域后:N0 = {P:{TP=A, TP=B}, V:{TP=A, TP=B}}, ...Nk = {P:{TP=A, TP=B}, V:{TP=A, TP=B}} - 所有节点都已切换到演示证书 B。证书 A 现在可以通过后续升级集从群集定义中停用/删除。
同样,将证书声明的类型(从指纹更改为公用名)将遵循与上述模式相同的模式。 请注意,验证规则允许在同一群集定义中通过指纹和公用名声明给定角色的证书。 不过,相比之下,呈现规则只允许一种声明形式。 顺便说一句,将群集证书从指纹转换为公用名的安全方法是先通过指纹引入预期的目标证书,然后将该声明更改为基于公用名的证书。 在下面的示例中,我们将假定指纹“A”和使用者公用名“B”引用同一证书。
- 初始状态:N0 = {P:{TP=A}, V:{TP=A}}, ...Nk = {P:{TP=A}, V:{TP=A}} - 群集处于静态状态,所有节点共享通用配置,A 是主证书指纹
- 完成升级域 0 后: N0 = {P:{TP=A}, V:{TP=A, CN=B}}, ...Nk = {P:{TP=A}, V:{TP=A}} - UD0 中的节点将显示证书 A,并接受指纹 A 或公用名 B 的证书;所有其他节点仅提供并接受证书 A
- 完成最后一个升级域后: N0 = {P:{TP=A}, V:{TP=A, CN=B}}, ...Nk = {P:{TP=A}, V:{TP=A, CN=B}} - 所有节点都存在证书 A,所有节点都将接受证书 A (TP) 或 B (CN)
此时,我们可以继续更改演示规则,然后进行后续升级:
- 完成升级域 0: N0 = {P:{CN=B}, V:{TP=A, CN=B}}, ...Nk = {P:{TP=A}, V:{TP=A, CN=B}} - UD0 中的节点将显示 CN 找到的证书 B,并接受指纹 A 或公用名称 B 的证书;所有其他节点都存在并接受证书 A(按指纹选择)
- 完成最后一个升级域后:N0 = {P:{CN=B}, V:{TP=A, CN=B}}, ...Nk = {P:{CN=B}, V:{TP=A, CN=B}} - CN 找到的所有节点都存在证书 B,所有节点都将接受证书 A (TP) 或 B (CN)
完成阶段 2 还标志着群集转换为基于公用名称的证书;可以在后续群集升级中删除基于指纹的验证声明。
注意
在 Azure Service Fabric 群集中,上述工作流由 Service Fabric 资源提供程序协调;群集所有者仍负责根据指示的规则(演示或验证)将证书预配到群集中,并建议在多个步骤中执行更改。
在单独的文章中,我们将讨论在 Service Fabric 群集中管理和预配证书的主题。
虽然在 Service Fabric 群集中调试身份验证相关问题并不容易,但我们希望以下提示和提示可能会有所帮助。 开始调查的最简单方法是检查群集节点上的 Service Fabric 事件日志,不一定只是那些显示症状的节点,以及那些已启动但无法连接到其中一个邻居的节点。 在 Windows 上,重要事件通常分别记录在“应用程序和服务日志\Microsoft-ServiceFabric\Admin”或“操作”通道下。 有时 ,启用 CAPI2 日志记录可能会有所帮助,以便捕获有关证书验证、检索 CRL/CTL 等的更多详细信息(请务必在完成重现后禁用它,这可能相当详细。
在遇到身份验证问题的群集中表现自己的典型症状包括:
- 节点已关闭/循环
- 连接尝试被拒绝
- 连接尝试正在超时
每个症状都可能是由不同的问题引起的,相同的根本原因可能表现出不同的表现:因此,我们将只列出一小部分典型问题示例,并提供了解决问题的建议。
节点可以交换消息,但无法连接。 连接尝试终止的可能原因是“证书不匹配”错误 - Service Fabric 到 Service Fabric 连接中的某个参与方正在显示一个证书,该证书未能通过收件人的验证规则。 可能附带以下任一错误:
0x80071c44 -2147017660 FABRIC_E_SERVER_AUTHENTICATION_FAILED
若要进一步诊断/调查:在尝试连接的每个节点上,确定正在显示哪个证书;检查证书并尝试模拟验证规则(检查指纹或公用名称相等性,检查颁发者指纹(如果指定)。
另一个常见的伴随错误代码可能是:
0x800b0109 -2146762487 CERT_E_UNTRUSTEDROOT
在这种情况下,证书按公用名声明,以下任一适用:
- 证书颁发者未被绑定,且根证书不被信任,或者
- 颁发者已被锁定,但声明中不包括此证书的直接颁发者的指纹。
节点已启动,但无法连接到其他节点;其他节点不会从失败的节点接收入站流量。 在这种情况下,证书加载可能在本地节点上失败。 查找以下错误:
找不到证书 - 确保可以通过 LocalMachine\My(或指定)证书存储的内容解析演示文稿规则中声明的证书。 失败的可能原因可能包括:
- 指纹声明中的无效字符
- 未安装证书
- 证书已过期
- 公用名声明包括前缀“CN=”
- 声明中指定了通配符,但证书存储中不存在精确匹配的证书(声明:CN=*.mydomain.com,实际证书:CN=server.mydomain.com)
未知凭据 - 指示与证书对应的缺少私钥,通常附带错误代码:
0x8009030d -2146893043 SEC_E_UNKNOWN_CREDENTIALS 0x8009030e -2146893042 SEC_E_NO_CREDENTIALS
若要补救,请检查私钥是否存在;验证是否向 SFAdmins 授予对私钥的“read|execute”访问权限。
错误的提供程序类型 - 指示加密新一代(CNG)证书(“Microsoft软件密钥存储提供程序”):目前,Service Fabric 仅支持 CAPI1 证书。 通常附带错误代码:
0x80090014 -2146893804 NTE_BAD_PROV_TYPE
若要解决此问题,请使用 CAPI1(例如“Microsoft增强 RSA 和 AES 加密提供程序”)提供程序重新创建群集证书。 有关加密提供程序的更多详细信息,请参阅 了解加密提供程序