2022/01/31

DNS プロバイダ文書の設定と実行結果の確認方法について

ずいぶん前の「テクてくLotus技術者夜会」で CertMgr タスクによる TLS 証明書の取得についてお話した際、スライド枚数の割りに実行結果を確認する方法といった細かいことには触れておらず、これから ACME DNS-01 チャレンジに挑戦したい場合にちょっと分かりづらいんじゃないかなとモヤモヤしてます。

今回は、DNSプロバイダ設定文書の設定内容と、実行結果を確認する方法について簡単にフォローしたいと思います。

まずは分かりづらいスライドで恐縮ですが、ご確認ください。


下図は、CertMgr タスクと Let's Encrypt と DNS の間でやりとりする DNS-01 チャレンジのフローを大雑把に示したものです。Dominoのアイコンが CertMgr タスクを示します。

ACME DNS-01

Domino と Let's Encrypt の間にある「CLOUDFLARE」は、私が保有するドメイン「dominov12beta.work」の DNS レコードをもつ「ホスティングプロバイダ」です。ここはご自身が使用する DNS プロバイダに読み替えてください。

CertMgr による証明書の取得に DNS-01 チャレンジを使う場合、DNS プロバイダ側へのDNS レコードの追加と削除(上の図の3番と7番にある Domino から CLOUDFLARE へ向いた青い矢印の部分)を REST API またはコマンドで実行できなければなりません。

DNS レコードの登録や削除を行う場合、REST API やコマンドを CertMgr が実行できるよう構成しなければなりませんが、その方法は DNS プロバイダによって異なります。REST API やコマンドを構成するための「式」を CertStore.nsf の「DNS プロバイダ設定」文書に記述します。

ただ、ここの「式」を白紙の状態から一つ一つ指定することはなかなか難しい...

ですが、CertStore.nsf には、「DNS プロバイダ設定」文書を簡単に作成できる「Import DXL」機能があります。誰かが「DNS プロバイダ設定」文書を作成し、Export した .DXL ファイルが公開されていれば、それを取り込んで作成することができます。私は、Daniel Nashed 氏がベータフォーラムに添付してくれていた .DXL ファイルをダウンロードしてそれをインポートしました。CLOUDFLARE 用の「DNS プロバイダ設定」文書はそこに含まれていました。.DXLファイルは、技術情報にある こちらの Article からもダウンロード可能です。

私が過去に利用していた MyDNS.jp の場合、ACMEプロトコルに対応した Certbot の提供はありますが、REST API の仕様は公開されていないようで、AWS CLI のようなコマンド発行できるツールもなさそうでしたので諦めました。
【2022/2/5 追記】DirectEdit というスクリプトを参考にして MyDNS.jp を使った証明書の取得に成功しました。そちらも別のエントリで紹介したいと思います。
一方 CLOUDFLARE は REST API のドキュメントがしっかり公開されています。なので私は MyDNS.jp から CLOUDFLARE へ DNS を乗り換えることにしました。

話を戻します。

私の環境にある「CLOUDFLARE」用の「DNS プロバイダ設定」文書では、[操作]タブの最上部を、下図のように設定しています。

ここの「要求 URL:」に、APIのベースURLがセットされています。要求URLの値は、[操作]タブの「HTTP 設定」以下に設定する「式」の中で "cfg_URL" という名前で呼び出すことができます。インポートした文書のプロパティ(下図)でも、アイテム名が "cfg_URL" としてセットされていることがわかります。

「ステータス式:」には、DNS へのレコード追加要求に対するレスポンス(retJSON_Add)の success が "true" のとき 200 (正常)としています。
「DNS プロバイダ遅延」には、DNS へ追加した TXT レコードが伝搬されるまでの時間を指定します。ここでは 20 (秒)としていますので、レコード追加の次の要求まで に 20 秒の待ちが入ります。


話を少し戻しますが、"cfg_URL" のようにどの文書のどのフィールドがどういった名前で呼び出し可能なのかは、こちらのブログ記事が良くまとまっていて参考になるかと思います。私はこの記事のおかげで理解が早まりました。

では「HTTP 設定」にある「HTTP 検索要求」を見てみます。

「HTTP 検索要求」の各項目では、DNS に対して REST API で TXT レコードの追加/削除を行うために必要な値を予め取得しておくといった場合に、取得する際のURLやヘッダー等のパラメータやレスポンスを分解して保存したりするための「式」を指定します。

話が少しそれますが、CLOUDFLARE に TXT レコードを追加する方法は Create DNS Record に書かれていますが、TXT レコードを追加するために、URI へ「ゾーン ID(zone identifier)」を含めなければなりません。
https://api.cloudflare.com/client/v4/zones
ですので、DNSレコードの追加する場合の URL は
https://api.cloudflare.com/client/v4/zones/<ゾーン ID>/dns_records
となります。ゾーン IDが分からないとTXTレコードの追加を行うことはできないのです。

ゾーン ID(zone identifier)は、CLOUDFLARE のWebサイトの「概要」ページから確認できます。

ゾーン IDを「DNS プロバイダアカウント」文書の [基本] タブにある「設定値」の中の「DNS ゾーン:」にあらかじめ記載しておけば、そこから「cfg_DnsZone」変数の値として式で読み込むことができます。
ですが、ゾーンID は API で取得することもできます。せっかくなので「DNS プロバイダ設定」文書の「HTTP 検索要求」を利用してゾーン ID を API で取得してみることにしました。

話を戻します。
「HTTP 検索要求」の「検索 URL 式:」の式には、url の name パラメータの値として param_RegisterdDomain フィールドを指定しています。このフィールドは「DNS プロバイダアカウント」文書の「登録済みドメイン:」の値を参照しています。また「検索ヘッダー式:」の式には、cfg_AuthToken が指定されています。こちらは「DNS プロバイダアカウント」文書の「認証トークン」の値を参照しています。

REST API を実行して戻ってきた JSON は retJSON_Lookup 変数に入ります。実際に入っていた JSON は下の様なものでした。

result という配列の最初(0)にある id の値(retJSON_Lookup.result.0.id)がゾーン識別子です。この id の値を「カスタム結果式:」の式で「cfg_DnsZone」フィールドの値として参照できます。

次は「HTTP 検索要求」の「検索ヘッダー式」です。ここには、REAT API 発行時のヘッダーへ設定する情報を生成するための式を指定します。
ヘッダーには、「DNS プロバイダアカウント」文書の「認証トークン」に値が無ければ、X-Auth-Email と X-Auth-Key と Content-Type を設定し、「認証トークン」に値があれば Authorization: Bearer と Content-Type  を設定します。式では、複数のヘッダーをコロン":"で区切るように設定します。
私は CLOUDFLARE で管理しているドメインのために作成した「DNS プロバイダアカウント」文書(下図)の「設定値」に、「認証トークン」だけ指定しました。他の「DNS ゾーン」や「Emailアドレス」等のフィールドには何も指定していません。

認証トークンの取得は CLOUDFLARE の場合、ダッシュボードからドメインの「概要」ページを開き、右側の「API」というくくりの中に「API トークンの取得」というリンクがあり、APIトークンのページ(下図)から作成できました。

次は「HTTP 追加要求」(下図)です。

ここの「URL式」と「ヘッダー式」については先に触れましたので割愛します。
「投稿データ式:」には、パラメータとその値で構成されたJSON文字列を作るための式を記述します。CLOUDFLARE では、DNSへ TXT レコードを追加する際に指定するパラメータは4つ(type, name, content, ttl)あり、各パラメータへセットする値は次のとおりです。

「type」... DNSレコードのタイプを指定します。TXT レコードなのでここは "TXT" とします。
「name」... ホスト名の頭に "_acme-challenge." を付けた値です。「TLS証明書」文書で「ホスト名」に "testserver.dominov12beta.work" とした場合、ここでは "_acme-challenge.testserver.dominov12beta.work" になります。
「content」... TXTレコードへセットする認証用トークンです。
「ttl」... 120 としましたが、1 をセットすると"自動"となるようです。

これらのうち name の値を param_DnsTxtName 、content の値を  param_DnsTxtValue という変数名で呼び出します。この2つの変数の値は CertMgr が Let's Encrypt とのやりとりの中から Let's Encrypt 側から指定された値をもとにセットしているようです。

最後は「HTTP 削除要求」(下図)です。

この中の「URL 式」では、TXTレコードの追加要求に対する応答(retJSON_Add)にあるJSONから result.id の値の有無によってURLの有無を決めています。
「ヘッダー式」は「HTTP 追加要求」と同じですので割愛します。



さて、CertMgr タスクを起動するときに -d オプションを付けるとデバッグモードになります。CertMgr タスクが起動している場合はいったん「tell certmgr q」で終了し「load certmgr -d」で起動します。

【重要なメモ】 
デバッグモードで起動すると、データディレクトリ内の IBM_TECHNICAL_SUPPORT フォルダ内に "certmgr_debug_<domino name>_yyyy_mm_dd@hh_nn_ss.txt" といったテキストが作成され、詳細な情報が記録されます。

認証局への要求を開始するまでには、
  1. 「グローバル設定」を構成する
  2. 「ACME アカウント」文書を開いて Let's Encrypt の利用規約に了承する
  3. 「TLS 証明書」文書を作成して「要求の送信」をクリックする
といった手順がありますが、これらは「DNS-01 チャレンジを使用して証明書要求の準備をする」を参照していただくこととして、ここでは割愛します。


「TLS証明書」文書を開いて「要求の送信」をクリックすると、要求はペンディングの要求として加えられます。CertMgr タスクがペンディングの要求を処理していくのですが、なかなか処理が始まらない場合は「tell certmgr process」を投入します。

-d オプションを付けた CertMgr が要求を処理すると、上のメモに書いたようにログファイルが作成されます。
ログファイルでは、Let's Encrypt や CLUDFLARE との間のやりとりとその結果が詳細に記録されています。
主なやりとりにはほぼほぼ "------- NewOrder:Headers -------" といったようなヘッダー情報があります。それらはテキストエディタの検索機能を使い ":Headers " という文字列で検索することで順を追って調べるのに役立ちました。
ちなみに、私がドメインの証明書を最初に要求したときのログでは次の順に記録されていました。(※必ずしもこの順になるとは限りませんが参考まで)
------- NewOrder:Headers -------
------- Authorization:Headers -------
------- ret_LookupResult:Headers -------
------- ret_AddResult:Headers -------
------- Authorization:Headers -------
------- Challenge:Headers -------
------- Authorization:Headers -------
------- Authorization:Headers -------
------- OrderCheckReady:Headers -------
------- Finalize:Headers -------
------- OrderCheckValid:Headers -------
------- Certificate:Headers -------
------- ret_DelResult:Headers -------

そして要求に対するレスポンスコードが、これら文字列のすぐ下に "HTTP/1.1 201 Created" や "HTTP/1.1 200 OK" のように記録されていました。これらのレスポンスコードが 200 番台であることが正常かどうかを判断する一つの目安になると思います。

これらが DNS と Let's Encrypt のどちらと何のやりとりするためのヘッダーなのかは、これらの文字列の数行上あたりにある "CURL-URL [" という文字列で始まる行を探すと URL が記録されていますので、それで判断できそうです。ちなみに "ret_○○○Result:Headers" は DNS への要求、そのほかは Let's Encrypt への要求でした。

また、要求へ設定するヘッダーやPOSTするデータの値、結果の判定式などが、DNS プロバイダ設定文書で指定した式のとおりに組み立てられたかどうかも、ログで確認することができます。

私は試していませんが「"@example.com" のようなメールアドレスを使うとブラックリストによってはじかれる」という噂があり、それが本当なら「ACME アカウント」文書の「E メールアドレス」が原因で "------- NewOrder:Headers -------" 以前のやりとりで却下される可能性があるように思います。

という訳で、最初はデバッグモードで出力したログとにらめっこしてみてはいかがでしょうか。

0 件のコメント:

コメントを投稿