新:在TwitterMastodon 获取项目更新。

HTTP 验证

使用 HTTP 验证颁发 ACME 证书

cert-manager 可用于使用 ACME 协议从 CA 获取证书。ACME 协议支持各种挑战机制,这些机制用于证明域所有权,以便可以为该域颁发有效证书。

其中一种挑战机制是 HTTP01 挑战。使用 HTTP01 挑战,您可以通过确保域上存在特定文件来证明对域的所有权。如果您可以将给定文件发布到给定路径下,则假设您控制该域。

以下颁发者定义了启用 HTTP 验证所需的信息。您可以在颁发者文档中详细了解颁发者资源。

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-staging
namespace: default
spec:
acme:
# The ACME server URL
server: https://acme-staging-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: user@example.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-staging
# Enable the HTTP-01 challenge provider
solvers:
# An empty 'selector' means that this solver matches all domains
- selector: {}
http01:
ingress:
ingressClassName: nginx

我们已为 Let's Encrypt 的 暂存环境指定了 ACME 服务器 URL。暂存环境不会颁发可信证书,但用于确保验证过程在迁移到生产环境之前正常运行。Let's Encrypt 的生产环境施加了更严格的 速率限制,因此为了减少您遇到这些限制的可能性,强烈建议您先使用暂存环境。要迁移到生产环境,只需创建一个新的颁发者,并将 URL 设置为 https://acme-v02.api.letsencrypt.org/directory

ACME 协议的第一阶段是客户端向 ACME 服务器注册。此阶段包括生成一个非对称密钥对,然后将其与颁发者中指定的电子邮件地址相关联。确保将此电子邮件地址更改为有效的您拥有的电子邮件地址。它通常用于在您的证书即将到期时发送到期通知。生成的私钥存储在名为 letsencrypt-staging 的 Secret 中。

我们必须提供一个或多个求解器来处理 ACME 挑战。在本例中,我们希望使用 HTTP 验证,因此我们指定了一个 http01 求解器。我们可以选择将不同的域映射到不同的求解器配置。

创建上述颁发者后,我们可以使用它来获取证书。

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: default
spec:
secretName: example-com-tls
issuerRef:
name: letsencrypt-staging
commonName: example.com
dnsNames:
- www.example.com

证书资源描述了我们想要的证书以及可以用于获取证书的可能方法。您可以在文档中详细了解证书资源。如果证书成功获取,生成的密钥对将存储在与证书位于同一命名空间中的名为 example-com-tls 的 secret 中。

证书将具有 example.com 的通用名称,并且 主题备用名称 (SAN) 将是 example.comwww.example.com。请注意,只有这些 SAN 将被 TLS 客户端接受。

在我们的证书中,我们引用了上面提到的 letsencrypt-staging 颁发者。颁发者必须与证书位于同一命名空间。如果您想引用一个 ClusterIssuer(它是颁发者的集群范围版本),您必须将 kind: ClusterIssuer 添加到 issuerRef 节。

有关 ClusterIssuers 的更多信息,请阅读 ClusterIssuer 文档

acme 节定义了我们 ACME 挑战的配置。这里我们定义了 HTTP01 挑战的配置,它将用于验证域所有权。为了验证 http01 节中提到的每个域的所有权,cert-manager 将创建一个 Pod、服务和 Ingress,这些资源会公开一个满足 HTTP01 挑战的 HTTP 端点。

ingressClassNameclassname 字段可以在 http01 节中用于控制 cert-manager 如何与 Ingress 资源交互。

  • 如果指定了 ingressClassName 字段,将创建一个具有随机生成名称的新 ingress 资源,以解决挑战。这个新的资源将具有值为 ingressClassName 字段值的 ingressClassName 字段。这是配置应使用哪个 Ingress 控制器 的推荐方法。这适用于 NGINX Ingress 控制器。

  • 如果指定了 class 字段,将创建一个具有随机生成名称的新 ingress 资源,以解决挑战。这个新的资源将具有一个带键为 kubernetes.io/ingress.class 且值为 class 字段值的注释。只有当 不支持 ingressClassName 字段 的 ingress-gce 时,才推荐使用此字段。

  • 如果指定了 name 字段,则必须在与证书位于同一命名空间中,且具有相同名称的 Ingress 资源已经存在,并且它将仅修改以添加解决挑战的适当规则。此字段对于 Google Cloud Loadbalancer Ingress 控制器以及许多其他为每个 Ingress 资源分配单个公共 IP 地址的控制器很有用。如果没有手动干预,创建新的 Ingress 资源会导致任何挑战失败。

  • 如果两者都没有指定,则将使用随机生成的名称创建新的 Ingress 资源,但它们不会设置 ingress 类注释。

  • 如果两者都指定,则 ingress 字段将优先。

验证域所有权后,任何受 cert-manager 影响的资源都将被清理或删除。

注意:将每个域名指向 Ingress 控制器的正确 IP 地址是您的责任。

创建上述证书后,我们可以使用 kubectl describe 检查它是否已成功获取。

$ kubectl describe certificate example-com
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreateOrder 57m cert-manager Created new ACME order, attempting validation...
Normal DomainVerified 55m cert-manager Domain "example.com" verified with "http-01" validation
Normal DomainVerified 55m cert-manager Domain "www.example.com" verified with "http-01" validation
Normal IssueCert 55m cert-manager Issuing certificate...
Normal CertObtained 55m cert-manager Obtained certificate from ACME server
Normal CertIssued 55m cert-manager Certificate issued successfully

您还可以使用 kubectl get secret example-com-tls -o yaml 检查颁发是否成功。您应该会看到一个 base64 编码的已签名的 TLS 密钥对。

获取证书后,cert-manager 将定期检查其有效性,并在证书即将到期时尝试续期。当证书上的“不迟于”字段小于当前时间加上 30 天时,cert-manager 认为证书即将到期。