Edited at

Macのログインを検出し、Slackへ通知する

More than 1 year has passed since last update.

スクリーンショット 2016-10-23 12.51.01.png

※ slackのformatをいじったらこんな感じになりました。


概要


  • サービス管理フレームワーク(launchd)を利用し、スクリプトを定期実行する

  • スクリプトで、ログイン成功を検出し、Slackへ通知する

  • ライフログとして利用したり、コンピュータ紛失時のアクティビティ監視に応用できる


環境

以下の環境で、動作確認を行いました。

$ sw_vers                                                                          

ProductName: Mac OS X
ProductVersion: 10.11.5
BuildVersion: 15F34


ログインを検出する

LINEやAmazon、Googleなどは、ログイン時にメールやメッセージを、ユーザに送るようになりました。不正ログインによる被害を最小限にする施策です。このようなログインアクティビティの通知は、不正ログインの被害を抑えるだけでなく、ライフログとして活用できます。

今回は、日常的に利用しているMac OS XSlackを使ってログインアクティビティの通知を行います。


Mac OS Xのログイン履歴

Macの場合、ログイン成功のログは、/var/log/accountpolicy.logにあります1。ほかのさまざまなログは、console.appから確認できます。

ログイン成功のログは以下のようになっています。各レコードでcompletedという文字列を見つければよさそうです。

Oct 23 03:36:55 (73.392.1) AuthenticationAllowed completed: record "tamanobi", result: Success (0).

Oct 23 03:36:55 (73.393.1) AuthenticationAllowed completed: record "tamanobi", result: Success (0).
Oct 23 03:40:41 (73.394.1) AuthenticationAllowed completed: record "tamanobi", result: Success (0).
Oct 23 03:40:41 (73.395.1) AuthenticationAllowed completed: record "tamanobi", result: Success (0).


10秒以内にログインしていたら通知する

上記で説明したログには、日時が記録されています。チェックしたときの日時と、何秒前の記録まで通知するか決めればよさそうです。

シェルスクリプトを書いてみました。最後に出てくるwebhook.shは、[10分で出来る]シェルスクリプトの結果をslackに投稿を参考にしてください。


noticeLoginActivity.sh

#!/bin/bash

set -eux

# 実行時の日時から、何秒前のレコードをSlack通知の対象とするか
INTERVAL=10
# ログファイルのフルパス
LOGFILENAME=$1

function dateComp()
{
# Oct 23 01:59:20 形式から経過秒に変換
ARG1_SECOND=`date -j -f "%b %d %H:%M:%S" "$1" "+%s"`
ARG2_SECOND=`date -j -f "%b %d %H:%M:%S" "$2" "+%s"`

expr $ARG1_SECOND - $ARG2_SECOND
}

# ログのレコードから、時間を"%b %d %H:%M:%S"形式で取得
function record2date()
{
RECORD=`echo $1 | awk '{print $1 " " $2 " " $3}'`
echo $RECORD
}

NOW=`date '+%b %d %H:%M:%S'`
PREV=`date -v-${INTERVAL}S '+%b %d %H:%M:%S'`

# ダブルクオーテーションがあると変数展開時に厄介なので、アスタリスクに置換
LAST_RECORD=`tail -n 1 "$LOGFILENAME" | sed -e 's/"/*/g'`

DATETIME_LAST_RECORD=`record2date "$LAST_RECORD"`
MAX_DIFF_DATETIME=`dateComp "$NOW" "$PREV"`
DIFF_DATETIME_LAST_RECORD=`dateComp "$NOW" "$DATETIME_LAST_RECORD"`

if [[ $MAX_DIFF_DATETIME -gt $DIFF_DATETIME_LAST_RECORD ]]; then
if
[[ "$LAST_RECORD" =~ completed ]];then
echo "User logged in!\n$LAST_RECORD" | sh /Users/tamanobi/webhook.sh
fi
fi



定期的にログを確認して、監視をする

監視にはログインフックを利用することもできますが、定期的にログを確認するシンプルなアプローチを今回は採用します。


launchdを利用してプログラムを定期実行する

定期実行といえば、cronですが今回は利用しません。代わりに、launchdというサービス管理フレームワークを利用します。

以下は、launchdでできることの一例です。



  • cronのように任意のスクリプトを定期実行する

  • ファイルの変更を監視し、変更時に任意のスクリプトを実行する


プログラムを定期実行するための設定ファイルを作成する

launchdを利用するには、XMLで書かれた設定ファイルを登録する必要があります。今回用意した設定ファイルを載せます。

記述量は多めですが、重要なのは以下の3つだけです。

* プロセスのラベル

* コマンド

* 定期実行の間隔(秒)


~/Library/LaunchAgents/monitoringLoginActivity.plist

<?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>monitoringLoginActivity</string>

<key>ProgramArguments</key>
<array>
<!-- コマンド -->
<string>bash</string>
<!-- コマンドに渡す第一引数 -->
<string>/Users/tamanobi/noticeLoginActivity.sh</string>
<!-- コマンドに渡す第二引数 -->
<string>/var/log/accountpolicy.log</string>
</array>

<key>StartInterval</key>
<!-- 定期実行の間隔(秒) -->
<integer>10</integer>

<key>StandardOutPath</key>
<!-- 出力を保存するファイルへのパス -->
<string>/tmp/monitoringLoginActivity.out</string>

<key>StandardErrorPath</key>
<!-- エラーを保存するファイルへのパス -->
<string>/tmp/monitoringLoginActivity.err</string>
</dict>
</plist>



動かしてみる

登録する前に必要なファイルの確認です。以下のファイルが必要です。


  • ~/Library/LaunchAgents/monitoringLoginActivity.plist

  • /Users/tamanobi/noticeLoginActivity.sh

  • /Users/tamanobi/webhook.sh2


launchdに登録する

launchdを操作するには、launchctlコマンドを使用します。launchctl loadでplistを登録できます。登録したら、すぐに10秒ごとに監視が動き出します。

$ launchctl load ~/Library/LaunchAgents/monitoringLoginActivity.plist

エラーログや出力結果は、設定したとおり/tmp/monitoringLoginActivity.err/tmp/monitoringLoginActivity.outで確認できます。


launchdの登録を削除するには launchctl unloadを使う

登録したものはlaunchctl unloadで削除できます。

$ launchctl unload ~/Library/LaunchAgents/monitoringLoginActivity.plist


launchdの登録一覧をみるには launchctl listを使う

登録したものはlaunchctl listで確認できます。量が多いので、設定したラベルでgrepすることをおすすめします。

$ launchctl list


完成!(実際にログインし直してみる)

実際にログインし直してみると、Slackに通知が来ます。

スクリーンショット 2016-10-23 6.43.34.png


ログインアクティビティを通知する


まとめ

この記事では、MacのログインアクティビティをSlackに通知する方法を紹介しました。

一例として、Slackに通知を送りましたが、スクリプト次第で別のサービスへ通知を送ることもできます。ログインしたタイミングで、特定のビルドを走らせたり、本日の予定を画面に表示させることもできるでしょう。

また、ログインアクティビティをストレージに保存しておけば、ライフログとして活用できるでしょう。職業プログラマなら生産性の指標になるかもしれません。


参考リンク





  1. バージョンごとに違う可能性があるので注意して下さい。 



  2. [10分で出来る]シェルスクリプトの結果をslackに投稿を参考にしてください。