2017/11/06

SSL 証明書の更新チェック

最近は Let's Encrypt を利用する機会が多くなっているので SSL 証明書の更新は基本的に自動で実行しているが、 通常の SSL 証明書の場合は有効期間のチェックが必要なので定期的にチェックするスクリプトを作成した。
このスクリプトは SSL 証明書から有効期限を取得し現在の日付と比較してチェックを行い、

  • 有効期間が 30 日以内の場合は 1 日に 1 度
  • 有効期間が 10 日以内の場合は実行するたび
slack にメッセージを投稿する。
ubuntu サーバでの動作を前提としたスクリプトなので SSL 証明書ファイルは /etc/apache2/sites-enables/0000-default-ssl.conf から取得しているが、 SSL 証明書ファイルを直接指定する事で汎用的に動作させる事が可能となっている。
slack に投稿するためには予め slack にアクセスし Webhook URL を取得する必要がある。

  1#!/bin/sh
  2# SSL 証明書の有効期限をチェックして slack に通知する
  3# 1日数回の実施 (10:00 / 13:00 / 16:00 / 18:00) を想定している
  4
  5host=${1:-`hostname`}
  6cert=$(awk '{ gsub(/#.*/, ""); if($1 == "SSLCertificateFile") print $2; }' /etc/apache2/sites-enabled/000-default-ssl.conf)
  7check=/tmp/sslcheck-send
  8
  9# slack の API フック指定
 10target='https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
 11user="${host} SSLチェック"
 12
 13# リミット
 14soft=$((30 * 24 * 60 * 60))
 15hard=$((10 * 24 * 60 * 60))
 16
 17send_slack()
 18{
 19
 20    icon=${1}
 21    shift
 22
 23    curl -X POST -H 'Content-type: application/json' --data '{"text": "'"${*}"'", "icon_emoji": "'"${icon}"'", "username": "'"${user}"'" }' ${target} > /dev/null 2>&1
 24
 25}
 26
 27# 証明書から有効日を取得
 28limit=$(date -d "$(openssl x509 -noout -text -in ${cert} | sed -n '/Not After/s/.* : \(.*\).*/\1/p')" '+%Y/%m/%d %H:%M:%S')
 29limit_s=$(date -d "${limit}" '+%s')
 30today=$(date -d "00:00:00" '+%Y/%m/%d %H:%M:%S')
 31today_s=$(date -d "${today}" '+%s')
 32
 33current_s=$((${limit_s} - ${today_s}))
 34current=$((current_s / (24 * 60 * 60)))
 35
 36if [ ${current_s} -lt 0 ]
 37then
 38    # 証明書期限切れ
 39    send_slack ":red_circle:" "*ホスト${host}のSSL証明書の期限が${limit}で終了しています。大至急更新作業をして下さい。*"
 40    echo ${update} > ${check}
 41elif [ ${current_s} -le ${hard} ]
 42then
 43    # 証明書期限まで残り 10 日以内
 44    send_slack ":bangbang:" "_ホスト${host}のSSL証明書の期限が${limit}までです (残り${current}日)。至急更新作業をして下さい。_"
 45elif [ ${current_s} -le ${soft} ]
 46then
 47    # 証明書期限まで残り 30 日以内 (1日1回通知)
 48    update=$(date '+%m%d')
 49    if [ -f ${check} -a "$(cat ${check})" -eq ${update} ]
 50    then
 51        :
 52    else
 53        send_slack ":warning:" "ホスト${host}のSSL証明書の期限が${limit}まです (残り${current}日)。更新作業をして下さい。"
 54        echo ${update} > ${check}
 55    fi
 56fi
    

このスクリプトを crontab などで一日数回自動的に実行する様に設定すると、定期的に SSL 証明書の有効期限が確認できる。
slack を利用していない場合、send_slack の部分を変更する事でメール送信などに変更する事ができる。

メール送信する場合のサンプルも以下に示す。
この例では POSIX 準拠のコマンド以外に nkf(1) と base64(1) が必要となっている。

  1send_mail()
  2{
  3
  4    sendmail="/usr/sbin/sendmail -i -t"
  5    from="送信元メイルアドレス"
  6    to="受信先メイルアドレス"
  7    subject=$(echo "サブジェクト" | nkf -WM)
  8    body=$(echo ${*} | sed -e "s/;/\n/g" -e "/^\$/s/\$/\r/" -e "/[^\r]\$/s/\$/\r/" | base64)
  9
 10    cat << EOF | ${sendmail}
 11From: ${from}
 12To: ${to}
 13Subject: ${subject}
 14
 15${body}
 16EOF
 17
 18}
    


Copyright © 2008-2020 Mitzyuki IMAIZUMI. All rights reserved.