最新:在TwitterMastodon 上获取项目更新。

常见问题解答 (FAQ)

本页将为您提供有关 cert-manager 的一些常见问题的答案。

术语

公认信任自签名 的含义是什么?

这些术语在 TLS 术语页面 中定义。

术语 中间叶子 证书 的含义是什么?

这些术语在 TLS 术语页面 中定义。

证书

我可以按需从 cert-manager 触发更新吗?

这是 cert-manager 从 v0.16 版本开始提供的功能,使用 cmctl CLI。有关更多信息,请参阅 renew 命令的页面

证书何时会重新签发?

为了确定证书是否需要重新签发,cert-manager 会查看 证书 资源的规范和最新的 证书请求,以及包含 X.509 证书的 密钥 中的数据。

如果以下情况成立,签发流程将始终被触发

  • 证书 规范中命名的 密钥 不存在、缺少私钥或证书数据,或者包含损坏的数据
  • 存储在 密钥 中的私钥与 证书 上的私钥规范不匹配
  • 签发的证书的公钥与存储在 密钥 中的私钥不匹配
  • 密钥 上的 cert-manager 发行商注释与 证书 上指定的发行商不匹配
  • 签发的证书上的 DNS 名称、IP 地址、URL 或电子邮件地址与 证书 规范上的地址不匹配
  • 证书需要续期(因为证书已过期或续期时间为现在或过去)
  • 证书已手动标记为需要续期 使用 cmctl

此外,如果找到 证书 的最新 证书请求,cert-manager 也会在以下情况下重新签发

  • 证书请求 中找到的 CSR 上的通用名称与 证书 规范上的通用名称不匹配
  • 证书请求 中找到的 CSR 上的主题字段与 证书 规范的主题字段不匹配
  • 证书请求 上的持续时间与 证书 规范上的持续时间不匹配
  • 证书 规范上的 isCA 字段值与 证书请求 上的值不匹配
  • 证书请求 规范上的 DNS 名称、IP 地址、URL 或电子邮件地址与 证书 规范上的地址不匹配
  • 证书请求 规范上的密钥用法与 证书 规范上的密钥用法不匹配

请注意,对于某些字段,只有在存在 cert-manager 可以用来确定 证书 规范自上次签发以来是否已更改的 证书请求 时,才会触发更改时的重新签发。这是因为某些发行商可能不尊重这些字段的请求值,因此我们无法依赖签发的 X.509 证书中的值。其中一个这样的字段是 .spec.duration - 对此字段的更改只有在存在可以用来比较的 证书请求 时才会触发重新签发。在您需要重新签发,但由于没有 证书请求(例如备份和恢复后)导致重新签发未自动触发的情况下,您可以使用 cmctl renew 手动触发。

为什么我的签发的密钥中的 tls.crt 中没有我的根证书?

有时,人们会使用在 TLS 链方面做出错误选择的系统。 TLS 规范 中的“服务器证书”部分有以下内容:

这是一个证书序列(链)。发送者的证书必须位于列表的第一位。每个后续证书必须直接认证前一个证书。由于证书验证需要独立分发根密钥,因此指定根证书颁发机构的自签名证书可以从链中省略,前提是远程端必须已经拥有它,以便在任何情况下验证它。

在标准、安全且配置正确的 TLS 环境中,向链添加根证书几乎总是没有必要且浪费的。

证书可以通过两种方式获得信任

  • 显式地,将其包含在信任存储中。
  • 通过签名,通过将证书链向上追溯到显式信任的证书。

至关重要的是,根证书本身是自签名的,无法通过签名验证。

因此,如果有一个客户端试图验证服务器发送的证书链,则客户端必须在连接启动之前已经拥有根证书。如果客户端已经拥有根证书,则服务器根本没有必要发送它!

不发送根证书的相同逻辑也适用于服务器试图验证客户端证书;相同的理由在 TLS RFC 中有说明。

为什么我的签发的密钥中的 ca.crt 中没有我的证书链?

用户经常问我们关于更改 ca.crt 以包含更多证书或不同证书的问题。我们倾向于拒绝这些请求,因为我们认为 ca.crt 对大多数用户来说都是一种风险。

ca.crt 由 cert-manager 填充,它会“尽力猜测”发行 CA 是什么。重要的是,cert-manager 通常只能猜测;如果发行商没有提供包含根证书的完整链,则 cert-manager 可能无法知道链的根是什么。在这种情况下,cert-manager 会尽力尝试使用链中最深的发行商。

这种“尽力尝试”是 ca.crt 可能存在风险的原因之一;它可能不正确,并且即使 cert-manager 没有变化,它也可能在发行商更改时发生变化。

ca.crt 的另一个问题是它在证书更新时更新。一些用户可能会想使用 ca.crt 来进行信任目的,但安全地轮换受信任的证书依赖于能够同时信任旧的和新的 CA 证书。

通过直接从您的密钥中获取 CA,这变得不可能;ca.crt 将始终只包含对当前证书的 CA 的尽力猜测,并且永远不会包含旧的或新的 CA。

cert-manager 将所有事件发布到 Kubernetes 事件机制,您可以使用 kubectl describe <resource> <name> 获取特定资源的事件。

由于 Kubernetes 事件机制的特性,这些事件将在一段时间后被清除。如果您使用的是专用日志系统,它可能已经或正在存储 Kubernetes 事件。

如果颁发失败会发生什么?会重试吗?

cert-manager 会重试失败的颁发,除了少数需要手动干预的罕见边缘情况。

我们旨在在发生短暂故障(例如网络连接错误)时,经过短暂延迟后重试;在发生“最终”故障后,以更长的指数级增长的延迟进行重试。

如果 CertificateIssuing 条件设置为 false 并且具有 status.lastFailureTime 设置,则表示最新的颁发已最终失败。在这种情况下,颁发将在经过指数级增长的延迟(1 到 32 小时)后重试,方法是创建一个新的 CertficateRequest。您可以使用 cmctl renew 命令 立即触发续订。如果颁发者将 CertificateRequest 设置为失败(例如,如果 CA 由于达到速率限制而拒绝了请求)或无效,或者如果 CertificateRequest 被批准者拒绝,则会出现最终故障。

短暂故障会导致同一个 CertificateRequest 在短暂延迟(最长 5 分钟)后重新同步。通常,它们只能在 cert-manager 控制器日志中观察到。

如果颁发似乎卡住了,并且 cmctl renew 不起作用,您可以删除最新的 CertificateRequest。这通常是一个无害的操作(最糟糕的情况是在进行中可能存在成功的颁发时,会导致重复颁发),但我们确实希望这不是用户流程的一部分,如果您认为您发现了一个可以改进流程的情况,请与我们联系。

是否支持 ECC(椭圆曲线密码术)?

cert-manager 支持 ECDSA 密钥对!您可以在证书资源的 privateKey 部分设置证书以使用 ECDSA。

例如

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ecdsa
spec:
secretName: ecdsa-cert
isCA: false
privateKey:
algorithm: ECDSA
size: 256
dnsNames:
- ecdsa.example.com
issuerRef:
[...]

如果未定义 renewBeforeduration,默认值是什么?

默认 duration90 天。如果未设置 renewBefore,则会在 Certificate 持续时间的 2/3 处进行续订。

为什么 JKS 或 PKCS#12 文件上的密码没有用?

这个问题有多种形式,包括

  • "为什么可以对这些密码进行硬编码?"
  • "我需要保护这些密码吗?"
  • "这些密码是否以安全的方式使用?"

具体来说,此常见问题解答讨论的是 PKCS#12 和 JKS "密钥库" 的密码。

简短回答

PKCS#12 或 JKS 文件上的“密码”几乎总是安全防范措施,并且仅需要支持无法解析这些文件无密码版本的应用程序。即使您对这些文件使用安全密码(这种情况很少见),弱加密算法和底层材料的管理通常会使安全密码无效。

我们建议您将这些密码视为传统实现细节,当您被迫使用密码时,对这些密码使用简短的硬编码字符串。不要花时间尝试为这些文件生成或处理“安全”密码 - 只需选择一个常量,例如 changeitnotapassword123,并将其用于您生成的每个 PKCS#12 或 JKS 捆绑包。

更详细的回答

许多人在处理 JKS 或 PKCS#12 捆绑包时看到了“密码”一词,他们得出了显而易见的结论,即这是一个需要谨慎处理的宝贵安全资源。

这通常不是这种情况 - 这些密码不仅不是真正的密码,而且它们极不可能对任何安全起任何作用。

大多数情况下,这些密码的存在仅仅是因为某些应用程序要求设置密码。该要求是 cert-manager 及其子项目支持在这些类型的捆绑包上设置密码的唯一原因。

我们不认为这些密码是安全关键因素,主要有以下几个原因:

  1. 大多数使用这些密码的应用程序会将包含密码的文件以纯文本形式安装在使用该密码的捆绑包旁边,具有相同的权限和访问控制。这将使即使是最安全的密码也完全失去作为安全措施的意义。
  2. 大多数加密的 PKCS#12 和 JKS 捆绑包使用极其古老的加密算法,这些算法从根本上是不安全的。
  3. "密码" 一词会让人联想到人类可以记住的密码,这对于这种类型的加密不合适。这意味着在此上下文中使用的密码本身往往是不安全的。
  4. 当我们生成 PKCS#12 或 JKS 文件时,它们几乎总是与未加密的私钥位于同一个 Secret 中!

如果没有非常详细的威胁模型,并且以极其偏执的方式认真投入到系统的架构中,那么花时间处理这些“密码”将是一个毫无意义的浪费时间,几乎没有回报。您的努力几乎总是更好地花在通过其他方法保护系统上。

有关这些“密码”的用法指南,请参阅上面的“简短回答”。

其他

Kubernetes 有一个内置的 CertificateSigningRequest API。为什么不使用它?

Kubernetes 有一个 证书签名请求 API 和一个 kubectl certificates 命令,允许您批准证书签名请求并让 Kubernetes 集群的证书颁发机构 (CA) 对其进行签名。

这个 API 和 CLI 有时被误用于为非控制平面 Pod 签名证书,但这是一个错误。为了保护 Kubernetes 集群的安全,限制对 Kubernetes 证书颁发机构的访问非常重要,并且重要的是不要使用该证书颁发机构为在控制平面之外使用的证书签名,因为这些证书会增加对 Kubernetes API 服务器的攻击机会。

在 Kubernetes 1.19 中,证书签名请求 API 已达到 V1,通过遵循(或自动化)请求签名过程,可以更普遍地使用它。

cert-manager 目前对该资源有一些 有限的实验性支持

如何写“cert-manager”

cert-manager 始终应以小写形式书写。即使在标题或句子开头通常应大写的情况下。单词之间始终使用连字符,不要用空格替换它,也不要删除它。