みなさんこんにちは。テックデザインの河野です。
1/23(木)にヤマハ銀座スタジオで行われた「ヤマハMeetup東京2020 ~Happy New Year~」のライトニングトークセッションに参加させていただき、ヤマハルーターのSyslogをLuaスクリプトで監視して、ルーターへのログイン/ログアウトを検出したらSlackへ通知するというデモを行いました。今回はそのSlack通知Luaスクリプトを紹介いたします。
本記事ではvRXを使って解説をしています。お手元にヤマハルーターがなくても、AWSアカウントをお持ちであれば vRX無償トライアルライセンスがなくても試すことが可能です。動作確認は vRX Rev.19.00.01 (Fri Sep 13 12:13:56 2019)とRTX830 Rev.15.02.14で行っています。
1. ヤマハルーター対応機種について
通知はSlackのIncoming WebhookにHTTPリクエストで送信しています。HTTPSを使用するため、ヤマハルーターに搭載されているLuaバージョンが1.08以上である必要があります。ヤマハルーターの現行機種では、NVR500を除く全ての機種対応しています。
[対応機種]
RTX5000/RTX3500/RTX1210/RTX830
NVR700W/NVR510
vRX
参考:Lua スクリプト機能バージョンの変更履歴
http://www.rtpro.yamaha.co.jp/RT/docs/lua/#version
2. 通知メッセージのフォーマット
通知メッセージの1行目は見出しとして太字にし、2行目は検知したSyslogメッセージとします。また、メッセージの重要度や緊急性が一目で分かるように赤・黄・緑の3色に色分けをして通知します。

3. ソースコード
> 下記のLuaスクリプトをダウンロードすることができます。(解凍してお使いください)
◆ヤマハルーターSlack通知Luaスクリプト 動作環境:LUAスクリプト機能バージョン 1.08以上 動作機種:RTX5000/RTX3500/RTX1210/RTX830/NVR700W/NVR510/vRX --]] ----------------## 初期設定 ##------------------- -- 検出したいSYSLOG文字列パターン ptn = "Log%l%l%l* " -- Slack Incoming Webhook URL url = "(Webhook URL)" -- Slackチャンネル名 -- 例:#general channel = "(通知先チャンネル名)" -- Slack通知ユーザー名 -- 例:vRX Syslog監視bot botname = "(表示ユーザー名)" ------------## 初期設定ここまで ##----------------- -------------------------------------------------- -- 通知カラー名・Subject設定用関数 -------------------------------------------------- function make_arg(syslog_message) if string.find(syslog_message, "succeeded") ~= nil then color_name = "green" subject = "*情報:ログイン成功*" end if string.find(syslog_message, "failed") ~= nil then color_name = "yellow" subject = "*注意:ログイン失敗*" end if string.find(syslog_message, "Logout ") ~= nil then color_name = "green" subject = "*情報:ログアウト*" end if string.find(syslog_message, "restricted") ~= nil then color_name = "red" subject = "*警告:ログイン制限中*" end return color_name, subject end -------------------------------------------------- -- カラー名・RGB変換用関数 -------------------------------------------------- function set_rgb_color(color_name) if color_name == "green" then return "#01bc77" elseif color_name == "red" then return "#ec4301" elseif color_name == "yellow" then return "#ffc759" else -- gray return "#e3e4e6" end end -------------------------------------------------- -- Slackペイロード作成用関数 -------------------------------------------------- local function make_payload(channel, botname, color_name, subject, syslog_message) -- カラー名をRGBに変換 local color_rgb = set_rgb_color(color_name) -- メッセージ部 local text = subject .. "\\n" .. syslog_message -- ペイロードを作成 local payload = "payload={\"channel\": \"" .. channel .. "\", \"username\": \"" .. botname .. "\", \"mrkdwn\": true, \"attachments\": [{\"color\": \"" .. color_rgb .. "\", \"text\": \"" .. text .. "\", \"mrkdwn_in\": [\"text\"]}]}" return payload end -------------------------------------------------- -- Slack通知用関数 -------------------------------------------------- function post_slack(url, payload) local req_t = { url = url, method = "POST", content_type = "application/x-www-form-urlencoded", post_text = payload } -- SlackにPOST local rsp_t = rt.httprequest(req_t) -- エラー処理 if (rsp_t.code ~= 200) then -- デバッグ用 print("Post failed.") print(rsp_t.rtn1, rsp_t.rtn2, rsp_t.err, rsp_t.code, rsp_t.header) end end -------------------------------------------------- -- メインルーチン -------------------------------------------------- local rtn, str, color_name, subject, payload while (true) do rtn, str = rt.syslogwatch(ptn, 1) if (rtn) and (str) then color_name, subject = make_arg(str[1]) payload = make_payload(channel, botname, color_name, subject, str[1]) post_slack(url, payload) end end
4. 解説
初期設定
ユーザー環境に合わせて設定が必要になるのは初期設定の4項目のみです。
SYSLOG文字列の監視は rt.syslogwatch
コマンドで行っています。監視する文字列にはLua正規表現パターンを利用することができますがカッコを用いたキャプチャ機能には対応していないため、残念ながらあまり複雑なパターンを作ることはできません。
下記の例では「Login 」と「Logout 」(末尾に半角スペース付き)を検知するため、共通部分「Lo」のあとに2〜3文字の任意の英小文字の文字列を表す「%l%l%l*」と半角スペースを付けています。
検知する文字列を変更したい場合は、このパターンを変更してください。
Luaの正規表現については下記に詳しく解説されています。
Lua言語のライブラリ関数
http://www.rtpro.yamaha.co.jp/RT/docs/lua/tutorial/library.html#pattern
また、本稿ではSlackのIncoming Webhook URLの取得方法については割愛します。
下記参考に設定し、取得してください。
Slack での Incoming Webhook の利用 | Slack
https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8
----------------## 設定値 ##-------------------- -- 検出したいSYSLOG文字列パターン ptn = "Log%l%l%l* " -- Slack Incoming Webhook URL url = "(Webhook URL)" -- Slackチャンネル名 -- 例:#general channel = "(通知先チャンネル名)" -- Slack通知ユーザー名 -- 例:vRX Syslog監視bot botname = "(表示ユーザー名)" ------------## 設定値ここまで ##----------------
通知カラー名・Subject設定用関数
ここでは通知メッセージのカラーと1行目の文字列を設定しています。
色指定は最終的にRGBで行いますが、追加や変更がしやすいように green や red など名前で指定しています。
また、検知したSYSLOGメッセージに「succeeded」「failed」「Logout 」「restricted」が含まれているかをチェックし、パターン毎に1行目の文字列を設定しています。
-------------------------------------------------- -- 通知カラー名・Subject設定用関数 -------------------------------------------------- function make_arg(syslog_message) if string.find(syslog_message, "succeeded") ~= nil then color_name = "green" subject = "*情報:ログイン成功*" end if string.find(syslog_message, "failed") ~= nil then color_name = "yellow" subject = "*注意:ログイン失敗*" end if string.find(syslog_message, "Logout ") ~= nil then color_name = "green" subject = "*情報:ログアウト*" end if string.find(syslog_message, "restricted") ~= nil then color_name = "red" subject = "*警告:ログイン制限中*" end return color_name, subject end
カラー名・RGB変換用関数
green / red/ yellow の文字列を RGB 値に変換し、それ以外の文字列が与えられた場合にはグレーの RGB 値を返します。後述の「Slack ペイロード作成用関数」から呼び出して使っています。
-------------------------------------------------- -- カラー名・RGB変換用関数 -------------------------------------------------- function set_rgb_color(color_name) if color_name == "green" then return "#01bc77" elseif color_name == "red" then return "#ec4301" elseif color_name == "yellow" then return "#ffc759" else -- gray return "#e3e4e6" end end
Slackペイロード作成用関数
Incoming Webhook API に送信する JSON 形式のペイロードを作成します。
Slack のペイロード仕様については下記で詳しく説明されています。
Reference: Message payloads | Slack
https://api.slack.com/reference/messaging/payload
-------------------------------------------------- -- Slackペイロード作成用関数 -------------------------------------------------- local function make_payload(channel, botname, color_name, subject, syslog_message) -- カラー名をRGBに変換 local color_rgb = set_rgb_color(color_name) -- メッセージ部 local text = subject .. "\\n" .. syslog_message -- ペイロードを作成 local payload = "payload={\"channel\": \"" .. channel .. "\", \"username\": \"" .. botname .. "\", \"mrkdwn\": true, \"attachments\": [{\"color\": \"" .. color_rgb .. "\", \"text\": \"" .. text .. "\", \"mrkdwn_in\": [\"text\"]}]}" return payload end
Slack通知用関数
rt.httprequest
関数を使い、Webhook URL に HTTP POSTメソッドで作成したペイロードを送信します。
-------------------------------------------------- -- Slack通知用関数 -------------------------------------------------- function post_slack(url, payload) local req_t = { url = url, method = "POST", content_type = "application/x-www-form-urlencoded", post_text = payload } -- SlackにPOST local rsp_t = rt.httprequest(req_t) -- エラー処理 if (rsp_t.code ~= 200) then -- デバッグ用 print("Post failed.") print(rsp_t.rtn1, rsp_t.rtn2, rsp_t.err, rsp_t.code, rsp_t.header) end end
送信に失敗した場合は、デバッグ用としてコンソール上にHTTPリクエストの送信結果、エラーメッセージ、HTTPステータスコード、レスポンスデータのヘッダを出力するようにしています。
下記は誤った Webhook URL を設定した際の出力です。ステータスコード 403 がヒントになりますね。
vRX> Post failed. true nil nil 403 HTTP/1.1 403 Forbidden Date: Sun, 01 Mar 2020 18:00:20 GMT Server: Apache Vary: Accept-Encoding X-Slack-Backend: h Strict-Transport-Security: max-age=31536000; includeSubDomains; preload Referrer-Policy: no-referrer X-Frame-Options: SAMEORIGIN Access-Control-Allow-Origin: * Connection: close Transfer-Encoding: chunked Content-Type: text/html X-Via: haproxy-www-rtkx
メインルーチン
rt.syslogwatch
関数を while true
のループで実行することでSYSLOGを監視し続けます。指定した文字列を検知すると、
1)make_arg
関数で検知内容に適合する通知カラーとSubjectを設定
2)make_payload
関数でペイロード作成
3)post_slack
関数で Incoming Webhook URL に作成したペイロードを送信
の順に実行します。
-------------------------------------------------- -- メインルーチン -------------------------------------------------- local rtn, str, color_name, subject, payload while (true) do rtn, str = rt.syslogwatch(ptn, 1) if (rtn) and (str) then color_name, subject = make_arg(str[1]) payload = make_payload(channel, botname, color_name, subject, str[1]) post_slack(url, payload) end end
5. Luaスクリプトをヤマハルーターに転送する
初期設定が完了したら、tftp
コマンドや sftp
コマンドで slack.lua をルーターに転送します。
$ sftp -i ~/.ssh/vRX_key.pem XX.XX.XX.XX Connected to XX.XX.XX.XX. sftp> put slack.lua /slack.lua Uploading slack.lua to /slack.lua slack.lua 100% 503 23.3KB/s 00:00 sftp> quit
転送が完了したらヤマハルーターにSSHでログインして管理者ユーザーに切り替え、 schedule at
コマンドでsyslog_watch.luaをルーター起動時に開始するように設定します。既にスケジュールが登録されている場合は、環境に合わせてスケジュール番号を適宜変更してください。
vRX# schedule at 1 startup * /slack.lua
スケジュールコマンドを登録したらルーターをいったん再起動して、Luaスクリプトが自動的に起動するか確認します。show status lua
コマンドを実行して、[running] に slack.lua が表示されていれば成功です。
vRX> show status lua Luaライブラリバージョン: Lua 5.1.5 Luaスクリプト機能バージョン: 1.08 [running] LuaタスクID (状態): 1 (WATCH) 走行トリガー: スケジュールによる実行 コマンドライン: lua /slack.lua スクリプトファイル: /slack.lua 監視文字列: "Log%l%l%l* " 開始日時: 2020/03/02 00:34:40 経過時間: 38分51秒 (以下省略) ```
6. 動作確認
実際にログインやログアウトを行うことで動作確認をすることができますが、LTデモで行ったように管理者ユーザーでSYSLOGを直接書き込む方法でも動作確認をすることができます。
vRX# lua -e "rt.syslog(\"INFO\", \"2020/03/02 03:14:45: [TEST] Login succeeded : XX.XX.XX.XX as administrator\")"
ヤマハのウェブサイトには既に多くの実用的な設定例が公開されていますが、「Google 認証システムの確認コード生成方法に準じたワンタイムパスワードを設定する」は「Luaでここまで機能拡張ができるのか!」と個人的に最も衝撃を受けた設定例です。外部サービスと連携するとヤマハルーターをより便利に面白く使うことができると思いますので、「私はこんな使い方をしているよ!」みたいな例があれば Twitter や Facebook で教えていただけると嬉しいです。
関連記事
- なかせのコラム ヤマハのコラム 更新情報
ヤマハ株式会社が「Interop Tokyo 2023」に出展!SCSKも参加予定です!
- さくらのコラム ヤマハのコラム 更新情報
ヤマハ出展の「第14回 EDIX(教育総合展)東京」 訪問レポート
- おがわのコラム ヤマハのコラム 技術コラム
ヤマハNWファンミーティング2023 Spring @Youtubeライブ アンケートQ&A その3
- かとうのコラム コラム はじめてのヤマハUTX ヤマハのコラム 更新情報
はじめてのヤマハUTX 第3回 ~UTXシリーズ紹介②~
- かとうのコラム コラム はじめてのヤマハUTX ヤマハのコラム 更新情報
はじめてのヤマハUTX 第3回 ~UTXシリーズ紹介①~