最新:在TwitterMastodon

ACMEDNS

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: example-issuer
spec:
acme:
solvers:
- dns01:
acmeDNS:
host: https://acme.example.com
accountSecretRef:
name: acme-dns
key: acmedns.json

通常,ACMEDNS 的客户端代表用户执行注册,并告知他们必须创建的 CNAME 条目。这在 cert-manager 中是不可能的,它是一个非交互式系统。注册必须事先进行,并将生成的凭据 JSON 上传到集群作为 Secret。在本例中,我们使用 curl 和 API 端点直接进行操作。有关设置和配置 ACMEDNS 的信息,请参阅 ACMEDNS 项目页面.

  1. 首先,在 ACMEDNS 服务器上注册,在本例中,有一个服务器运行在 auth.example.com 上。命令

    curl -X POST http://auth.example.com/register

    将返回一个包含您的注册凭据的 JSON。

    {
    "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
    "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
    "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
    "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
    "allowfrom": []
    }

    强烈建议将更新端点限制为 Pod 的 IP 范围。这在注册时按如下方式进行

    curl -X POST http://auth.example.com/register \
    -H "Content-Type: application/json" \
    --data '{"allowfrom": ["10.244.0.0/16"]}'

    确保将 allowfrom 字段更新为匹配您的集群配置。现在 JSON 将如下所示:

    {
    "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
    "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
    "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
    "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
    "allowfrom": ["10.244.0.0/16"]
    }
  2. 将此 JSON 保存到一个以您的域名为键的文件中。如果您愿意,您可以使用相同的凭据指定多个域。在我们的示例中,返回的凭据可用于验证 example.comexample.org 的所有权。

    {
    "example.com": {
    "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
    "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
    "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
    "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
    "allowfrom": ["10.244.0.0/16"]
    },
    "example.org": {
    "username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
    "password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
    "fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
    "subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
    "allowfrom": ["10.244.0.0/16"]
    }
    }
  3. 接下来,使用 CNAME 记录更新您的主 DNS 服务器,该记录将告诉验证器如何找到挑战 TXT 记录。这是从注册中的 fulldomain 字段获得的。

    _acme-challenge.example.com CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com
    _acme-challenge.example.org CNAME d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com

    记录的“名称”始终具有 _acme-challenge 子域,“值”与注册中的 fulldomain 字段完全匹配。

    在验证时,域名 d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com 将是一个 TXT 记录,设置为您的验证令牌。当验证器查询 _acme-challenge.example.com 时,此 CNAME 记录将将其引导到正确的位置。这证明您控制着 example.com

  4. 从步骤 2 中保存的凭据 JSON 中创建一个密钥,此密钥在 DNS01 发行者设置的 accountSecretRef 字段中引用。创建 Issuer 时,此 IssuerSecret 必须在同一个命名空间中。但是,对于 ClusterIssuer(没有命名空间),Secret 必须放置在 cert-manager pod 运行的命名空间中(在默认设置中为 cert-manager)。

    kubectl create secret generic acme-dns --from-file acmedns.json

acme-dns 服务器的限制

acme-dns 服务器有一个 已知限制:当一组凭据与 2 个以上域一起使用时,cert-manager 将无法解决 DNS01 挑战。

假设您已使用一组凭据配置了 ACMEDNS 发行者,并且这组凭据的“子域”是 d420c923-bbd7-4056-ab64-c3ca54c9b3cf

kind: Secret
metadata:
name: auth-example-com
stringData:
acmedns.json: |
{
"example.com": {
"username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
"password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
"fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
"subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
"allowfrom": ["10.244.0.0/16"]
},
}
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: my-acme-dns
spec:
acme:
solvers:
- dns01:
acmeDNS:
accountSecretRef:
name: auth-example-com
key: acmedns.json
host: auth.example.com

并且假设您想要创建具有三个子域的证书

kind: Certificate
spec:
issuerRef:
name: issuer-1
dnsNames:
- "example.com"
- "*.example.com"
- "foo.example.com"

cert-manager 将只能以非确定性的方式解决 3 个挑战中的 2 个。此限制来自 此 acme-dns 问题中提到的“功能”。

一种解决方法是为我们要挑战的每个域颁发一组 acme-dns 凭据,请记住每个 acme-dns“子域”最多只能接受 2 个挑战域。例如,上面的密钥将变为

kind: Secret
metadata:
name: auth-example-com
stringData:
acmedns.json: |
{
"example.com": {
"username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
"password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
"fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
"subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
"allowfrom": ["10.244.0.0/16"]
},
"foo.example.com": {
"username": "eabcdb41-d89f-4580-826f-3e62e9755ef2",
"password": "pbAXVjlIOE01xbut7YnAbkhMQIkcwoHO0ek2j4Q0",
"fulldomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf.auth.example.com",
"subdomain": "d420c923-bbd7-4056-ab64-c3ca54c9b3cf",
"allowfrom": ["10.244.0.0/16"]
}

使用此设置,我们有

  • example.com*.example.com 在 acme-dns“子域” d420c923-bbd7-4056-ab64-c3ca54c9b3cf 中注册。
  • foo.example.com 在 acme-dns“子域” d420c923-bbd7-4056-ab64-c3ca54c9b3cf 中注册。

另一种解决方法是在运行 cert-manager-controller 时使用 --max-concurrent-challenges 2。使用此设置,acme-dns 的数据库中始终只有 2 个 TXT 记录,这缓解了该问题。