Перейти к основному содержимому

Настройка 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, или такого пользователя нет в тенанте.
429Graph ограничивает приложение. Сообщение содержит значение 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) выше; выключите параметр, чтобы вернуть прежний замысел.