Всем привет! Меня зовут Григорий Ильдюков, я занимаюсь проектированием, развёртыванием и трансформацией инфраструктуры и информационных систем.В этой статье я бы хотел поделиться опытом по проектированию и развёртыванию системы коммуникации на базе Mattermost Server. Немного о том, для чего это было сделано, и почему был выбран именно Mattermost. Предпосылкой к внедрению именно self-hosted системы стала необходимость предоставления пользователям инструмента коммуникации, в полной мере контролируемого Компанией.  Mattermost уже был опробован для части пользователей и подходил по функциональности, но его конфигурация не отвечала нефункциональным требованиям, предъявляемым к продуктивным средам. Решено было произвести развёртывание заново, с учётом соответствующих требований. Также требовалось обеспечить интеграцию со службой каталогов для входа с учётными записями Active Directory и возможность использования мобильного приложения Mattermost. Кроме того, одним из ключевых требований было использование бесплатных редакций программного обеспечения. Рассмотрение возможности перехода на платные редакции решено было провести в будущем, по мере возникновения необходимости и роста востребованности решения среди пользователей. Как сказано на официальном сайте проекта — это open source, self-hosted альтернатива Slack и прочим системам коммуникации. На момент проектирования был представлен в платных редакциях E10 и E20, а также в бесплатной редакции Team Edition.  Стоимость лицензий платных редакций рассчитывается по количеству пользователей. Отличие бесплатной редакции от платной заключается, в частности, в отсутствии кластеризации и механизма интеграции со службой каталогов MS Active Directory. Об использовании бесплатного ПО и пойдёт речь далее. В общем случае архитектура Mattermost Server состоит из самого сервера Mattermost, реверсивного прокси Nginx и базы данных для хранения сообщений и настроек. Поддерживаются MySQL и PostgreSQL. По умолчанию Mattermost хранит файлы пользователей (вложения, пересылаемые скриншоты, изображения профилей) локально, в качестве альтернативы можно указать S3-совместимое хранилище. Есть веб, мобильные и десктопные клиенты.  Для отправки push-уведомлений на мобильные клиенты необходим Push Proxy Service, подробнее о нём ниже. Для расширения функциональности Mattermost Server возможна установка различных плагинов. В нашем случае была разработана следующая архитектура решения: в OpenShift развёртывается сам Mattermost Server, реверсивный прокси Nginx и Keycloak, Push Proxy Service развёртывается на отдельной ВМ в виде MPNS (Mattermost Push Notification Service), БД PostgreSQL и S3-совместимое файловое хранилище предоставляется как сервис внутри сети Компании.  Логи компонент передаются в ELK с помощью Filebeat. Решение о развёртывании MPNS на отдельной ВМ было принято по специфическим для Компании требованиям, в общем случае его вполне возможно было разместить в OpenShift. Архитектурная схема: Теперь подробнее о компонентах решения и причинах того, почему они представлены в такой конфигурации. OpenShift. Использовать его было решено для обеспечения высокой доступности компонент решения. Причина выбора именно такого пути — OpenShift представлен в технологическом стеке Компании и предоставляется как сервис внутренним подразделением. Mattermost Server. Как было сказано ранее, бесплатная редакция Team Edition не поддерживает кластеризацию: нельзя построить конфигурацию, при которой два и более серверов были бы одновременно задействованы в обслуживании пользователей. Причина этого ограничения в том, что серверы при параллельной работе не синхронизируют состояние чатов между собой и не могут оповестить пользователей о новых сообщениях с «параллельного» сервера.  Таким образом может сложиться ситуация, когда пользователи А и Б находятся в одном чате, но подключены к разным серверам, а значит не увидят новых сообщений друг друга, пока самостоятельно не обновят страницу чата.  Для обхода этого ограничения мы развернули два пода с Mattermost Server — основной и резервный, переключение между ними обеспечивается на уровне реверсивного прокси Nginx. Следовательно, пользователи всегда будут подключаться к основному экземпляру сервера и не будут испытывать описанной выше проблемы, а при его отказе будут перенаправлены на резервный. При подключении хранилища S3, если там используется самоподписанный сертификат, нужно разместить его в /etc/pki/ca-trust/source/anchors и выполнить: Или разрешить небезопасные исходящие соединения в конфигурационном файле Mattermost Server: Делать это допустимо только в тестовом окружении. Ещё одна особенность – устанавливаемые плагины размещаются только на локальной файловой системе. Поэтому необходимо добавлять плагины на этапе сборки образа. Здесь нужно оговориться, что одним из требований Компании был запрет на использование Persistent Volumes или NFS. Mattermost предусматривает возможность кастомизации веб-клиента, для этого необходимо заменить все файлы в /opt/mattermost/client на полученные в результате сборки нового веб-приложения. Например, для того, чтобы изменить текст на кнопке входа, нужно указать целевой текст в значении ключа login.gitlab в файле /mattermost-webapp/i18n/en.json и запустить сборку. Подробнее об этом можно почитать здесь.  Keycloak. Это open source решение для обеспечения идентификации и управления доступом. Как было сказано выше, редакция Team Edition не может напрямую интегрироваться с MS Active Directory. Для обхода этого ограничения можно использовать Keycloak, который будет выступать связующим звеном между Active Directory и Mattermost Server.  Keycloak при взаимодействии с Mattermost эмулирует аутентификацию средствами GitLab (поддерживаемую редакцией Team Edition), осуществляя при этом аутентификацию пользователей на основании данных об учетных записях из Active Directory.  Для реализации такой схемы на стороне Keycloak настраивается маппинг какого-либо атрибута учётных записей из Active Directory, имеющего уникальные численные значения, с атрибутом ID, передаваемым Keycloak в Mattermost при аутентификации пользователей. Описанная схема позволяет осуществлять вход в Mattermost с использованием учетных данных из Active Directory. Концептуальная схема интеграции с AD: Нужно отметить, что при использовании описанной выше схемы, идентификация и аутентификация пользователей осуществляется средствами Keycloak и Active Directory, а авторизация — средствами Mattermost. Это означает, что осуществлять назначение ролей пользователям на основании их членства в группах Active Directory нельзя, для этого нужно использовать платную редакцию Mattermost.  В нашем случае это не было препятствием, т.к. абсолютное большинство были рядовыми пользователями системы, а назначение нескольких администраторов можно было осуществить вручную через GUI Mattermost Server. Подробно на настройке я останавливаться не буду, отмечу лишь, что Keycloak требуется отдельная БД, в которой хранится настроенная конфигурация и пользователи. Подробнее о настройке можно почитать по ссылке. Также следует обратить внимание вот на что – если разрешить пользователям использование токенов для доступа к Mattermost, то нужно предусмотреть механизм блокировки токенов, принадлежащих заблокированным на уровне Active Directory учётным записям. Иначе заблокированные пользователи смогут получить доступ к Mattermost с помощью ранее созданного токена. Реверсивный прокси Nginx. Конфигурация Nginx создавалась на основе рекомендованной, но в нашем случае приобрела некоторые особенности. Во-первых, для обеспечения переключения между основным и резервным подами Mattermost используется директива backup: Во-вторых для обеспечения входа через Keycloak был добавлен следующий location: Для отправки логов в ELK в поды добавлялся контейнер с Filebeat. Push Proxy Service. Этот компонент служит для отправки push-уведомлений на мобильные клиенты Mattermost т.е. выступает в качестве прокси между Mattermost Server с одной стороны и Apple Push Notification Services и Firebase Cloud Messaging Service с другой.  Есть несколько вариантов реализации этой функции — MPNS, HPNS и TPNS. HPNS — Hosted Push Notification Service, предоставляется как высокодоступный сервис обладателям платных редакций. TPNS — Test Push Notification Service, тоже, что и HPNS, но без гарантий работоспособности, можно использовать с Team Edition.  И, наконец, MPNS — реализация Push Proxy для размещения on-premise. Если планируется использовать кастомизированное мобильное приложение Mattermost, как было в нашем случае, то MPNS — это единственный возможный вариант. Все варианты реализации позволяют регулировать содержимое push-уведомлений: можно посылать полный текст сообщения или лишь уведомлять о новом сообщении с указанием отправителя или без такового.  В платной редакции E20 предусмотрен механизм более безопасной отправки содержимого сообщений — с фактической отправкой через push только id сообщения, получив который мобильный клиент запрашивает содержимое напрямую с сервера Mattermost. Подробнее об этом здесь. Ещё одной особенностью MPNS является отсутствие поддержки SSL для соединений между Mattermost и MPNS. Если требуется устанавливать защищённое соединение между ними, то можно установить Nginx перед MPNS. Также MPNS не проверяет отправителя сообщения, т.е. отправлять push-уведомления можно, например, с помощью curl. Следует помнить об этом и ограничить возможность подключения к MPNS только со стороны Mattermost Server на уровне Nginx и / или файервола. Подробнее о Push Proxy можно почитать в документации. Поддерживаются различные механизмы интеграции, самым простым из которых являются входящие веб-хуки. С помощью этого механизма можно настроить автоматическую отправку уведомлений из внешних систем в определённый канал Mattermost.  Для создания входящего веб-хука они должны быть разрешены на уровне сервера, и пользователь должен обладать полномочиями роли Team Admin или System Admin. Также возможно разрешить создание интеграций для рядовых пользователей, для это необходимо указать в конфигурационном файле в "ServiceSettings": Все пользователи с указанными полномочиями видят все настроенные веб-хуки в рамках одной Team. Сообщение, сгенерированное внешней системой, будет отображено в чате от имени того пользователя, который создал веб-хук, но с пометкой «BOT». В качестве примера можно привести интеграции с Bitbucket и TeamCity. Таким образом, нам удалось успешно реализовать поставленную задачу, построив систему коммуникации, отвечающую всем поставленным требованиям с использованием только бесплатных редакций ПО.  P.S. В статье описан опыт построения системы в первом полугодии 2021 года. За это время ситуация в части потенциально применимых решений могла существенно измениться. Тем не менее, в статье приведён достаточно актуальный пример решения подобных задач.