新:在推特Mastodon获取项目更新。

ACME

ACME 发行者类型代表与自动证书管理环境 (ACME) 证书颁发机构服务器注册的单个帐户。 当您创建新的 ACME Issuer 时,cert-manager 将生成一个私钥,用于识别您与 ACME 服务器之间的身份。

由公共 ACME 服务器颁发的证书通常默认情况下受客户端计算机信任。 这意味着,例如,访问由为该 URL 颁发的 ACME 证书支持的网站,将默认情况下受大多数客户端 Web 浏览器信任。 ACME 证书通常是免费的。

解决挑战

为了使 ACME CA 服务器验证客户端是否拥有正在请求证书的域或多个域,客户端必须完成“挑战”。 这是为了确保客户端无法为他们不拥有的域请求证书,从而导致欺诈性地假冒另一个人的站点。 如RFC8555 中所述,cert-manager 提供两种挑战验证 - HTTP01 和 DNS01 挑战。

HTTP01 挑战通过在 HTTP URL 端点处呈现计算出的密钥来完成,该密钥应该存在并可通过互联网路由。 此 URL 将使用为证书请求的域名。 一旦 ACME 服务器能够通过互联网从该 URL 获取该密钥,ACME 服务器就可以验证您是该域的所有者。 当创建 HTTP01 挑战时,cert-manager 将自动配置您的集群入口,以将此 URL 的流量路由到呈现该密钥的小型 Web 服务器。

DNS01 挑战通过提供存在于 DNS TXT 记录中的计算出的密钥来完成。 一旦该 TXT 记录在整个互联网上传播,ACME 服务器就可以通过 DNS 查询成功检索该密钥,并可以验证客户端是否拥有请求证书的域。 具有正确权限的 cert-manager 将自动为您给定的 DNS 提供商呈现此 TXT 记录。

配置

创建基本的 ACME 发行者

所有 ACME Issuers 遵循类似的配置结构 - 客户端的 emailserver URL、privateKeySecretRef 和一个或多个 solvers。 下面是一个简单的 ACME 发行者的示例

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: user@example.com
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource that will be used to store the account's private key.
name: example-issuer-account-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
ingressClassName: nginx

求解器采用 dns01http01 节的格式。 有关如何配置这些求解器类型的更多信息,请访问其各自的文档 - DNS01HTTP01

外部帐户绑定

cert-manager 支持在您的 ACME 帐户中使用外部帐户绑定。 外部帐户绑定用于将您的 ACME 帐户与外部帐户(例如 CA 自定义数据库)关联。 这通常对于大多数 cert-manager 用户来说是不需要的,除非您知道它是明确需要的。

外部帐户绑定在 ACME Issuer 上需要两个字段,这些字段代表您的 ACME 帐户。 这些字段是

  • keyID - 外部帐户绑定被外部帐户管理器索引的密钥 ID 或帐户 ID
  • keySecretRef - 包含您的外部帐户对称 MAC 密钥的 base 64 编码 URL 字符串的秘密的名称和密钥

注意:在大多数情况下,MAC 密钥必须使用 base64URL 编码。 以下命令将对密钥进行 base64 编码并将其转换为 base64URL

$ echo 'my-secret-key' | base64 -w0 | sed -e 's/+/-/g' -e 's/\//_/g' -e 's/=//g'

然后,您可以使用以下命令创建 Secret 资源

$ kubectl create secret generic eab-secret --from-literal \
secret={base64 encoded secret key}

以下是一个带有外部帐户绑定的 ACME 发行者的示例。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: my-acme-server-with-eab
spec:
acme:
email: user@example.com
server: https://my-acme-server-with-eab.com/directory
externalAccountBinding:
keyID: my-keyID-1
keySecretRef:
name: eab-secret
key: secret
privateKeySecretRef:
name: example-issuer-account-key
solvers:
- http01:
ingress:
ingressClassName: nginx

注意:cert-manager 版本早于 v1.3.0 还要求用户通过设置 Issuer.spec.acme.externalAccountBinding.keyAlgorithm 字段来指定 EAB 的 MAC 算法。 该字段现已弃用,因为上游 Go x/crypto 库将算法硬编码为 HS256。(参见上游相关讨论 CL#41430)。

重用 ACME 帐户

您可能希望在多个集群中重用单个 ACME 帐户。 这在使用 EAB 时特别有用。 如果设置了 disableAccountKeyGeneration 字段,cert-manager 将不会创建新的 ACME 帐户,而是使用 privateKeySecretRef 中指定的现有密钥。 请注意,Issuer/ClusterIssuer 将不会处于就绪状态,并将继续重试,直到提供 Secret

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: my-acme-server-with-existing-acme-account
spec:
acme:
email: user@example.com
disableAccountKeyGeneration: true
privateKeySecretRef:
name: example-issuer-account-key

添加多个求解器类型

您可能希望为不同的入口控制器使用不同类型的挑战求解器配置,例如,如果您想使用 DNS01 颁发通配符证书,以及使用 HTTP01 验证的其他证书。

solvers 节有一个可选的 selector 字段,可用于指定哪些 Certificates 以及这些 Certificates 上的哪些 DNS 名称应该用于解决挑战。

有三种选择器类型可用于形成 Certificate 必须满足的才能被选择为求解器的要求 - matchLabelsdnsNamesdnsZones。 您可以在单个求解器上拥有任意数量的这三种选择器。

匹配标签

matchLabel 选择器要求所有 Certificates 匹配该节中字符串映射列表中定义的所有标签。 例如,以下 Issuer 将只匹配具有标签 "user-cloudflare-solver": "true""email": "user@example.com"Certificates

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
...
solvers:
- dns01:
cloudflare:
email: user@example.com
apiKeySecretRef:
name: cloudflare-apikey-secret
key: apikey
selector:
matchLabels:
"use-cloudflare-solver": "true"
"email": "user@example.com"

DNS 名称

dnsNames 选择器是应该映射到求解器的精确 DNS 名称列表。 这意味着包含任何这些 DNS 名称的 Certificates 将被选中。 如果找到匹配项,dnsNames 选择器将优先于 dnsZones 选择器。 如果多个求解器使用相同的 dnsNames 值匹配,则具有 matchLabels 中最多匹配标签的求解器将被选中。 如果两者都没有更多匹配项,则列表中定义更早的求解器将被选中。

以下示例将解决 DNS 名称 example.com*.example.comCertificates 的挑战,用于这些域。

注意:dnsNames 采用精确匹配,不支持通配符解析,这意味着以下 Issuer 不会 解析像 foo.example.com 这样的 DNS 名称。使用 dnsZones 选择器类型来匹配区域内的所有子域。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
...
solvers:
- dns01:
cloudflare:
email: user@example.com
apiKeySecretRef:
name: cloudflare-apikey-secret
key: apikey
selector:
dnsNames:
- 'example.com'
- '*.example.com'

DNS 区域

dnsZones 段定义了此解析器可以解析的 DNS 区域列表。如果 DNS 名称是完全匹配,或指定 dnsZones 中任何一个的子域,此解析器将被使用,除非配置了更具体的 dnsNames 匹配。这意味着对于域 www.sys.example.comsys.example.com 将被选中,而不是指定 example.com 的那个。如果多个解析器具有相同的 dnsZones 值,则具有 matchLabels 中最多匹配标签的解析器将被选中。如果两个都没有更多匹配,则列表中较早定义的解析器将被选中。

在以下示例中,此解析器将解析域 example.com 以及其所有子域 *.example.com 的挑战。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
...
solvers:
- dns01:
cloudflare:
email: user@example.com
apiKeySecretRef:
name: cloudflare-apikey-secret
key: apikey
selector:
dnsZones:
- 'example.com'

全部一起

每个解析器都可以定义任意数量的这三种选择器类型。在以下示例中,DNS01 解析器将用于解决 Certificates 针对 a.example.comb.example.com 这些 DNS 名称的挑战。DNS01 解析器将用于解决 Certificates 针对匹配区域 test.example.com 以及其所有子域(例如 foo.test.example.com)的 DNS 名称的挑战。

对于所有其他挑战,HTTP01 解析器将Certificate 也包含标签 "use-http01-solver": "true" 时使用。

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
...
solvers:
- http01:
ingress:
ingressClassName: nginx
selector:
matchLabels:
"use-http01-solver": "true"
- dns01:
cloudflare:
email: user@example.com
apiKeySecretRef:
name: cloudflare-apikey-secret
key: apikey
selector:
dnsNames:
- 'a.example.com'
- 'b.example.com'
- dns01:
cloudDNS:
project: my-project-id
hostedZoneName: 'test-example.com'
serviceAccountSecretRef:
key: sa
name: gcp-sa-secret
selector:
dnsZones:
- 'test.example.com' # This should be the DNS name of the zone

每个单独的选择器块可以包含多个选择器类型,例如

solvers:
- dns01:
cloudflare:
email: user@example.com
apiKeySecretRef:
name: cloudflare-apikey-secret
key: apikey
selector:
matchLabels:
'email': 'user@example.com'
'solver': 'cloudflare'
dnsZones:
- 'test.example.com'
- 'example.dev'

在这种情况下,DNS01 解析器将仅用于解决针对 DNS 名称的挑战,前提是 Certificate 具有来自 matchLabels 的标签并且 DNS 名称匹配 dnsZones 中的区域。

私有 ACME 服务器

cert-manager 应该也能与私有或自托管的 ACME 服务器配合使用,只要它们遵循 ACME 规范。

如果您的 ACME 服务器没有使用公认的证书,您可以在创建颁发者时传递一个可信的 CA,从 cert-manager 1.11 开始

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: my-acme-server-issuer
spec:
acme:
server: https://my-acme-server.example.com
caBundle: <base64 encoded CA Bundle in PEM format>
...

替代证书链

从 ACME 服务器获取证书时,可以选择替代证书链。这允许颁发者在过渡期间将用户逐步过渡到新的根证书;最著名的例子是 Let's Encrypt "ISRG Root" 转换

此功能并不专属于 Let's Encrypt;如果您的 ACME 服务器支持使用多个 CA 进行签名,您可以在颁发者部分的证书中使用 preferredChain 以及您想要的链的通用名称的值。如果通用名称匹配不同的链,服务器可以选择使用并返回该新链。

如果 preferredChain 不匹配证书,服务器将返回它认为的默认证书。

举例来说,下面是用户在(现在已完成的)"ISRG Root" 转换之前如何请求替代链,但请注意,由于此转换已经完成,因此现在不需要在 Let's Encrypt 中使用它了

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
preferredChain: "ISRG Root X1"