Skip to content

Внешний API (v3) ​

Панель отдаёт HTTP API для сторонних интеграций на /api/v3/*. Авторизация — по ключу, права — по областям доступа (scopes).

Включение ​

API выключен по умолчанию. Включается переменными веб-бэкенда:

ПеременнаяПо умолчаниюЧто делает
EXTERNAL_API_ENABLEDfalseглавный выключатель /api/v3/*
EXTERNAL_API_DOCSfalseотдавать Swagger UI на /api/v3/docs

Текущее состояние видно в интерфейсе: Настройки → API.

Создание ключа ​

  1. API и вебхуки → API-ключи
  2. Создать ключ, указать:
    • имя — понятное человеку, например prod-monitoring
    • срок жизни — бессрочно, 1, 7, 30, 90 или 365 дней; просроченный ключ отвечает 401
    • области доступа — см. таблицу ниже
    • описание — по желанию
  3. Ключ показывается один раз. Скопируйте его в своё хранилище секретов: закрыть диалог, не подтвердив сохранение, панель не даст
  4. Дальше виден только префикс — первые 12 символов вида rwa_AbCd3fGh. Полное значение восстановить нельзя: если потеряли, ключ придётся перевыпустить

Формат ​

rwa_<43 символа urlsafe base64>

Префикс rwa_ помечает класс ключа, дальше 32 случайных байта. В базе хранится только SHA-256 от ключа — открытого значения у сервера нет.

Авторизация ​

Ключ передаётся заголовком X-API-Key в каждом запросе:

bash
curl -H "X-API-Key: rwa_ВАШ_КЛЮЧ" https://admin.example.com/api/v3/users
python
import requests

r = requests.get(
    "https://admin.example.com/api/v3/users",
    headers={"X-API-Key": "rwa_ВАШ_КЛЮЧ"},
    timeout=10,
)
javascript
const res = await fetch("https://admin.example.com/api/v3/users", {
  headers: { "X-API-Key": "rwa_ВАШ_КЛЮЧ" },
})

Что вернётся при отказе:

СитуацияОтвет
нет заголовка401 Missing X-API-Key header
ключ неверный, отключён или просрочен401 Invalid or expired API key
ключу не хватает области доступа403 Missing scope: <имя>
превышен лимит запросов429 с заголовком Retry-After

Области доступа ​

Запрос проходит, только если у ключа есть область, которую требует эндпоинт.

ОбластьЧто разрешаетПримеры
users:readчитать пользователейGET /users, GET /users/{uuid}
users:writeсоздавать, менять, включать, сбрасывать трафикPOST /users, POST /users/{uuid}/enable
users:deleteудалять пользователяDELETE /users/{uuid}
nodes:readчитать нодыGET /nodes, GET /nodes/{uuid}
nodes:writeвключать, отключать, перезапускать ноду, синхронизировать список нод с панельюPOST /nodes/{uuid}/restart
nodes:tokenгенерировать и отзывать токен агента нодыPOST /nodes/{uuid}/agent-token/generate
hosts:readчитать хостыGET /hosts
stats:readобщая статистикаGET /stats
violations:readчитать нарушенияGET /violations
enforcement:supportсообщать об обращении клиента во внешнюю поддержкуPOST /support-events
bulk:writeмассовые операцииPOST /users/bulk/*

Разумные привычки:

  • Давайте ровно то, что нужно: дашборду хватит users:read, users:delete ему ни к чему
  • Свой ключ на каждую интеграцию — тогда его отзыв не заденет остальные
  • Ключам CI/CD ставьте короткий срок жизни и перевыпускайте регулярно
  • bulk:write обходит проверки по отдельным пользователям — относитесь к нему как к привилегированному
  • nodes:token даёт доступ к токену агента — этим токеном аутентифицируется Collector API, WebSocket агента и удалённый терминал, то есть фактически это ключ к хосту ноды. Ещё более привилегированная область, чем bulk:write

Ключ не может получить область, права на которую нет у создавшего его админа. Области, которые работают по всем юзерам (users:*, bulk:write, violations:read, enforcement:support), выдаёт только админ без ограничения видимости юзеров. Ключ отключённого или удалённого админа перестаёт работать.

Ограничения ключа ​

Кроме областей, ключ можно сузить — в окне создания или правки:

  • Адреса — список IP и подсетей, например 203.0.113.10 и 10.0.0.0/24. С любого другого адреса ключ считается недействительным и получает 401. Пустой список — любой адрес
  • Юзеры — сквады и тег. Ключ видит и меняет только юзеров, которые состоят хотя бы в одном из этих сквадов и носят этот тег (если заданы оба условия, нужны оба), и только их нарушения. Создать юзера такой ключ может лишь в своих сквадах и со своим тегом — тег подставляется сам

Журнал запросов ​

У каждого ключа в интерфейсе есть журнал последних запросов: метод, путь, код ответа, IP и время. По нему видно, кто и откуда ходит с ключом, — и что пора его перевыпустить.

Лимиты запросов ​

Считаются в окне 60 секунд, отдельно по каждому ключу.

ПеременнаяПо умолчаниюНа что действует
API_V3_RATE_READ_PER_MIN120запросы GET
API_V3_RATE_WRITE_PER_MIN60POST, PATCH, DELETE кроме массовых
API_V3_RATE_BULK_PER_MIN10всё под /users/bulk/

При превышении приходит 429 и заголовок Retry-After с числом секунд до конца окна.

Счётчик привязан к ключу, а не к адресу: два разных ключа с одного сервера квоту не делят.

Перевыпуск ​

  1. Кнопка Перевыпустить рядом с ключом
  2. Выберите, сколько ещё будет работать старое значение: сразу погасить — если ключ утёк, или оставить на 1–72 часа, пока интеграция переключается на новый
  3. Новое значение показывается один раз — обновите интеграцию

Имя, области доступа, ограничения, срок и описание сохраняются — история не теряется. Перевыпуск попадает в аудит-лог.

Просроченные ключи ​

По достижении срока ключ считается недействительным, в списке появляется отметка. Оживить его можно только перевыпуском — новый секрет, новый отсчёт.

Аудит ​

Создание, изменение, перевыпуск и удаление ключей пишутся в аудит-лог: кто, с какого адреса, что именно поменял. Сам секрет туда, разумеется, не попадает.

Частые вопросы ​

Почему «последнее использование» отстаёт? Отметка сбрасывается в базу раз в 30 секунд — иначе под нагрузкой строка ключа стала бы точкой блокировок.

Можно один ключ на несколько интеграций? Технически да, практически нет: одна скомпрометированная система утаскивает за собой остальные, а по аудиту потом не понять, кто что делал.

Можно посмотреть ключ ещё раз? Нет. Только перевыпуск.

Есть ограничение по адресам? Да — список IP и подсетей в ограничениях ключа.

AGPL-3.0 с исключением для плагинов