【Zabbix】Windows端末から特定のトリガーを無効化／有効化する手法について

#はじめに
やりたいことは、定期的に出力するアラート（例：毎週日曜22:00にｘｘｘサービスを停止し22:10に起動）を抑止することです。
※Zabbixサーバ（Linux）とWebGUIを操作する端末（Windows）は分離されている想定で、今回はWindows端末のみで目的を達成したい考えです。

ZabbixのGUI操作で設定できないか調べてみましたが、対応方法は見つけられませんでした。
(Zabbixにはメンテナンス機能がありますが、ホスト単位によるアラート抑止になるため、必要なアラートも抑止されてしまいます。)

調べている過程で、Zabbix APIを使えばトリガー単位で制御できそうだと思い、試してみました。

#環境
Zabbixサーバ（Centos7）にWindows10からWebブラウザで操作する想定。
・Centos7.1
・ZABBIX 3.0.31
・windows10　Pro（1909)

#Zabbix APIについて
####①Zabbix APIとは
WebGUIを操作せずに、ホストの追加などの設定変更や、各種設定情報などの参照を行うことができます。
今回はその中の以下２つを使用します。
・user.login
　　Zabbixにログインしトークンを取得
・trigger.update
　　トリガーの設定変更

####②ZabbixAPIの利用方法
以下のURLへパラメータを渡すことで使用します。

```text:【URL】
http://Zabbixサーバのホスト名（またはIPアドレス）/zabbix/api_jsonrpc.php
```


パラメータはZabbixAPIのメソッドごとに規定されています。
以下は例としてuser.loginとtrigger.updateのパラメータを記載します。

```text:【パラメータ】（例）user.login
{
　"auth":null,
　"method":"user.login",
　"id":"1",
　"params":{
　　　"user":"ユーザーID",
　　　"password":"パスワード"
　},
　"jsonrpc":"2.0"
}
```

```text:【パラメータ】（例）trigger.update
{
　"auth":トークンID,
　"method":"trigger.update",
　"id":"1",
　"params":{
　　　"triggerid":"トリガーID",
　　　"status":1または2（1:有効/2:無効）
　},
　"jsonrpc":"2.0"
}

```
####③ZabbixAPIを実際に利用してみる
CURLコマンドを使用し、ZabbixAPIのURLへパラメータを渡します。
コマンドは以下の通りです。
※Windows版curlでは　-dオプション内の　"　を認識させるには、\　でエスケープする必要があります。

```text:コマンド（例）user.login
curl -X GET -d "{\"auth\":null,\"method\":\"user.login\",\"id\":\"1\",\"params\":{\"user\":\"zabbixadmin\",\"password\":\"zabbix1!\"},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
```

```text:コマンド結果（例）user.login
{"jsonrpc":"2.0","result":"70434f055799f167b835601bc2623efd","id":"1"}
```
"result":"～"　の部分がログイン後に発行されたトークンIDです。
（上記だと70434f055799f167b835601bc2623efd）
ZabbixAPIを利用する際にauthにトークンIDを記載することでログイン状態を維持し、ZabbixにAPI経由での操作ができるようになります。


```text:コマンド（例）trigger.update
curl -X GET -d "{\"auth\":\"70434f055799f167b835601bc2623efd\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"13491\",\"status\":1},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
```
```text:コマンド結果（例）trigger.update
{"jsonrpc":"2.0","result":{"triggerids":["13491"]},"id":"1"}
```

user.login　と　trigger.update　を使用することで、
Windows端末のコマンドラインでトリガーの有効/無効を操作できました。

これらをバッチ化し、タスクスケジューラに登録することでトリガーの無効/有効を自動化することができます。

#バッチの概要
対象トリガーIDはファイルに記載し、そのファイルを引数にします。
また、トラブルシューティングできるように実行ログも出力させます。

バッチの流れとしては、以下のようにしたいと思います。
①停止（または開始）対象のTriggerIDをテキストファイルに記載。
②「①」のファイルを引数にし、バッチ実行。
③実行結果をログファイルに出力。


####ToriigerIDを記載するファイル
対象のトリガーIDをただ記載するだけです。対象トリガーIDが複数ある場合は1行につき1IDで記載します。

```text:triggerid.txt
13491
13492
```

####バッチファイル
トリガーの有効・無効は
set CURLCMD2　の　行で　trigger.update　のパラメータを修正。
\"status\":0　　トリガー有効
\"status\":1　　トリガー無効

以下は有効にした際のバッチ（status\":0）。
※ZabbixIDとパスワード、URLは環境に合わせて要修正

```bat:zabbix_trigger_on.bat
@echo off

cd /d %~dp0
set crDir=%CD%\

set NOWTIME=%time:~0,2%%time:~3,2%%time:~6,2%
set NOWTIME=%NOWTIME: =0%
set TODAY=%date:~0,4%%date:~5,2%%date:~8,2%
set LOG=%crDir%log\%TODAY%%NOWTIME%_TriggerEnable.log

set TRIGGER_ID=%1

set ZABBIX_ID=Admin
set ZABBIX_PW=zabbix
set ZABBIX_URL=http://192.168.123.130/zabbix/api_jsonrpc.php

echo %date% %time% Batch Start >> %LOG% 2>&1

set CURLCMD1=curl -sS -X GET -d "{\"auth\":null,\"method\":\"user.login\",\"id\":\"1\",\"params\":{\"user\":\"%ZABBIX_ID%\",\"password\":\"%ZABBIX_PW%\"},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" %ZABBIX_URL%
echo %CURLCMD1% >> %LOG% 2>&1

for /f "usebackq tokens=4 delims=,:" %%A in ( `%CURLCMD1%` ) do set STRREC=%%A >> %LOG% 2>&1
echo. >> %LOG% 2>&1

set ZABBIX_TOKEN=%STRREC:~0,-2%\"

set CURLCMD2=curl -sS -X GET -d "{\"auth\":\%ZABBIX_TOKEN%,\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"%%B\",\"status\":0},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" %ZABBIX_URL%
echo %CURLCMD2% >> %LOG% 2>&1

for /f %%B in ( %TRIGGER_ID% ) do (
 echo %CURLCMD2%
 %CURLCMD2%
 echo. 
) >> %LOG% 2>&1

echo %date% %time% Batch End >> %LOG% 2>&1

```


####logファイルの出力先を作成
バッチファイルとトリガーIDを記載したテキストファイルを同じフォルダに配置し、
同階層にlogフォルダを作成する。
![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644439/785f7741-9840-c53e-3a0b-7f87f05678ac.jpeg)

#バッチの実行について
バッチにトリガーIDを記載したファイルを引数として渡して実行。

```cmd:コマンド
zabbix_trigger_off.bat triggerid.txt
```
```text:実行結果
2020/05/29  1:00:56.32 Batch Start 
curl -sS -X GET -d "{\"auth\":null,\"method\":\"user.login\",\"id\":\"1\",\"params\":{\"user\":\"Admin\",\"password\":\"zabbix\"},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php 
 
curl -sS -X GET -d "{\"auth\":\"3ad1459971b8833e082ab0fd076709ae\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"%B\",\"status\":1},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php 
curl -sS -X GET -d "{\"auth\":\"3ad1459971b8833e082ab0fd076709ae\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"13491\",\"status\":1},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":{"triggerids":["13491"]},"id":"1"} 
curl -sS -X GET -d "{\"auth\":\"3ad1459971b8833e082ab0fd076709ae\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"13492\",\"status\":1},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":{"triggerids":["13492"]},"id":"1"} 
2020/05/29  1:00:56.64 Batch End 
```

ZabbixのWebGUIからレポート→監査の画面を開き、トリガーが無効化（Statusが0→1に変化）されていることを確認。
![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644439/11a37cf3-aadc-1eda-17e3-58099689d658.jpeg)

#まとめ
このバッチをタスクスケジューラに以下のように登録することで、
トリガー単位で該当時間帯のアラート抑止ができました。
該当時間以降にもアラート検知することも確認できました。

| 起動日時 | タスク名 | 実行コマンド |
|:-------|--------------:|:-------------------------------------:|
| 22:00  | トリガー無効   | zabbix_trigger_off.bat triggerid.txt  |
| 22:10  | トリガー有効   | zabbix_trigger_on.bat triggerid.txt   |

#疑問点
「バッチの実行について」で実行したバッチの内部では、引数とするトリガーIDが2つしかないのにcurlコマンドが3回実行されていました。
（%B　という引数が余計に渡されている）

1回目　%B
2回目　13491
3回目　13492



バッチ内の該当箇所を単体でコマンド実行してみると、2回しか実行しませんでした。

```text:コマンド（　for　をコマンド実行する際は　%%B　を　%B　に変える必要有り）
set CURLCMD2=curl -sS -X GET -d "{\"auth\":\"c8da2c1add3e2918c8a2f28be9eb8f4d\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"%B\",\"status\":0},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php

for /f %B in ( triggerid.txt ) do (
 %CURLCMD2%
 echo.
)
```

```text:実行結果（CURLコマンドは想定通り2回実行）
curl -sS -X GET -d "{\"auth\":\"c8da2c1add3e2918c8a2f28be9eb8f4d\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"13491\",\"status\":0},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":{"triggerids":["13491"]},"id":"1"}
curl -sS -X GET -d "{\"auth\":\"c8da2c1add3e2918c8a2f28be9eb8f4d\",\"method\":\"trigger.update\",\"id\":\"1\",\"params\":{\"triggerid\":\"13492\",\"status\":0},\"jsonrpc\":\"2.0\"}" -H "Content-Type: application/json-rpc" http://192.168.123.130/zabbix/api_jsonrpc.php
{"jsonrpc":"2.0","result":{"triggerids":["13492"]},"id":"1"}
```

でも、もう一度バッチから実行すると3回実行されていました・・・
（どういうロジックなんだ・・・）