Настройка Microsoft Teams
Плагин Microsoft Teams создаёт онлайн-встречу Teams, которая служит конференцией инцидента. Он аутентифицируется в Microsoft Graph по OAuth2 client-credentials flow и создаёт встречу от имени назначенного пользователя. Встречи Teams истекают через 60 дней после времени начала или окончания (срок продлевается ещё на 60 дней, если встречу обновили или активировали), так что ссылка для подключения остаётся рабочей всё время жизни инцидента независимо от настроенной длительности.
Настройка Azure
Плагин действует как приложение, а не как вошедший пользователь, поэтому ему нужна регистрация приложения с разрешением типа application и политика Teams, в которой назван пользователь, для которого создаются встречи. Нужны обе половины: действительный токен без политики возвращает 403.
1. Зарегистрируйте приложение
В центре администрирования Microsoft Entra откройте App registrations → New registration. Запишите Application (client) ID и Directory (tenant) ID.
2. Выдайте разрешение Graph
В разделе API permissions добавьте Microsoft Graph → Application permissions → OnlineMeetings.ReadWrite.All, затем нажмите Grant admin consent.
Это должно быть разрешение типа application. Делегированные разрешения относятся к вошедшему пользователю, и этот плагин их не использует.
3. Создайте секрет клиента
В разделе Certificates & secrets → New client secret скопируйте значение секрета (не его ID). Оно показывается только один раз. Секреты клиента истекают — поставьте напоминание: истёкший секрет проявляется как invalid_client в хронологии инцидента.
4. Разрешите приложению создавать встречи для пользователя
Этот шаг легко пропустить. Выдайте приложению доступ к пользователю, в чьём календаре создаются встречи:
Import-Module MicrosoftTeams
Connect-MicrosoftTeams
New-CsApplicationAccessPolicy -Identity Dispatch-Conference `
-AppIds "<application-client-id>" -Description "Dispatch conference plugin"
Grant-CsApplicationAccessPolicy -PolicyName Dispatch-Conference `
-Identity "<user-object-id>"
Назначение политики может вступать в силу до 30 минут. См. Разрешение приложениям доступа к онлайн-встречам от имени пользователя.
Конфигурация Dispatch
Плагин Microsoft Teams настраивается в веб-интерфейсе Dispatch: «Настройки» -> «Проект» -> «Плагины». Добавьте плагин кнопкой NEW и затем отредактируйте его конфигурацию, нажав на три вертикальные точки.
URL центра авторизации (MS team Authority URL)
https://login.microsoftonline.com/<directory-tenant-id>. Укажите конкретный тенант:commonиorganizationsдля client-credentials flow не поддерживаются.
Идентификатор клиента (client id)
Application (client) ID из шага 1.
Секрет клиента Azure (Azure Client Secret)
Значение секрета клиента из шага 3.
Идентификатор пользователя (User id)
Object ID пользователя, от имени которого приложение создаёт встречи, — не его адрес эл. почты. Это должен быть тот же пользователь, что указан в политике доступа приложения на шаге 4.
Разрешить автоматическую запись (Allow Auto Recording)
Включите, если хотите записывать встречи по умолчанию. По умолчанию выключено.
Длительность встречи по умолчанию, в минутах (Default Meeting Duration (Minutes))
Длительность конференций по умолчанию в минутах. По умолчанию 1440 минут (1 день). К встречам Teams можно подключаться и после запланированного окончания, так что этот параметр в основном определяет, когда встреча истечёт, а не обрывает конференцию.
Требовать код доступа к встрече (Require a Meeting Passcode)
Требовать код доступа при подключении по идентификатору встречи. По умолчанию включено.
Код доступа действует только при подключении по идентификатору встречи. Ссылка для подключения несёт собственный контекст аутентификации встречи, поэтому у тех, кто переходит по ссылке из Slack, код никогда не запрашивается: включение этого параметра не усложняет обычный путь. Для звонков по телефону используется отдельный идентификатор конференции (
audioConferencing.conferenceId), на который этот параметр не влияет.Поскольку код доступа бесполезен без идентификатора встречи, с которым он связан, Dispatch публикует их вместе: описание конференции выглядит как
Password: aB3dEf7h (meeting ID 123 456 789).
Диагностика
Сбои записываются в хронологию инцидента вместе с причиной, которую вернул Graph.
| Симптом | Причина |
|---|---|
invalid_client | Неверный или истёкший секрет клиента. |
403 при действительном токене | Для настроенного пользователя нет политики доступа приложения, либо она ещё не применилась. |
404 при создании | Идентификатор пользователя (User id) — не object ID, или такого пользователя нет в тенанте. |
429 | Graph ограничивает приложение. Сообщение содержит значение Retry-After как есть (Graph присылает либо число секунд, либо HTTP-дату). Dispatch не повторяет запрос: повтор на записывающей конечной точке рискует создать вторую конференцию для одного инцидента. |
Ограничения
Microsoft документирует лимит в 2000 встреч на пользователя в месяц для сведений о встречах. Поскольку Dispatch создаёт все конференции под единственным пользователем, настроенным выше, именно в этот потолок плагин упрётся первым. Microsoft не публикует лимит запросов в секунду для /onlineMeetings в таблице ограничений по сервисам; если приложение ограничено, Graph отвечает 429 с Retry-After, и Dispatch выводит и то и другое в хронологию инцидента.
Примечания
add_participantиremove_participantдержат список участников встречи в соответствии с участниками инцидента. Это метаданные о составе, а не контроль доступа: ссылка для подключения работает для любого, у кого она есть, так что добавление не даёт ничего сверх того, что уже даёт опубликованная ссылка, а удаление не выгоняет участника из идущей встречи и не отзывает ссылку. Участники добавляются с рольюattendee: Microsoft не позволяет назначатьpresenterилиcoorganizerучётным записям, которые Entra не может разрешить, а среди реагирующих могут быть внешние люди.- При каждом обновлении Graph заменяет весь список участников, поэтому Dispatch перед каждым изменением читает встречу и отправляет существующих участников без изменений. Сбой записывается в хронологию инцидента и не прерывает добавление или удаление участника во всех остальных местах.
- Допуск из лобби и права докладчика — отдельная тема, которой этот плагин не управляет.
- Не проверено на живом тенанте. Участники идентифицируются только по user principal name; Graph описывает более полный объект
identityкак необязательный, а чтобы его разрешить, помимо перечисленных выше разрешений понадобился быUser.Read.All. Есть также сообщения, что Graph отвечает200на обновление списка участников с разрешениями приложения, не применяя его. Поскольку сбой состава никогда не прерывает инцидент, установка, где это молча ничего не делает, выглядит так же, как та, где всё работает. Прежде чем полагаться на точность состава, прогоните на своём тенанте живой набор тестов, включаемый вручную (tests/plugins/dispatch_microsoft_teams/test_teams_live.pyс заданнойDISPATCH_MSTEAMS_TEST_ATTENDEE_UPN). - Сейчас в Dispatch ничто не вызывает
deleteдля конференции; метод реализован для единообразия интерфейса. - Встреча создаётся с начальным составом участников: реагирующие, определённые для инцидента, минус те, кто выключил у себя в настройках «Автоматически подключать меня к конференциям инцидентов» (Add me automatically to incident bridges). Тот же список, та же роль
attendeeи те же оговорки, что и дляadd_participantвыше, — только состав задаётся одним запросом, а не добавляется потом, поэтому состав, который Graph отвергнет, провалит создание, а не оставит встречу, о которой Dispatch ничего не знает. Инцидент без таких реагирующих получает встречу без участников, и это не ошибка. descriptionплагин принимает, но не использует: уonlineMeetingнет поля повестки.
Обновление
До исправлений из Jamyn/dispatch#81 этот плагин вообще не мог аутентифицироваться: он передавал строку там, где MSAL требует список скоупов, поэтому каждая попытка падала, не доходя до Graph, и ошибка проглатывалась. Значит, ни одна существующая установка конференций не создавала, и прежнего рабочего поведения, которое нужно сохранять, нет. Тем не менее две вещи отличаются от того, что старый код пытался сделать:
- Темой встречи теперь служит название инцидента (а если его нет —
Situation Room for <incident name>), как в плагине Zoom. Раньше это было кодовое имя инцидента. Названия инцидентов описательнее кодовых имён, а тема видна всем в тенанте, у кого есть доступ к календарю настроенного пользователя. - Код доступа запрашивается по умолчанию. См. Требовать код доступа к встрече (Require a Meeting Passcode) выше; выключите параметр, чтобы вернуть прежний замысел.