Выбирая замену, используемой у нас системы обмена сообщениями, наткнулся на описание Mattermost, и решил попробовать. Одним из плюсов, описываемой системы, является простая интеграция со сторонними сервисами, так называемые "хуки" (outgoing и incoming hooks). Вот про настройку взаимодействия через хуки с внешними системами и будет данная статья (в нашем конкретном случае это zabbix и glpi).
Часть первая. Интеграция с GLPI
Так как мы, в своей работе, для учета оборудования, программного обеспечения, соединений, регистрации обращений в техподдержку используем GLPI, то логично было-бы организовать возможность для пользователей отправлять заявки в ТП из mattermost.
API
Для интеграции с внешними сервисами у GLPI есть http rest api. Документация по нему доступна в установленной системе по ссылке http://glpi/apirest.php/#glossary (где "glpi" адрес вашего сервера).
Слегка подумав над задачей, было решено алгоритм обмена реализовать на php, в пользу данного решения говорит то факт, что php уже установлен в системе и скрипт был органично вписан в glpi и доступен по адресу http://glpi/mm.php. Получился, своего рода, "прокси", который принимает запрос от mattermost, преобразует в нужный формат и отправляет GLPI. Все http-запросы передаются в JSON-формате.
Процедура работы состоит из 5-ти частей:
- Получение запроса от mattermost
- Инициализация сессии в glpi
- Получение данных из запроса
- Отправка данных в glpi
- Закрытие сессии
Перед тем как приступить к описанию кода срипта, проведём подготовительную работу как в mattermost так и в glpi.
GLPI
- Cоздадим пользователя helpdesk, от имени которого, будут создаваться запросы, и зайдя в настройки этого пользователя сгенерируем токены:
Тот, что обведен красным, будет user_token. - В настройках системы необходимо добавить клиента для взаимодействия с API. Для этого идём в "Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)
- Для идентификации источника запросов в системе, добавим запись в справочник "Источники запросов" и зайдя в, только что, добавленную запись запомним его id (обведено красным)
На этом настройка АПИ в GLPI закончена.
Mattermost
В меню клиента Mattermost идём в "Inegration"->"Outgoing Webhooks" жмем "Add" и добавлем запись. На скрине я подчеркнул значимые поля. Тут следует сделать отступление: в mattermost "спусковым крючком" для запуска процедуры отправки запроса служит слово или фраза, которая, будучи указанной в начале сообщения, собственно, и запускает процесс. В нащем случае слово-тригер — "112" (тут прямая ассоциация с МЧС).
Имя пользователя по умолчанию и ссылку на аватарку можно добавить (а можно не добавлять), так как эти параметры будут переданы в запросе. Но для того, чтобы mattermost смог обрабатывать данные параметры, в настройках сервера надо поменять пару опций в файле /opt/mattermost/config/config.json
"EnablePostUsernameOverride": true,
"EnablePostIconOverride": true,
На этом настройка окончена. Настало время перейти к написанию кода. Скрипт скопирован в корневой каталог с файлами glpi, в моём случае это /var/www/html/glpi/mm.php
<?php
# GLPI токены сгенерированные в настройках
$app_token = '7uizyyildM71x84j1UxeABXTuCHdPoLRW45Tx2wG';
$user_app_token ='dZdCqc10Xhb1TxCT4OsXp8qqDSEqILASf2wZot0w';
# Тип источника запроса (значение из справочника, которое запомнили чуть раньше)
$requesttypes_id = '7';
# Код типа запроса GLPI (1 - Инцидент, 2 - Запрос)
$type = '1';
# Принимает запрос и декодируем данные
$postData = file_get_contents('php://input');
$data = json_decode($postData, true);
# Разбор json от MatterMost. Если эти данные нужны соответствующую строку
# можно раскоментировать и использовать перменную ниже по коду
#$message_text = $data["text"];
#$user_name = $data["user_name"];
#$user_id = $data["user_id"];
#$channel_name = $data["channel_name"];
#$channel_id = $data["channel_id"];
#$team_domain = $data["team_domain"];
#$team_id = $data["team_id"];
#$post_id = $data["post_id"];
# обрезаем "112" от сообщения, точнее обрезаем первые 4 символа.
$message_text = substr($data["text"],4);
# Ответ на POST запрос, который будет выведен пользователю в mattermost
#HTTP/1.1 200 OK
header('Content-Type: application/json');
$reply = array(
'response_type' => 'comment',
'text'=> 'Ваш запрос передан в службу технической поддержки'
);
echo json_encode($reply);
# Инициируем пользовательскую сессию в glpi
# тут нам и понадобятся ранее сгенерированные токены
# данный запрос вернёт идентификатор сессии для дальнейшей работы
if( $curl = curl_init() ) {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: user_token '.$user_app_token, 'App-Token: '.$app_token));
curl_setopt($curl, CURLOPT_URL, 'http://glpi/apirest.php/initSession');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($curl);
$session = json_decode($out, true);
$session_token = $session["session_token"];
#echo $session_token;
curl_close($curl);
}
# подготовим текст для запроса создания заявки
$json = array(
'input'=> array(
'name'=>'Заявка от '.$data["user_name"],
'requesttypes_id'=>$requesttypes_id,
'content'=>$message_text,
'type'=>$type
)
);
# Отправим запрос
if( $curl = curl_init() ) {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'App-Token: '.$app_token, 'Session-token: '.$session_token));
curl_setopt($curl, CURLOPT_URL, 'http://glpi/apirest.php/Ticket');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json));
$out = curl_exec($curl);
curl_close($curl);
}
# Закроем сессию
if( $curl = curl_init() ) {
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'App-Token: '.$app_token, 'Session-token: '.$session_token));
curl_setopt($curl, CURLOPT_URL, 'http://glpi/apirest.php/killSession');
curl_setopt($curl, CURLOPT_POST, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($curl);
curl_close($curl);
}
?>
Результатом работы данного скрипта будет добавленный запрос в системе регистрации инцидентов в GLPI. В картинках это выглядит следующим образом:
Пишем сообщение в mattermost:
Идём в GLPI "Поддержка"->"Заявки" и в списке должно появится новое сообщение:
Ткнув на заголовок сообщения, откроется более подробная информация (красным обведены поля, значения которых передаются в скрипте)
На этом настройку отправки сообщений в GLPI из Mattermost, можно считать завершенной. Поработав немного над кодом, ничто не помешает реализовать изменение типа запроса (инцидент или заявка).