Zabbix - это популярное средство мониторинга в компьютерных сетях. Основными принципами работы программы заключается во взаимодействии сервера и агентов (программы, устанавливающиеся на хосты), но вы можете этим не ограничиваться. В Zabbix доступны и другие инструменты, которые позволяют запускать скрипты, в том числе и Powershell. Такой подход позволяет добавлять в Zabbix нужные для вас данные или вести дополнительную аналитику получая данные с сервера.
Основная цель этой статьи показать, как выполнять взаимодействие между Zabbix и Powershell. Подразумевается, что у вас есть какое-то понимание работы этого средства мониторинга.
Варианты получения и отправки данных в Zabbix с Powershell
Инструменты, которые будут показываться в статье, условно можно разделить на 2 части. Создающиеся или хранящиеся на сервере Zabbix:
- Скрипты (Scripts) - это скрипты, которые можно использовать в веб-интерфейсе Zabbix. По сути кнопки;
- External Scripts - папка, в которую можно поместить скрипт и привязать его к какому-то хосту;
- API - HTTP интерфейс, к которому можно обращаться получая большую часть данных или создавать/редактировать существующие элементы;
Клиентские инструменты, которые чаще всего используются на хостах (клиентах):
- zabbix_sender - отдельная программа, которая отправляет данные на сервер Zabbix;
- zabbix_get - отдельная программа для получения данных с хостов, на которых установлен zabbix_agent. Обычно используется для тестирования;
- UserParameter - параметр, который устанавливается в конфигурации агентов на хостах. С помощью его так же можно отправить данные на сервер.
- system.run - в отличие от UserParameter позволяет выполнять любой скрипт, а не определенный.
Zabbix_get и zabbix_sender идут вместе с агентом, который можно скачать с официального сайта.
Отправляем данные на сервер
В Zabbix есть 2 разных способа обработки полученных данных. Если вы отправляете результат похожий на следующий, то вы должны использовать обычный 'Item' (Элементы данных):
(Get-ADUser -Filter * -Properties LockedOut).Count
Еще один тип - 'Discovery rules' (правила обнаружения) и 'Item Prototype' (Прототипы данных) используются, когда вам нужно обработать массив данных. В 'Discovery rules' попадают массивы следующего вида (формат JSON). Пример такого формата в Powershell и сконвертированная версия в JSON:
$somedata = @{
data=@(
@{'{#Переменная1}'='Значение1'; '{#Переменная2}'='Значение2'};
@{'{#Переменная1}'='Значение3'; '{#Переменная2}'='Значение4'};
)
}
$somedata | ConvertTo-Json
Этот массив проходит через цикл, где для каждого из его значения выполняется какая-то функция - для этого и нужен 'Item Prototype'. Для лучшего понимания мы можем итерировать массив и выполнить функцию для его значение в Powershell так:
foreach ($obj in $somedata.data){
# Какая-то функция
somefunc($obj['{#Переменная1}'])
}
Items и Discovery rules (с Item Prototype) создаются в разных местах:
Описанное выше нужно хорошо понимать т.к. легко столкнуться с ошибкой из-за неверного выбора.
zabbix_sender
Приложение, которое может отправлять данные без использования агента, называется zabbix_sender. Как и говорилось выше - его можно скачать в архиве с агентом. По сути эта программа отправляет данные в формате JSON, на сервер Zabbix, по порту 10050.
Перед тем как отправлять данные на сервер - мы должны создать хост к которому эти данные будут относиться.
Необходимо указать только название хоста и группу. В этом случае IP адрес и DNS имя не имеет значение, так как мы сами будем отправлять данные:
Далее мы должны создать новый 'Item' внутри которого заполнить поля:
- Name (3) - имя элемента (играет значение внутри самого веб-интерфейса Zabbix);
- Type (4) - тип данных (в нашем случае это Zabbix Trapper, обозначающий получение каких-то данных от пользователя);
- Key (5) - название ключа (на ваше усмотрение), которое нужно указывать при отправке через zabbix_sender;
- Type of information (6) - тип данных. В нашем случае - это число.
После создания элемента - мы можем отправить данные уже с сервера. Используем скрипт, который возвращает количество заблокированных пользователей:
$users_locked = (Get-ADUser -Filter * -Properties LockedOut).Count
.\zabbix_sender.exe -z 192.168.2.60 -s "randomhost" -k users.blocked -o $users_locked
Были использованы следующие ключи:
- -z - адрес сервера Zabbix;
- -s - хост, который вы создавали;
- -k - ключ, который создавался у хоста;
- -o - значение, которое вы хотите передать.
Значение 'processed' говорит, что вы успешно отправили данные. Если вы видите ваш результат failed, то один из параметров заполнен неверно (либо не создан на стороне сервера, проблема с фаерволом). Результат работы команд так же можно увидеть на странице 'Latest Data'.
Готовый скрипт можно поместить в планировщик задач и получать подобные данные регулярно.
UserParameter
Еще один способ отправить данные в Zabbix - UserParameter. Этот параметр указывается в конфигурационном файле агента. Его плюсы в том, что агент может работать как служба (сервис) и вы можете устанавливать расписание опроса в самом Zabbix (т.е. без планировщика задач).
Конфигурационный файл агента можно найти в архиве вместе с агентом. Он будет иметь название 'zabbix_agentd.conf'. Для примера используем ту же команду, что и выше. Добавьте следующую строку в конфигурационный файл:
UserParameter=users.locked,powershell -Command "(Get-ADUser -Filter * -Properties LockedOut).Count"
По сути UserParameter говорит, что если вы обратитесь к ключу 'users.locked', будет вызвана следующая команда/скрипт.
Агент может работать в пассивном (сервер забирает информацию сам) и активном режиме (агент сам отправляет). Далее подразумевается, что остальная часть агента уже была вами настроена (вы должны обязательно заполнить Server и Hostname).
После указания UserParameter нужно установить новый конфигурационный файл, если вы используете агент как службу. В своем случае я использую фоновый режим:
.\zabbix_agentd.exe -c 'C:\zabbix_agent-5.0.19-windows-i386\conf\zabbix_agentd.conf' -f
Уже в самом Zabbix мы должны создать новый хост (или использовать старый) для установки связи с агентом. В отличие от предыдущего способа - мы должны указать название хоста аналогичное указанному в конфигурационном файле (Hostname) и верный IP:
При создании 'Item' (элемента данных) мы должны указать 'Zabbix agent' (пассивный ражим) или 'Zabbix agent active' (активный режим, при заполненном ServerActive) в зависимости от вашего режима.
В 'Update Interval' так же можно указать временный интервал для получения данных.
Передача параметров
В примере выше мы получали общее значение заблокированных пользователей в числовом эквиваленте. Мы можем использовать параметры что бы узнавать заблокирован ли конкретный пользователь. Используя только Powershell это можно сделать так:
[int](Get-ADUser -Filter {Name -eq 'someuser'} -Properties LockedOut).LockedOut
Используя UserParameter можно передавать параметры (в нашем случае название нужного пользователя) в команду. Для этого измените или добавьте следующий UserParameter в конфигурационный файл Zabbix:
# Старый вариант
UserParameter=users.locked,powershell -Command "(Get-ADUser -Filter * -Properties LockedOut).Count"
# Новый вариант
UserParameter=users.locked[*],powershell -Command "[int](Get-ADUser -Filter {Name -eq '$1'} -Properties LockedOut).LockedOut"
Значение '$1' соответствует первому переданному параметру. Второй и последующий параметры будут соответствовать следующим обозначениям '$2', '$3' и т.д.
Уже в самом 'Item' мы сможем указывать нужные значения параметров:
Если у вас сложности при работе с такими ключами - попробуйте использовать zabbix_get, который описан ниже. Он часто используется при тестировании.
Discovery Rules и Item Prototype
В примере выше пришлось создавать 'Item' для отдельного пользователя 'администратор'. Если пользователей много, то мы можем упростить процесс проверки разделив задачу на две. В первую очередь нужно создать массив определенного формата.
Для примера создадим массив с пользователями, которых нужно проверять. Мы можем получить его автоматически, но так как для понимания это будет более сложный пример - возьмем уже готовый:
$somedata = @{
data=@(
@{'{#NAME}'='администратор';};
@{'{#NAME}'='krbtgt';};
)
}
$somedata | ConvertTo-Json -Compress
После этого мы должны создать ключ в Zabbix, который примет подобный массив. Если вы используете 'zabbix_sender', то создавайте тип 'Zabbix trapper' (как на скриншоте). Если вы хотите использовать UserParameter - используйте 'Zabbix agent'/'Zabbix agent active' или посмотрите на предыдущий пример.
После этого мы должны привязать функцию, которая будет обрабатывать элементы массива:
В качестве функции, которая будет применять к значениям массива, я буду использовать ключ 'users.locked', созданный раньше через UserParameter:
Обратите внимание, что значение 'Name' должно быть уникальным и для этого была использована переменная '{#NAME}'.
Отправка данных будет выглядеть следующим образом:
$somedata = @{
data=@(
@{'{#NAME}'='администратор';};
@{'{#NAME}'='krbtgt';};
)
}
$json = $somedata | ConvertTo-Json -Compress
.\zabbix_sender.exe -z 192.168.2.60 -s "AD-1" -k users.list -o $json
Результат примерно следующим:
Отправка массивов в Zabbix, с помощью Powershell и zabbix_sender, может привести к нескольким ошибкам:
- В zabbix неверно преобразуется кириллица;
- Zabbix неверно распознает массив и выдает ошибку: 'Value should be a JSON object'.
Ошибку с Json можно исправить дополнительно экранировав массив кавычками:
$json = $json -replace '"','"""'
Есть еще способы, которые в некоторых случаях могут помочь. Например сохранение скрипта в файл с кодировкой 'UTF-8' или поместить скрипт в следующую конструкцию (меняет кодировку вывода):
# Сохраняем предыдущую кодировку
$prev = [Console]::OutputEncoding
# Меняем кодировку на UTF8
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
# Тут находится наш скрипт
# Меняем кодировку на первоначальную
[Console]::OutputEncoding = $prev
Отмечу, что решить проблему с отображением кириллицы через zabbix_sender (windows powershell) у меня так и не вышло. За время, которое я пытался с этим разобраться, можно было сделать свой zabbix sender. Такие реализации есть на разных языках , в том числе Powershell. Правда в версии Powershell (называется 'Send-ZabbixTrap.ps1'), доступной через NuGet, так же есть проблема с кириллицей.
Проблемы с кириллицей нет, если использовать UserParameter, который можно создать по примеру ниже:
Любой скрипт с system.run
Еще одна возможность, которая поддерживается агентами zabbix, выполнять любые скрипты через инструкцию 'system.run'. По умолчанию эта инструкция запрещена т.к. легко может привести к уязвимостям. Включив эту инструкцию вы позволите серверу выполнять любые скрипты на хостах. Это и является отличием от UserParameter, которые ограничивают возможности определенными скриптами.
В конфигурационных файлах агентов вы должны добавить следующую инструкцию:
AllowKey=system.run[*]
После этого, создавая Item, ItemPrototype или Discovery rulse, мы можем указывать ключи с целым скриптом. Например это можно сделать так:
# запускаем скрипт на хосте
system.run[powershell -File C:\script2.ps1,]
# выполняем одну или несколько команд
system.run[powershell.exe -c Get-Process,]
Пример создания Item и результат полученной информации:
Получение данных от Zabbix
В основном есть два способа получить данные для обработки в Powershell - это API и zabbix_get. Лучшим вариантом будет считаться API т.к. он имеет много возможностей и не требует настроек со стороны агента.
Получаем данные через zabbix_get
Программа zabbix_get, идет в архиве с агентом. Чаще всего используется для тестирования работы UserParameter в агентах. По сути она работает так же как Zabbix сервер запрашивая с хостов нужные данные. Одно из условий работы этой программы - прописанный 'Server' в конфигурации агента. Этот параметр указывает, с каких адресов могут получать данные.
Этих серверов может быть несколько. Например так я могу запрашивать данные локально и с сервера Zabbix:
Так мы получим данные по работающему агенту и по количеству заблокированных пользователей (используя UserParameter который создавался раннее):
./zabbix_get -s 127.0.0.1 -p 10050 -k agent.ping
./zabbix_get -s 127.0.0.1 -p 10050 -k users.locked
Пример получения значений, которые создаются и обрабатываются через 'Discovery Rules':
# получаем данные в формате json
$discovery_rules = ./zabbix_get -s 127.0.0.1 -p 10050 -k net.if.discovery
# преобразовываем в массив Powershell
$object = $discovery_rules | ConvertFrom-Json
Получение данных с API
Если в случае с zabbix_get мы получали данные с хостов с запущенным агентом, то с помощью API мы можем получить данные с самого Zabbix сервера. Кроме получения данных мы так же можем создавать и изменять существующие данные, а так же выполнять скрипты.
Перед началом работы - нужно получить токен доступа, который будет работать в качестве "пароля" для запросов к API. Токен является временным, срок его работы так же можно узнать через один из методов. Так могут быть ограничения в доступе - примеры ниже выполнялись от пользователя с правами 'Zabbix Super Admin'.
В примере ниже мы получим токен. Не забудьте указать свой логин, пароль и адрес сервера:
$data = @{
"jsonrpc"="2.0";
"method"="user.login";
"params"=@{
"user"="Admin";
"password"="zabbix";
};
"id"=1
}
$token = (Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json")
Обратил внимание, что основной HTTP метод, который используется в Zabbix API - POST. Возможно где-то используется GET, UPDATE и DELETE, но в документации об этом не говорится.
Самая важная часть подобного запроса - значение 'method'. Именно в нем мы указываем что мы хотим получить. В 'params' указываются значение для фильтрации (где-то будут обязательные параметры, а где-то нет). Список методов очень большой и указан в документации.
Используя этот токен мы можем выполнять разные запросы к API. Например так мы получим список всех хостов, которые добавлены в Zabbix:
$data = @{
"jsonrpc"="2.0";
"method"="host.get";
"params"=@{
};
"id"=2;
"auth"=$token;
}
$result = Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json"
Если добавить к запросу несколько параметров, то можно ограничить количество полученной информации:
$data = @{
"jsonrpc"="2.0";
"method"="host.get";
"params"=@{
"output"=@(
"hostid";
"host";
);
};
"id"=2;
"auth"=$token;
}
$result = Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json"
В запросах к API (так же как и к базам), чаще всего, используются не имена, а идентификаторы. Так, на предыдущем скриншоте, мы получили значение HostID, а так получим триггеры, которые к нему привязаны:
$data = @{
"jsonrpc"="2.0";
"method"="trigger.get";
"params"=@{
"hostids"=@(10270;);
};
"auth"=$token;
"id"=1;
}
Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json"
Еще один пример, где мы получаем список скриптов на сервере Zabbix и выполняем его на одном из хостов:
# получаем ID скрипта
$data = @{
"jsonrpc"="2.0";
"method"="script.get";
"params"=@{
};
"auth"=$token;
"id"=1;
}
$result = Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json"
$result.result | select name, scriptid
# выполняем скрипт на хосте
$data = @{
"jsonrpc"="2.0";
"method"="script.execute";
"params"=@{
"scriptid"=1;
"hostid"=10272;
};
"auth"=$token;
"id"=1;
}
$result = Invoke-RestMethod -Method 'Post' -Uri 'http://192.168.2.60/zabbix/api_jsonrpc.php' -Body ($data | ConvertTo-Json) -ContentType "application/json"
$result.result
$result.result.value
Использование скриптов на сервере
На сервере Zabbix мы можем создать два типа скриптов:
- Для получения данных через веб-интерфейс Zabbix. Они создаются в разделе 'Scripts';
- Для использования в качестве ключей. Файлы со скриптами добавляются в одну из папок Zabbix.
Выполняем скрипт в веб-интерфейсе Zabbix
На некоторых страницах Zabbix (например картах), если нажать на название хоста, может появится меню с выбором скриптов для запуска. Они выглядят примерно так:
Подобные скрипты можно создать в разделе 'Administration'-'Scripts':
Скрипты, которые будут запускаться на Linux, должны иметь Powershell (который не установлен по умолчанию). Кроме этого названия команд, в версиях 5.1. и 7, могут иметь один вид, но разные ключи. Такое же отличие есть в версиях Linux и Windows.
Так, например, мы проверим доступность хоста на Linux:
pwsh -Command "Test-Connection -TargetName '127.0.0.1' -TcpPort 80"
На Windows, если у вас установлен Powershell 7, эта команда сработает так же.
На версиях Powershell 5.1, что бы проверить порт, вам нужно использовать следующую команду (она не доступна на Linux):
powershell.exe -Command "Test-NetConnection -ComputerName '127.0.0.1' -Port 80"
Т.е. создавая скрипты в этом разделе вы должны понимать на каких ОС они будут запускаться.
Вы так же должны определится, где эти скрипты будут выполняться:
- на сервере;
- на хосту (агенте);
- на прокси сервере.
Для примера создадим скрипт, который будет проверять 80 порт выбранного хоста:
В Zabbix так же существуют системные переменные. Одна из таких переменных - '{HOST.CONN}' хранит адрес хоста. Запуская скрипт Zabbix автоматически заменяет '{HOST.CONN}' значением, которое указано у хоста. Таких переменных много. Кроме этого вы можете создавать их сами.
Так как пример выше запускается на сервере, вам нужно проверять работу скрипта только на одном хосту. Если бы вы выполняли этот скрипт на 'Zabbix agent' - это пришлось бы дополнительно обдумывать.
Такие скрипты можно упорядочить в дополнительные меню изменив название 'Проверка 80 порта' на 'Windows/Проверка 80 порта/'. Например:
В случае ошибок с выбором 'Zabbix Agent' - попробуйте включить настройку 'system.run', которая описана выше. В случае ошибок с выбором 'Zabbix Server' - попробуйте выдать повышенные права пользователю zabbix.
Скрипты в качестве ключей
Мы можем создать на сервере скрипт, который можно будет использовать в Item, Item Prototype и Discovery Host. Скрипт так же будет запускаться с сервера. Для этого существует отдельная директория, которую можно увидеть так:
cat /etc/zabbix/zabbix_server.conf | grep Extern
Эта директория может быть еще не создана. Так вы можете это исправить:
mkdir -p /etc/zabbix/externalscripts/
Внутри этой директории мы создаем файл со скриптом. В примере ниже скрипт называется 'site_status.ps1', который просто возвращает HTTP статус:
#!/usr/bin/pwsh
$data = Invoke-WebRequest -Uri 'https://fixmypc.ru'
$data.StatusCode
Далее мы можем использовать название скрипта в качестве ключа при работе с Item и другими типами. Например так:
Хороший пример, где это может пригодится - принтеры и картриджи. Принтер может не иметь каких либо интерфейсов кроме HTTP. Вы можете парсить данные с помощью Powershell и добавлять в Zabbix.
Пример, который я сделал для видео:
...
Подписывайтесь на наш Telegram канал
Теги: #powershell #zabbix