Let's Encrypt の証明書を発行するフローには ACME HTTP-01 と DNS-01 の2つがある。
HTTP-01 の場合、事前に 80 番ポートで対象となるドメインにファイルを設置する必要があり、またワイルドカード証明書に対応できない (と、思う)。
DNS-01 の場合は対象ドメインの DNS の TXT レコードに特定の内容を設定する必要があるが、発行にあたって事前に HTTP 通信を行う必要がないし、ワイルドカード証明書も発行できる。
cert-manager は k8s 上で TLS 証明書の取得や更新をするものであり、 ACME DNS-01 に対応している (たぶん HTTP-01 にも対応している)。
DNS の設定をおこなう必要があるが、各種 DNS プロバイダ にオフィシャルに (ビルトインで) 対応している、が、リストをみてもらえるとわかるとおり、有名どころはあるがその数は少ない。
さまざまな DNS プロバイダへの対応コードを cert-manager に組み込んでいくとメンテナンスやクオリティコントロールの面で課題があるので、 cert-manager は Webhook Issuer という形で、外部から拡張可能にしているらしい。
野良を含め Webhook Issuer は https://github.com/topics/cert-manager-webhook にリストアップされている。 が、残念ながらわたしが利用している LuaDNS は存在しなかった。
未対応の DNS プロバイダに対応するためには https://github.com/cert-manager/webhook-example を参考に実装していけばよい。
以前 Traefik on k8s で let's encrypt のワイルドカード TLS 証明書を自動発行する - daily dayflower で書いたように、 Traefik はもともと LuaDNS に対応している。 どのようなコードで対応しているのかな、と思ったが、実際には GitHub - go-acme/lego: Let's Encrypt/ACME client and library written in Go ライブラリを利用しているようだ。
lego の LuaDNS むけ実装 と cert-manager の webhook example 実装 を照らし合わせてみてみたが、 (DNS-01 チャレンジを実装するという意味で) 似たような構造になっている。
これならそこまで難しくなさそうだぞと思い、 cert-manager webhook の LuaDNS 向け実装を書き始めた……
が……
気づいてしまった。
LuaDNS 専用に書くより https://github.com/go-acme/lego のサポートしている DNS プロバイダを汎用的にサポートすることができるんじゃないか?
そもそもそういう実装がすでにあるんじゃないか?
と、思い、探してみました。すでにありました。
これで自力で開発する必要はなくなった (!) ので、ふつうにこれを使わせてもらうことにする。
(実際には ArgoCD での利用にちょっと問題があったので (あくまで Helm chart 部分だけだけど) fork してそれを使っている: https://github.com/yxwuxuanl/cert-manager-lego-webhook)
といっても、使い方は難しくはなく、 README にあるとおりにやればよい。
まず webhook を Helm でインストールする。
自分はいまは k8s cluster として MicroK8s を使っており、 cert-manager を addon として容易に追加できる。
この場合、 Helm install するときに指定する value としては certManager.namespace は cert-manager、および certManager.serviceAccountName も cert-manager となる。
次に Issuer リソース を登録する (以下の例では ClusterIssuer を使っている)。
--- apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: luadns-issuer spec: acme: privateKeySecretRef: name: luadns-issuer server: https://acme-v02.api.letsencrypt.org/directory email: EMAIL-ADDRESS solvers: - dns01: webhook: groupName: lego.dns-solver solverName: lego-solver config: provider: luadns envFrom: secret: namespace: LUADNS-SECRET-NAMESPACE name: LUADNS-SECRET
metadata.name (および spec.acme.privateKeySecretRef.name) は自由につけれる。
それ以外の部分は (おそらく) lego の LuaDNS プロバイダを利用するなら上記のような設定になると思う。
あとは一般的な cert-manager での証明書リソースの登録をすればよい。
--- apiVersion: cert-manager.io/v1 kind: Certificate metadata: namespace: default name: example.com spec: issuerRef: kind: ClusterIssuer name: luadns-issuer secretName: example.com-tls commonName: example.com dnsNames: - example.com - "*.example.com"
spec.issuerRef に上記で登録した Issuer を指定する。