macOSで、さくらのクラウドのDNSを利用してSSL証明書取得/更新を自動化する

[主題]
macOSで、さくらのクラウドのDNSと、zerossl-botcertbot)を利用して、dns-01チャレンジによるドメイン認証を行い、SSL証明書取得/更新を自動化する手順を説明したい。

[背景]
zerossl-botcertbot)のドメイン認証方法には、http-01チャレンジと、dns-01チャレンジの二種類がある。このうちhttp-01チャレンジは、V6プラス環境下では使えない。残るdns-01チャレンジは、DNSにプログラムからアクセス可能である(APIが用意されている)必要がある。
一方、無料SSL証明書の有効期限は90日と短い。うっかり更新し忘れないためにも、自動化する仕組みは必要である。

[環境]
参考までに、筆者の環境を記載しておく
MacBook Pro 2018 15.4inch(インテルMac)
macOS 13.2 Ventura
MacBook Pro 2016 13inch(インテルMac)
mmacOS 12.6.2 Monterey

[前提条件]
以下を前提条件とする。

  1. ZeroSSLのアカウント
    ZeroSSLのアカウントがある事。

  2. DNSの設定
    さくらのクラウドのDNSを契約して、所有しているドメインのDNS設定を済ませてある事。
    参考:DNS(アプライアンス) | さくらのクラウド ドキュメント

  3. APIキーの取得
    さくらのクラウドにて、APIキーを作成、アクセストークン、およびアクセストークンシークレットを入手してあること。
    参考:APIキー | さくらのクラウド ドキュメント

  4. python3のインストール
    macOSは、最新バージョンの13.2(本稿執筆時)においても、以下のパスにpython3がインストールされている。

    $ /usr/bin/python3 --version
    Python 3.9.6

    しかし、後述するシェルスクリプトの関係から、最新バージョンを導入する事を推奨する。(または、スクリプトで、適切なパスを設定する)

[手順]

  1. certbot-dns-sakuracloudプラグインのインストール
    WebサーバーをインストールしてあるMacにPipを用いてインストールする。これにより、certbotも一緒にインストールされる。Homebrewを用いない理由は、このプラグインがないためである。

    pip3 install certbot-dns-sakuracloud
  2. certbotのシンボリックリンク
    シンボリックリンクを/usr/local/binに張る。

    sudo ln -s `which certbot` /usr/local/bin/
  3. APIキーファイルの作成
    さくらのクラウドのAPIキーをファイルに書いて置く。

    cd ${HOME}
    sudo vim .sakura

    記述する内容

    dns_sakuracloud_api_token = 'ここにアクセストークン'
    dns_sakuracloud_api_secret = 'ここにアクセストークンシークレット'

    アクセス権の変更
    変更しないとcertbotに怒られる。

    cd ${HOME}
    sudo chmod 600 .sakura
  4. zerossl-botの入手と改造
    現時点で入手できるzerossl-botにはバグがあり、修正が必要である。また自動実行のためには、certbotのパスをフルパスに書き換える必要がある。

    入手

    bash <(curl -s https://zerossl.com/get-zerosslbot.sh)

    修正個所
    修正個所をdiff形式で示す。

    sudo vim /usr/local/bin/zerossl-bot
    --- a/zerossl-bot.sh
    +++ b/zerossl-bot.sh
    @@ -5,9 +5,9 @@
     function parse_eab_credentials()
     {
         PYTHONIOENCODING=utf8
    -    ZEROSSL_EAB_KID=$(echo $1 | python -c "import sys, json;
    +    ZEROSSL_EAB_KID=$(echo $1 | python3 -c "import sys, json;
     print(json.load(sys.stdin)['eab_kid'])")
    -    ZEROSSL_EAB_HMAC_KEY=$(echo $1 | python -c "import sys, json;
    +    ZEROSSL_EAB_HMAC_KEY=$(echo $1 | python3 -c "import sys, json;
     print(json.load(sys.stdin)['eab_hmac_key'])")
         CERTBOT_ARGS+=(--eab-kid "$ZEROSSL_EAB_KID" --eab-hmac-key "$ZEROSSL_EAB_HMAC_KEY" --server "https://acme.zerossl.com/v2/DV90")
     }
    @@ -40,4 +40,4 @@
         parse_eab_credentials $(curl -s https://api.zerossl.com/acme/eab-credentials-email --data "email=$ZEROSSL_EMAIL")
     fi
    
    -certbot ${ARGS[@]}
    +/usr/local/bin/certbot ${CERTBOT_ARGS[@]}
  5. SSL証明書取得(初回)
    初回のみ、以下のコマンドを実行する。

    sudo zerossl-bot certonly \
    --dns-sakuracloud \
    --dns-sakuracloud-credentials ~/.sakura \
    --manual-public-ip-logging-ok \
    -m your_mail@exsample.jp \
    -d example.com \
    --agree-tos
    1. メールアドレスは、ZeroSSLに登録したアカウントのものを書く。(上の記述はダミー)

    2. ドメイン名は、所有している物を書く。(上の記述はダミー)

    3. コマンド実行の結果、zerossl-botcertbot)は、設定ファイルを作成し、次回以降は、以下のコマンドで、SSL証明書の更新が出来るようになる。

      sudo zerossl-bot renew
  6. launchdプロパティリストの作成
    cronではなく、launchdを用いて、スクリプトの定期実行を設定する。

    cd /Library/LaunchDaemons/
    sudo vim jp.yourName.zerossl-bot_renew.plist

    yourNameは、あなたの名字に置き換える。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>jp.yourName.zerossl-bot_renew</string>
        <key>ProgramArguments</key>
            <array>
                <string>/usr/local/bin/zerossl-bot_renew</string>
            </array>
        <key>RunAtLoad</key>
            <true/>
        <key>StartCalendarInterval</key>
            <dict>
                <key>Weekday</key>
                <integer>7</integer>
                <key>Hour</key>
                <integer>0</integer>
                <key>Minute</key>
                <integer>0</integer>
            </dict>
        <key>StandardErrorPath</key>
            <string>/Users/yourUserName/Library/Logs/zerossl-bot_renew_error.log</string>
        <key>StandardOutPath</key>
            <string>/Users/yourUserName/Library/Logs/zerossl-bot_renew_output.log</string>
    </dict>
    </plist>
    1. 6行目。LabelにあるyourNameは、あなたの名字に置き換える。

    2. 13行目〜21行目。StartCalendarIntervalは、本例では、毎週日曜日の0時0分に実行する設定である。この説明を参照して、任意の設定に変える事も出来る。

    3. 23, 25行目。yourUserNameは、あなたのログインユーザー名に置き換える。

  7. プロパティリストで実行するシェルスクリプトの作成

    sudo vim /usr/local/bin/zerossl-bot_renew
    #!/bin/sh
    #
    # a shellscript to renew certificates with zerossl-bot
    #
    # 2023.02.19 Tougenroushi
    
    # Every file path should be written as absolute path.
    # You can't use ${HOME} as home directory path, nor use `which` to
    # find out command's path.
    
    # renew certificatetes with zerossl-bot (certbot)
    /usr/local/bin/zerossl-bot renew
    
    # if last 4 lines of the file "zerossl-bot_renew_output.log" contains
    # string "succeeded", then apache web server should be restarted
    OUTFILE="/Users/yourUserName/Library/Logs/zerossl-bot_renew_output.log"
    RESULT=$(tail -n 4 "$OUTFILE")
    
    if [[ "$RESULT" =~ "succeeded" ]]; then
       /usr/local/apache2/bin/apachectl stop
       sleep 5
       /usr/local/apache2/bin/apachectl start
    fi
    1. 16行目。yourUserNameは、あなたのログインユーザー名に置き換える。

    2. 16, 17行目。プロパティリストのStandardOutPathで定義したログファイルには、12行目のコマンドの実行結果が追記出力される。このファイルの最後の4行は、直近の実行結果なので、それを取り出している。

    3. 19行目。取り出した4行にsucceededの文字列が含まれるかどうかの判定。すなわち、SSL証明書の更新に成功したかどうかの判定。

    4. 21行目。シェルスクリプトでapacheを停止/開始させる場合、一定の時間待ちが必要。5秒が最適かどうかは不明。

    シェルスクリプトを実行可能にする

    sudo chmod 755 /usr/local/bin/zerossl-bot_renew
  8. launchdプロパティリストの登録
    以下のコマンドで、作成したlaunchdプロパティリストを登録する。

    cd /Library/LaunchDaemons/
    sudo launchctl load -w jp.youreName.zerossl-bot_renew.plist

    yourNameは、あなたの名字に置き換える。

参考サイト

以上。

この投稿へのコメント

コメントはありません。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL