Регистрация приложения Microsoft Graph
Конвейер обработки Teams-встреч читает транскрипты, записи и связанные артефакты из Microsoft Graph с использованием app-only (daemon) аутентификации — без входа пользователя, без интерактивного согласия на каждую встречу. Для этого нужна регистрация Azure AD приложения с разрешениями уровня приложения, на которые дал согласие администратор.
Этот гайд охватывает:
- Создание регистрации приложения
- Создание секрета клиента
- Предоставление разрешений Graph API, которые нужны конвейеру
- Административное согласие на эти разрешения
- (Необязательно) Ограничение приложения конкретными пользователями через Application Access Policy
Для завершения вам понадобятся права администратора тенанта (или администратор, который даст согласие за вас). Сохраните значения, которые собираете — в конце они идут в ~/.hermes/.env.
Требования
- Тенант Microsoft 365 с лицензиями Teams Premium или Teams, генерирующими транскрипты и записи встреч
- Административный доступ к Azure Portal на entra.microsoft.com
- Публично доступный HTTPS-эндпоинт для уведомлений об изменениях Graph (настраивается позже, на шаге webhook listener)
Шаг 1: Создание регистрации приложения
- Войдите на entra.microsoft.com как администратор тенанта.
- Перейдите в Identity → Applications → App registrations.
- Нажмите New registration.
- Заполните:
- Name:
Hermes Teams Meeting Pipeline(или любое имя, которое вы узнаете). - Supported account types: Accounts in this organizational directory only (Single tenant).
- Redirect URI: оставьте пустым — для app-only аутентификации не нужен.
- Name:
- Нажмите Register.
Вы попадёте на страницу обзора приложения. Скопируйте два значения:
- Application (client) ID →
MSGRAPH_CLIENT_ID - Directory (tenant) ID →
MSGRAPH_TENANT_ID
Шаг 2: Создание секрета клиента
- В левой навигации откройте Certificates & secrets.
- Нажмите New client secret.
- Description:
hermes-graph-secret. Expires: выберите значение, соответствующее вашей политике ротации (обычно 6–24 месяца). - Нажмите Add.
- Немедленно скопируйте значение в столбце Value — оно показывается только один раз. Это и есть
MSGRAPH_CLIENT_SECRET.
Столбец Secret ID — не секрет. Нужен столбец Value.
Шаг 3: Предоставление разрешений Graph API
Конвейер использует минимально необходимый набор разрешений уровня приложения. Добавляйте только то, что нужно: каждое разрешение расширяет доступ приложения ко всему тенанту.
- В левой навигации откройте API permissions.
- Нажмите Add a permission → Microsoft Graph → Application permissions.
- Добавьте разрешения из таблицы ниже, соответствующие тому, что должен делать конвейер.
- После добавления нажмите Grant admin consent for
<ваш тенант>. Столбец Status должен смениться на зелёную галочку для каждого разрешения.
Необходимо для резюме на основе транскрипта
| Разрешение | Что позволяет приложению |
|---|---|
OnlineMeetings.Read.All | Читать метаданные Teams онлайн-встреч (тема, участники, ссылка на подключение). |
OnlineMeetingTranscript.Read.All | Читать транскрипты встреч, созданные Teams. |
Необходимо для резервного варианта через запись (когда транскрипт недоступен)
| Разрешение | Что позволяет приложению |
|---|---|
OnlineMeetingRecording.Read.All | Скачивать записи Teams-встреч для офлайн-транскрибации. |
CallRecords.Read.All | Разрешать встречи из записей звонков, когда известна только ссылка на подключение. |
Необходимо для доставки резюме (только режим Graph)
Если platforms.teams.extra.delivery_mode равно graph, конвейер публикует резюме в Teams-канал или чат через Graph API. Пропустите, если используете режим доставки incoming_webhook.
| Разрешение | Что позволяет приложению |
|---|---|
ChannelMessage.Send | Публиковать сообщения в Teams-каналы от имени приложения. |
Chat.ReadWrite.All | Публиковать сообщения в личные и групповые чаты (только если chat_id задан как цель доставки). |
Не рекомендуется
OnlineMeetings.ReadWrite.All/Chat.ReadWriteбез.All— шире, чем нужно конвейеру.- Делегированные разрешения — конвейер использует app-only (client-credentials) поток; делегированные разрешения не работают без входа пользователя.
Шаг 4: (Рекомендуется) Ограничение приложения через Application Access Policy
По умолчанию разрешения уровня приложения вроде OnlineMeetings.Read.All дают доступ ко всем встречам в тенанте. Для партнёрских демо и dev-тенантов это нормально; в продакшене почти наверняка нужно ограничить, чьи встречи может читать приложение.
Именно для этого Microsoft предоставляет Application Access Policies для Teams. Политика управляется только через PowerShell — интерфейса в Portal нет.
Из PowerShell администратора с установленным и подключённым модулем MicrosoftTeams (Connect-MicrosoftTeams):
# Создаём политику для приложения Hermes
New-CsApplicationAccessPolicy `
-Identity "Hermes-Meeting-Pipeline-Policy" `
-AppIds "<MSGRAPH_CLIENT_ID>" `
-Description "Restrict Hermes meeting pipeline to allow-listed users"
# Выдаём политику конкретным пользователям, чьи встречи может читать конвейер
Grant-CsApplicationAccessPolicy `
-PolicyName "Hermes-Meeting-Pipeline-Policy" `
-Identity "alice@example.com"
Grant-CsApplicationAccessPolicy `
-PolicyName "Hermes-Meeting-Pipeline-Policy" `
-Identity "bob@example.com"
После предоставления распространение может занять до 30 минут. Проверьте командой:
Test-CsApplicationAccessPolicy -Identity "alice@example.com" -AppId "<MSGRAPH_CLIENT_ID>"
Без политики любые встречи пользователей доступны для чтения — именно это технически даёт разрешение. Не пропускайте этот шаг в продакшеновом тенанте.
Шаг 5: Запись учётных данных в env-файл
Запишите три собранных значения в ~/.hermes/.env:
MSGRAPH_TENANT_ID=<directory-tenant-id>
MSGRAPH_CLIENT_ID=<application-client-id>
MSGRAPH_CLIENT_SECRET=<client-secret-value>
Установите права на файл, чтобы только вы могли читать секрет:
chmod 600 ~/.hermes/.env
Шаг 6: Проверка токен-потока
Hermes поставляется с дымовым тестом аутентификации Graph. Из установленного Hermes:
python -c "
import asyncio
from tools.microsoft_graph_auth import MicrosoftGraphTokenProvider
provider = MicrosoftGraphTokenProvider.from_env()
token = asyncio.run(provider.get_access_token())
print('Token acquired, length:', len(token))
print(provider.inspect_token_health())
"
Успешный запуск печатает длинную строку токена и словарь состояния с cached: True и значением expires_in_seconds около 3600. При ошибках выводится MicrosoftGraphTokenError с кодом ошибки Azure. Самые распространённые:
| Ошибка Azure | Значение | Решение |
|---|---|---|
AADSTS7000215: Invalid client secret | Значение секрета не совпадает или истекло. | Создайте новый секрет на шаге 2; обновите .env. |
AADSTS700016: Application not found | Неверный MSGRAPH_CLIENT_ID или неверный тенант. | Убедитесь, что значения из шага 1 взяты из одного и того же приложения. |
AADSTS90002: Tenant not found | Опечатка в MSGRAPH_TENANT_ID. | Снова скопируйте Directory (tenant) ID со страницы обзора приложения. |
insufficient_claims при вызове (не при получении токена) | Токен получен, но Graph возвращает 401/403. | Вы пропустили административное согласие на шаге 3 или добавили разрешения, но не дали согласие повторно. Вернитесь в API permissions и снова нажмите Grant admin consent. |
Ротация секрета клиента
У секретов клиента Azure есть жёсткий срок действия. Перед истечением:
- Создайте второй секрет клиента на шаге 2, не удаляя первый.
- Обновите
MSGRAPH_CLIENT_SECRETв~/.hermes/.envновым значением. - Перезапустите шлюз, чтобы подхватить новый секрет:
hermes gateway restart. - Проверьте с помощью дымового теста выше.
- Удалите старый секрет из Azure Portal.
Следующие шаги
Когда учётные данные успешно прошли проверку, продолжайте:
- Настройка webhook listener — запустите платформу шлюза
msgraph_webhook, которая получает уведомления об изменениях от Graph. - Конфигурация конвейера — настройте среду выполнения конвейера Teams-встреч и CLI оператора.
- Исходящая доставка — настройте отправку резюме в Teams-канал или чат.
Эти страницы появятся вместе с PR, добавляющими соответствующее время выполнения. Настройка учётных данных — самостоятельный шаг и безопасна для выполнения заранее.