Выбирая замену, используемой у нас системы обмена сообщениями, наткнулся на описание 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-ти частей:


  1. Получение запроса от mattermost
  2. Инициализация сессии в glpi
  3. Получение данных из запроса
  4. Отправка данных в glpi
  5. Закрытие сессии

Перед тем как приступить к описанию кода срипта, проведём подготовительную работу как в mattermost так и в glpi.


GLPI


  1. Cоздадим пользователя helpdesk, от имени которого, будут создаваться запросы, и зайдя в настройки этого пользователя сгенерируем токены:
    image
    Тот, что обведен красным, будет user_token.
  2. В настройках системы необходимо добавить клиента для взаимодействия с API. Для этого идём в "Настройки"->"Общие"->"API" и нажав кнопку "Добавить клиента", добавляем запись и генерируем токен (app_token)

image


  1. Для идентификации источника запросов в системе, добавим запись в справочник "Источники запросов" и зайдя в, только что, добавленную запись запомним его id (обведено красным)
    image

На этом настройка АПИ в GLPI закончена.


Mattermost


В меню клиента Mattermost идём в "Inegration"->"Outgoing Webhooks" жмем "Add" и добавлем запись. На скрине я подчеркнул значимые поля. Тут следует сделать отступление: в mattermost "спусковым крючком" для запуска процедуры отправки запроса служит слово или фраза, которая, будучи указанной в начале сообщения, собственно, и запускает процесс. В нащем случае слово-тригер — "112" (тут прямая ассоциация с МЧС).


image


Имя пользователя по умолчанию и ссылку на аватарку можно добавить (а можно не добавлять), так как эти параметры будут переданы в запросе. Но для того, чтобы 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:


image


Идём в GLPI "Поддержка"->"Заявки" и в списке должно появится новое сообщение:


image


Ткнув на заголовок сообщения, откроется более подробная информация (красным обведены поля, значения которых передаются в скрипте)


image


На этом настройку отправки сообщений в GLPI из Mattermost, можно считать завершенной. Поработав немного над кодом, ничто не помешает реализовать изменение типа запроса (инцидент или заявка).

Комментарии (6)


  1. Artemis86
    04.03.2019 07:47

    Вопрос ко всем, в том числе и к автору. Как настроена авторизация? Кто делал GooglAuth, OAuth, Atlassian-crowd-auth? Как успехи?


    1. svk28 Автор
      04.03.2019 07:49

      Авторизация путем добавления пользователяей с консоли. Т.е. ничего постороннего не используется. Не совсем удобно, но пока так.


      1. Artemis86
        04.03.2019 12:53

        Печально:( ПО создано для работы в корпоративной среде, без интеграции с существующей системой авторизации использовать затруднительно. Slack без проблем работает с GAuth.


        1. citius
          04.03.2019 13:35

          Печально что у автора этого нет? Так то оно работает.
          У нас интеграция с внутренним гитлабом через OAuth, гитлаб тянет пользователей из лдапа.


        1. svk28 Автор
          04.03.2019 14:20

          Оно есть за отдельные деньги, открыт и бесплатен только базовый набор функций. Куда лдап не входит


          1. Vanger
            04.03.2019 20:24
            +1

            но это странное, учитывая то, что у конкурентов LDAP есть из коробк.