ShellScript
MacOSX
launchd
Slack

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に投稿を参考にしてください。