はじめに
SSL証明書の有効期限が近付いた場合は警告メールを送ってくれるサービスもありますが、警告メールのタイトル・内容が英文になっていることで見逃してしまうことや、また届いたこと・期限が近いことは把握していてもうっかり有効期限切れ直前に急な割り込みにより失念してしまうこともあります。
そこで、、、
・メールとは違う何かで通知
・有効期限に近づいた時は通知頻度を短くして何度も通知
を実現したいと考えました。
幸い、既に以下のような仕組み
があったのでそれを流用して、
・メールとは違う何かで通知
→ Slackで通知
・有効期限に近づいた時は通知頻度を短くして何度も通知
→ シェルスクリプトで30日、14日、7日、3日以内は毎日通知
を実現しようと思います。
システム概要図
※今回の構成図もLucidchartを利用させてもらい作成しました。(無料枠)
大まかなフローは以下の通りです。
- 有効期限チェック
- 通知
- 確認
- 更新
今回の記事では「有効期限チェック」の部分に焦点をあてて説明します。
シェルスクリプト
概要図中の実行環境で動かすシェルスクリプトです。
SSL証明書の有効期限取得、チェック、Slack投稿を行います。
# !/bin/bash
HOSTLIST=(
"xxx.secual-inc.com:443"
)
WORKDIR="/public/toolz/check_cert"
RESULT_MSG=$WORKDIR"/check_cert_msg.txt"
RESULT_JSON=$WORKDIR"/check_cert.json"
LOCKFILE="/var/run/check_cert.lock"
if [ -f $LOCKFILE ]; then
echo "Already exist lock file. ["$LOCKFILE"]"
exit 9
fi
trap '{
rm $LOCKFILE;
exit $EXIT;
}' EXIT
touch $LOCKFILE
NOW=`date +%s`
EXIT=0
echo -n > $RESULT_MSG
for host in "${HOSTLIST[@]}"; do
STREXPIREDATE=`openssl s_client -connect $host < /dev/null 2> /dev/null | openssl x509 -text | grep "Not After" | sed -e 's/.*Not After : //g'`
if [ -z "$STREXPIREDATE" ]; then
continue;
fi
EXPIREDATE=`date --date="$STREXPIREDATE" +%s`
LAST=$(($((EXPIREDATE-NOW)) / 60 / 60/ 24))
if [ $LAST -gt 30 ]; then
continue;
elif [ $LAST -lt 30 ] && [ $LAST -gt 14 ]; then
continue;
elif [ $LAST -lt 14 ] && [ $LAST -gt 7 ]; then
continue;
elif [ $LAST -lt 7 ] && [ $LAST -gt 4 ]; then
continue;
fi
STREXPIREDATEJST=`date -d @$EXPIREDATE +"%Y/%m/%d %H:%M:%S"`
if [ $LAST -gt 0 ]; then
echo -n "△ : " >> $RESULT_MSG
else
echo -n "× : " >> $RESULT_MSG
fi
echo $host" : 有効期限["$STREXPIREDATEJST"]" >> $RESULT_MSG
done
if [ ! -s $RESULT_MSG ]; then
EXIT=1
exit
fi
###############################################################################
### post slack
###############################################################################
echo 'payload={"channel": "#service_checker", "username": "service checker bot", "text": "@here 証明書の有効期限通知です。 \n```' > $RESULT_JSON
cat $RESULT_MSG | sed -z 's/\n/\\n/g' >> $RESULT_JSON
echo '```", "icon_emoji": ":guardsman:", "link_names" : true}' >> $RESULT_JSON
curl -s -X POST -d @$RESULT_JSON https://hooks.slack.com/services/xxxxx/xxxxx/xxxxx
EXIT=0
exit
ロックファイルやtrapの話は、是非以下の記事を参照ください。
シェルスクリプト+ロックファイルで二重実行防止 - Qiita
https://qiita.com/SECUAL_masa/items/5b1b7e8c4ed13c420435
それ以外については、個別に説明していきます。
チェック対象ホストリスト
HOSTLIST=(
"xxx1.secual-inc.com:443"
"xxx2.secual-inc.com:443"
)
SSL証明書を利用しているサーバー&チェック対象のサーバーを列挙していきます。
"ホスト名:ポート番号"の形式になっています。これは次に記載する有効期限を取得するためのコマンドで利用するのがこの形式になっているためです。
有効期限取得
STREXPIREDATE=`openssl s_client -connect $host < /dev/null 2> /dev/null | openssl x509 -text | grep "Not After" | sed -e 's/.*Not After : //g'`
この部分が今回の肝になります。上記コマンドで有効期限を取得します。
openssl s_client -connect $host < /dev/null 2> /dev/null | openssl x509 -text
↑の部分でSSLの証明書の情報が取得でき、また"Not After"の部分が有効期限になりますので、それをgrep "Not After"で取り出し、また"sed -e 's/.*Not After : //g'"で後の日数算出に利用しやすい形式に整形します。
Aug 04 20:24:54 2021 GMT
有効期限変換(日時 → 日数)
EXPIREDATE=`date --date="$STREXPIREDATE" +%s`
LAST=$(($((EXPIREDATE-NOW)) / 60 / 60/ 24))
通知を
・30日
・14日
・7日
・3日以内
で実施しますので、その判定のための日数を取得するためいったん”Aug 04 20:24:54 2021 GMT"をUnixTimeに変換し、さらに日数に変換しています。
1628108694
30
以降はその日数の判定と、Slackへ投稿するメッセージの構築、投稿になりますので省略します。
定期実行設定
あとはシェルスクリプトをcronで指定して定期的に実行するようにします。
0 9 * * * /public/toolz/check_cert/check_cert.sh
Slackへの通知
今回の仕組みで最終的に以下のようにSlackに投稿されます。