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
遵循类似的配置结构 - 客户端的 email
、server
URL、privateKeySecretRef
和一个或多个 solvers
。 下面是一个简单的 ACME 发行者的示例
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec: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.comserver: https://acme-staging-v02.api.letsencrypt.org/directoryprivateKeySecretRef:# 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 nginxsolvers:- http01:ingress:ingressClassName: nginx
求解器采用 dns01
和 http01
节的格式。 有关如何配置这些求解器类型的更多信息,请访问其各自的文档 - DNS01、HTTP01。
外部帐户绑定
cert-manager 支持在您的 ACME 帐户中使用外部帐户绑定。 外部帐户绑定用于将您的 ACME 帐户与外部帐户(例如 CA 自定义数据库)关联。 这通常对于大多数 cert-manager 用户来说是不需要的,除非您知道它是明确需要的。
外部帐户绑定在 ACME Issuer
上需要两个字段,这些字段代表您的 ACME 帐户。 这些字段是
keyID
- 外部帐户绑定被外部帐户管理器索引的密钥 ID 或帐户 IDkeySecretRef
- 包含您的外部帐户对称 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/v1kind: ClusterIssuermetadata:name: my-acme-server-with-eabspec:acme:email: user@example.comserver: https://my-acme-server-with-eab.com/directoryexternalAccountBinding:keyID: my-keyID-1keySecretRef:name: eab-secretkey: secretprivateKeySecretRef:name: example-issuer-account-keysolvers:- http01:ingress:ingressClassName: nginx
注意:cert-manager 版本早于
v1.3.0
还要求用户通过设置Issuer.spec.acme.externalAccountBinding.keyAlgorithm
字段来指定 EAB 的 MAC 算法。 该字段现已弃用,因为上游 Gox/crypto
库将算法硬编码为HS256
。(参见上游相关讨论CL#41430
)。
重用 ACME 帐户
您可能希望在多个集群中重用单个 ACME 帐户。 这在使用 EAB 时特别有用。 如果设置了 disableAccountKeyGeneration
字段,cert-manager 将不会创建新的 ACME 帐户,而是使用 privateKeySecretRef
中指定的现有密钥。 请注意,Issuer
/ClusterIssuer
将不会处于就绪状态,并将继续重试,直到提供 Secret
。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: my-acme-server-with-existing-acme-accountspec:acme:email: user@example.comdisableAccountKeyGeneration: trueprivateKeySecretRef:name: example-issuer-account-key
添加多个求解器类型
您可能希望为不同的入口控制器使用不同类型的挑战求解器配置,例如,如果您想使用 DNS01
颁发通配符证书,以及使用 HTTP01
验证的其他证书。
solvers
节有一个可选的 selector
字段,可用于指定哪些 Certificates
以及这些 Certificates
上的哪些 DNS 名称应该用于解决挑战。
有三种选择器类型可用于形成 Certificate
必须满足的才能被选择为求解器的要求 - matchLabels
、dnsNames
和 dnsZones
。 您可以在单个求解器上拥有任意数量的这三种选择器。
匹配标签
matchLabel
选择器要求所有 Certificates
匹配该节中字符串映射列表中定义的所有标签。 例如,以下 Issuer
将只匹配具有标签 "user-cloudflare-solver": "true"
和 "email": "user@example.com"
的 Certificates
。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:matchLabels:"use-cloudflare-solver": "true""email": "user@example.com"
DNS 名称
dnsNames
选择器是应该映射到求解器的精确 DNS 名称列表。 这意味着包含任何这些 DNS 名称的 Certificates
将被选中。 如果找到匹配项,dnsNames
选择器将优先于 dnsZones
选择器。 如果多个求解器使用相同的 dnsNames
值匹配,则具有 matchLabels
中最多匹配标签的求解器将被选中。 如果两者都没有更多匹配项,则列表中定义更早的求解器将被选中。
以下示例将解决 DNS 名称 example.com
和 *.example.com
的 Certificates
的挑战,用于这些域。
注意:
dnsNames
采用精确匹配,不支持通配符解析,这意味着以下Issuer
不会 解析像foo.example.com
这样的 DNS 名称。使用dnsZones
选择器类型来匹配区域内的所有子域。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsNames:- 'example.com'- '*.example.com'
DNS 区域
dnsZones
段定义了此解析器可以解析的 DNS 区域列表。如果 DNS 名称是完全匹配,或指定 dnsZones
中任何一个的子域,此解析器将被使用,除非配置了更具体的 dnsNames
匹配。这意味着对于域 www.sys.example.com
,sys.example.com
将被选中,而不是指定 example.com
的那个。如果多个解析器具有相同的 dnsZones
值,则具有 matchLabels
中最多匹配标签的解析器将被选中。如果两个都没有更多匹配,则列表中较早定义的解析器将被选中。
在以下示例中,此解析器将解析域 example.com
以及其所有子域 *.example.com
的挑战。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsZones:- 'example.com'
全部一起
每个解析器都可以定义任意数量的这三种选择器类型。在以下示例中,DNS01
解析器将用于解决 Certificates
针对 a.example.com
和 b.example.com
这些 DNS 名称的挑战。DNS01
解析器将用于解决 Certificates
针对匹配区域 test.example.com
以及其所有子域(例如 foo.test.example.com
)的 DNS 名称的挑战。
对于所有其他挑战,HTTP01
解析器将仅在 Certificate
也包含标签 "use-http01-solver": "true"
时使用。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- http01:ingress:ingressClassName: nginxselector:matchLabels:"use-http01-solver": "true"- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsNames:- 'a.example.com'- 'b.example.com'- dns01:cloudDNS:project: my-project-idhostedZoneName: 'test-example.com'serviceAccountSecretRef:key: saname: gcp-sa-secretselector:dnsZones:- 'test.example.com' # This should be the DNS name of the zone
每个单独的选择器块可以包含多个选择器类型,例如
solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector: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/v1kind: ClusterIssuermetadata:name: my-acme-server-issuerspec:acme:server: https://my-acme-server.example.comcaBundle: <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/v1kind: Issuermetadata:name: letsencryptspec:acme:server: https://acme-v02.api.letsencrypt.org/directorypreferredChain: "ISRG Root X1"