Найти в Дзене
Записки сисадмина

Python. Zabbix API. Управление пользователями

Мне вот всегда интересно было, что может побудить человека заняться автоматизацией сильнее, чем собственная лень. Пока что я не нашел ответа, поэтому и начинаю очередной цикл статей по теме, которая может спасти вас от дней, недель, а то и нескольких месяцев рутинной работы. Если ваша компания пока что небольшая, и у вас на мониторнинге 10-20 серверов, вряд ли это будет вам полезно. Но как только вы столкнетесь с zabbix сервером, к которому подключено несколько сотен клиентов, эти статьи вам очень сильно помогут (я на это надеюсь). Особенно, если у вас несколько независимых серверов, которые нужно объединить. Сразу определим вводные данные: Поскольку я привожу примеры со своего локального тестового сервера, у меня нет необходимости прятать пароли и токены. Об этом вам нужно будет подумать самим. У меня установлен zabbix сервер версии 7.0, и код будет написан именно под данную версию. Но тестировал весь функционал я на версиях 4.0, 6.4, 7.0 В старых версиях некоторые параметры, передава
Оглавление

Мне вот всегда интересно было, что может побудить человека заняться автоматизацией сильнее, чем собственная лень. Пока что я не нашел ответа, поэтому и начинаю очередной цикл статей по теме, которая может спасти вас от дней, недель, а то и нескольких месяцев рутинной работы.

Если ваша компания пока что небольшая, и у вас на мониторнинге 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 Токены":

Создадим новый токен:

-2

Важно: токен привязывается напрямую к пользователю. Права пользователя распространятся и на токен. Если при обращении к API у вас будет недоступен какой-либо функционал, проверьте настройки пользователя токена, с которым вы обращаетесь.

В данном примере нам из всей библиотеки достаточно импортировать только модуль ZabbixAPI.

Создаем подключение к нашему серверу:

-3

При успешном подключении мы должны получить объект авторизации на сервере:

<zabbix_utils.api.ZabbixAPI object at 0x7a446ec62d10>

Теперь поговорим о нюансах:

Библиотека рассчитана на версию zabbix сервера 5.0+, но это никак не мешает управлять сервером более старой версии (проверено на 4.0 LTS). Для этого в объект подключения добавляем skip_version_check=True. Также, в старых версиях нет функционала API токенов, поэтому авторизация будет через пользователя и пароль:

-4
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

Напишем функцию создания пользователя:

-5
username - Имя пользователя
passwd - Его пароль
role - ID Роли пользователя
group - ID группы пользователей

Можно сразу добавить пользователю несколько групп. Тогда в наш передаваемый json мы должны добавить:

'usrgrps': [{"usrgrpid": "7"}, {"usrgrpid": "8"}, {"usrgrpid": "9"}]

Также, можно сразу добавить пользователю способы оповещений, но в данный момент мы это делать не будем.

Запускаем скрипт и получаем в ответ:

{'userids': ['5']}

Проверяем, что пользователь создался:

-6

Также, проверяем, что ему назначилась роль:

-7

user.delete

Удаление пользователей происходит проще: по списку их ID. Поскольку мы только что создали пользователя с ID=5, напишем функцию его удаления:

-8

Важно: ID пользователей нужно передавать списком, даже если вы хотите удалить всего одного.

Выполняем скрипт и получаем вывод:

{'userids': ['5']}

Проверяем, что пользователь удален:

-9

user.get

Запрос информации о пользователе.

В функцию достаточно передать просто параметр userids, чтобы API выдало нам информацию о пользователе. Однако, вывод будет не полным. Для решения этой проблемы добавляем флаг output='extend'.

-10

Вывод будет примерно таким:

[{'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'}}]

Финальная версия будет такая:

-11

Если вы хотите получить информацию о всех пользователях, передайте в userid=None.

user.update

А вот это самый опасный метод. Советую проверять его на тестовой среде, иначе рискуете все поломать.

Объясняю почему:

Я заранее заново создал пользователя test_user:

-12

Создадим функцию добавления группы пользователю:

-13

Выполняем, получаем в ответ json об успехе и смотрим в веб интерфейс:

-14

Пользователю не добавилась группа, а переписались полностью все настройки групп.

Правильно будет запрашивать внутри функции текущую информацию о настройках пользователя.

-15
  • Внутри функции мы вызываем ранее написанную get_user(), из которой получаем словарь с информацией о пользователе.
  • Создаем список со словарями, в который в цикле добавляем все текущие группы пользователя.
  • После этого мы так же добавляем новую группу и передаем всю собранную информацию уже в метод user.update

Проверяем:

-16

Весь код из статьи выложил здесь