Мне вот всегда интересно было, что может побудить человека заняться автоматизацией сильнее, чем собственная лень. Пока что я не нашел ответа, поэтому и начинаю очередной цикл статей по теме, которая может спасти вас от дней, недель, а то и нескольких месяцев рутинной работы.
Если ваша компания пока что небольшая, и у вас на мониторнинге 10-20 серверов, вряд ли это будет вам полезно. Но как только вы столкнетесь с zabbix сервером, к которому подключено несколько сотен клиентов, эти статьи вам очень сильно помогут (я на это надеюсь). Особенно, если у вас несколько независимых серверов, которые нужно объединить.
Сразу определим вводные данные:
Поскольку я привожу примеры со своего локального тестового сервера, у меня нет необходимости прятать пароли и токены. Об этом вам нужно будет подумать самим.
У меня установлен zabbix сервер версии 7.0, и код будет написан именно под данную версию. Но тестировал весь функционал я на версиях 4.0, 6.4, 7.0
В старых версиях некоторые параметры, передаваемые в функции get/create/update могут немного отличаться.
Код писать мы будем как обычно на python (советую версии выше 3.8, самое оптимальное - 3.10)
Настраиваем среду
Установим официальную библиотеку:
pip install zabbix_utils
Для доступа наших скриптов зайдем в веб интерфейсе zabbix сервера в "Пользователи" - "API Токены":
Создадим новый токен:
Важно: токен привязывается напрямую к пользователю. Права пользователя распространятся и на токен. Если при обращении к API у вас будет недоступен какой-либо функционал, проверьте настройки пользователя токена, с которым вы обращаетесь.
В данном примере нам из всей библиотеки достаточно импортировать только модуль ZabbixAPI.
Создаем подключение к нашему серверу:
При успешном подключении мы должны получить объект авторизации на сервере:
<zabbix_utils.api.ZabbixAPI object at 0x7a446ec62d10>
Теперь поговорим о нюансах:
Библиотека рассчитана на версию zabbix сервера 5.0+, но это никак не мешает управлять сервером более старой версии (проверено на 4.0 LTS). Для этого в объект подключения добавляем skip_version_check=True. Также, в старых версиях нет функционала API токенов, поэтому авторизация будет через пользователя и пароль:
from zabbix_utils import ZabbixAPI
zabbix_api = ZabbixAPI(url='zabbix url', skip_version_check=True)
zabbix_api.login(user='zabbix user', password='user password')
Итак, рабочую среду мы подготовили, начинаем разбираться с самыми нужными методами:
Пользователи (Users)
Все доступные методы можно посмотреть здесь.
Нас интересуют:
user.create - создание новых пользователей
user.delete - удаление пользователей
user.get - получение пользователей
user.update - обновление пользователей
user.create
Напишем функцию создания пользователя:
username - Имя пользователя
passwd - Его пароль
role - ID Роли пользователя
group - ID группы пользователей
Можно сразу добавить пользователю несколько групп. Тогда в наш передаваемый json мы должны добавить:
'usrgrps': [{"usrgrpid": "7"}, {"usrgrpid": "8"}, {"usrgrpid": "9"}]
Также, можно сразу добавить пользователю способы оповещений, но в данный момент мы это делать не будем.
Запускаем скрипт и получаем в ответ:
{'userids': ['5']}
Проверяем, что пользователь создался:
Также, проверяем, что ему назначилась роль:
user.delete
Удаление пользователей происходит проще: по списку их ID. Поскольку мы только что создали пользователя с ID=5, напишем функцию его удаления:
Важно: ID пользователей нужно передавать списком, даже если вы хотите удалить всего одного.
Выполняем скрипт и получаем вывод:
{'userids': ['5']}
Проверяем, что пользователь удален:
user.get
Запрос информации о пользователе.
В функцию достаточно передать просто параметр userids, чтобы API выдало нам информацию о пользователе. Однако, вывод будет не полным. Для решения этой проблемы добавляем флаг output='extend'.
Вывод будет примерно таким:
[{'userid': '7', 'username': 'test_user', 'name': '', 'surname': '', 'url': '', 'autologin': '0', 'autologout': '15m', 'lang': 'default', 'refresh': '30s', 'theme': 'default', 'attempt_failed': '0', 'attempt_ip': '', 'attempt_clock': '0', 'rows_per_page': '50', 'timezone': 'default', 'roleid': '2', 'userdirectoryid': '0', 'ts_provisioned': '0', 'provisioned': '0'}]
Но хотелось бы также получить информацию и о группах пользователя. для этого добавляем selectUsrgrps="extend", а также selectRole="extend" для информации о ролях пользователя:
[{'userid': '7', 'username': 'test_user', 'name': '', 'surname': '', 'url': '', 'autologin': '0', 'autologout': '15m', 'lang': 'default', 'refresh': '30s', 'theme': 'default', 'attempt_failed': '0', 'attempt_ip': '', 'attempt_clock': '0', 'rows_per_page': '50', 'timezone': 'default', 'roleid': '2', 'userdirectoryid': '0', 'ts_provisioned': '0', 'provisioned': '0', 'usrgrps': [{'usrgrpid': '13', 'name': 'Internal', 'gui_access': '1', 'users_status': '0', 'debug_mode': '0', 'userdirectoryid': '0', 'mfa_status': '0', 'mfaid': '0'}], 'role': {'roleid': '2', 'name': 'Admin role', 'type': '2', 'readonly': '0'}}]
Финальная версия будет такая:
Если вы хотите получить информацию о всех пользователях, передайте в userid=None.
user.update
А вот это самый опасный метод. Советую проверять его на тестовой среде, иначе рискуете все поломать.
Объясняю почему:
Я заранее заново создал пользователя test_user:
Создадим функцию добавления группы пользователю:
Выполняем, получаем в ответ json об успехе и смотрим в веб интерфейс:
Пользователю не добавилась группа, а переписались полностью все настройки групп.
Правильно будет запрашивать внутри функции текущую информацию о настройках пользователя.
- Внутри функции мы вызываем ранее написанную get_user(), из которой получаем словарь с информацией о пользователе.
- Создаем список со словарями, в который в цикле добавляем все текущие группы пользователя.
- После этого мы так же добавляем новую группу и передаем всю собранную информацию уже в метод user.update
Проверяем: