API-ключи: области действия, срок жизни, отзыв
sandbox-api.k8s.tangovision.dev принимает два вида учётных данных: org-scoped bearer-токен tvk_… и токен сессии вошедшего пользователя портала (его же сохраняет npx @tv/extension-sdk login — см. Вход через CLI). Ключи нужны для CI и всего остального неинтерактивного. Выпускаются они в портале разработчика; открытый текст показывается ровно один раз. Эта страница — справочник по поведению ключей.
Сначала два инварианта:
- Ключ никогда не может выпустить другой ключ. Для выпуска нужна активная сессия портала, поэтому утёкший ключ не размножится.
- До 5 активных ключей на организацию. Отозванные и истёкшие ключи не считаются — отзывайте то, чем не пользуетесь.
Области действия
Каждый ключ несёт одну область действия, выбранную при выпуске:
| Область | Разрешает | Для чего |
|---|---|---|
sandbox (по умолчанию) | API жизненного цикла песочниц (/api/v1/sandboxes*): создание, список, продление, сброс, удаление | Повседневная разработка модулей, CI, создающий песочницы |
publish | Публикация модулей (появится вместе с tv-sdk publish; пока ни один эндпоинт её не принимает) | Релизные конвейеры — когда публикация выйдет |
full | Всё вышеперечисленное плюс список и отзыв ключей через API | Аварийная автоматизация; предпочитайте более узкие области |
Запрос вне области действия ключа завершается 403 с кодом ошибки SCOPE_DENIED — выпустите ключ с нужной областью вместо расширения ключа существующего конвейера. Ключи, выпущенные до появления областей действия, ведут себя как full.
Вся поверхность управления ключами требует full
/api/v1/keys* требует области full, включая получение списка. Ключ с областью sandbox получит 403 SCOPE_DENIED даже на GET /api/v1/keys — это сделано намеренно, но удивляет тех, кто ожидает, что ключ способен увидеть хотя бы сам себя.
Срок жизни
Ключи самообслуживания всегда истекают — по умолчанию через 90 дней. Портал выпускает именно с этим значением; чтобы выбрать другой срок, вызовите API напрямую из своей сессии портала:
curl -X POST https://sandbox-api.k8s.tangovision.dev/api/v1/keys \
-H "Authorization: Bearer $PORTAL_JWT" \
-H "Content-Type: application/json" \
-d '{"label": "ci", "scope": "sandbox", "expiresInDays": 30}'Обратите внимание на Bearer $PORTAL_JWT — это не стилистический выбор. Для выпуска всегда нужна сессия портала: запрос, аутентифицированный ключом tvk_…, отклоняется с 403 KEY_MINT_REQUIRES_PORTAL_SESSION. Это первый инвариант из начала страницы, реализованный в коде.
expiresInDays принимает 1–365; всё остальное — 400 INVALID_EXPIRY. label длиннее 100 символов — тоже 400. Истёкший ключ получает 401 на следующем запросе; выпустите замену в портале (список ключей показывает дату истечения каждого, а статус меняется на истёк). Бессрочные ключи существуют только как операторские — запрос на такой в самообслуживании отклоняется с 403 NON_EXPIRING_DENIED, — поэтому напишите на developers@tango.vision, если сервису такой действительно нужен.
Ответ на выпуск — 201 вида { token, key }: token — тот самый открытый текст, который вы больше не увидите, key — метаданные, которые видны и в списке в портале.
Отзыв
Отзыв — в портале или через API:
curl -X DELETE https://sandbox-api.k8s.tangovision.dev/api/v1/keys/<keyId> \
-H "Authorization: Bearer $PORTAL_JWT"Отзыв возвращает 200 { "revoked": true } и действует со следующего запроса ключа — каждый запрос заново проверяется по хранилищу ключей, без какого-либо кэша, так что наблюдаемая задержка распространения равна времени до вашего следующего запроса. (Формальное обязательство платформы — менее 5 минут глобально; на практике это секунды.) Отзыв чужого ключа или уже отозванного — 404.
Если ключ утёк — немедленно отзовите его, выпустите замену и сообщите нам, чтобы вместе посмотреть журнал аудита.
Журнал аудита
Каждое событие ключа записывается: выпуск (кто выпустил, какая область, какой срок), использование (каждый аутентифицированный запрос: ключ, маршрут, IP-адрес, user agent), отказы (отозванные/истёкшие/неизвестные ключи, нарушения области действия) и отзыв. Записи хранятся 18 месяцев.
Из сессии портала можно запросить журнал своей организации:
curl "https://sandbox-api.k8s.tangovision.dev/api/v1/keys/audit?limit=50" \
-H "Authorization: Bearer $PORTAL_JWT"Фильтры: action (key.issued | key.used | key.revoked), keyId и limit — последний по умолчанию равен 100 и ограничивается сверху значением 500, а не отклоняется. Неизвестный action — это 400 INVALID_ACTION. Ответ имеет вид { events: [...] }.
Внешний разработчик читает журнал из сессии портала: ключ tvk_… отклоняется с 403 AUDIT_REQUIRES_PORTAL_SESSION. В записях есть IP-адреса и user agent, которым нечего делать за секретом CI. (Исключение — внутренние операторские учётные данные: они читают журнал напрямую и по всем организациям, что и нужно при разборе инцидентов.)