Files
ipwhitelist-app/docs/db-query-endpoint.md
naeel 4bdcb4c363 Export: убран filename из Content-Disposition для диалога сохранения
Версия: 0.1.13
Документация: db-query-endpoint.md
2026-07-08 14:57:17 +04:00

3.1 KiB

Endpoint SQL-запросов к БД (/v2/db/query)

Создан: 2026-07-08

Назначение

Дать DevOps-инженеру (одному человеку, заданному через ADMIN_EMAIL) возможность выполнять SQL-запросы к БД напрямую из браузера — без psql, без kubectl, без внешнего IP.

Доступ

  • Только один пользователь: req.email === ADMIN_EMAIL
  • Обычный юзер сервиса (проходит SSO как все)
  • Пример: ADMIN_EMAIL=atazet@narod.ru

Адрес

GET /v2/db/query?sql=<часть запроса после SELECT>

Как работает

  1. Пользователь заходит в сервис через SSO (любой URL, например /v2/app)
  2. Меняет в адресной строке путь на /v2/db/query?sql=...
  3. Сервер:
    • Проверяет сессию (resolveContext)
    • Проверяет что req.email === ADMIN_EMAIL
    • Добавляет префикс SELECT перед вводом пользователя
    • Выполняет: pool.query('SELECT ' + userInput)
    • Возвращает JSON

Примеры

Ввод в браузере Что выполняется
/v2/db/query?sql=* FROM _migrations SELECT * FROM _migrations
/v2/db/query?sql=count(*) FROM companies SELECT count(*) FROM companies
/v2/db/query?sql=* FROM whitelist_entries LIMIT 10 SELECT * FROM whitelist_entries LIMIT 10
/v2/db/query?sql=* FROM audit_log ORDER BY created_at DESC LIMIT 5 SELECT * FROM audit_log ORDER BY created_at DESC LIMIT 5

Безопасность

  1. SELECT префикс — жёстко добавляется SELECT перед вводом пользователя. DROP/INSERT/UPDATE/DELETE не работают:

    /v2/db/query?sql=DROP TABLE companies
    → SELECT DROP TABLE companies  (ошибка SQL, не выполнится)
    
  2. Одиночные запросы — драйвер pg не поддерживает множественные запросы в одном query(). Попытка 1; DROP TABLE не сработает.

  3. Доступ по email — только один человек, заданный в ADMIN_EMAIL.

  4. Rate limiter — endpoint защищён лимитером (как mutationLimiter).

Ответ

{
  "rows": [ ... ],
  "rowCount": 5,
  "fields": ["id", "filename", "applied_at"]
}

Реализация

  • Файл: v2/src/db/query.js
  • Middleware: resolveContext + проверка req.canQueryDB
  • Роутер монтируется в v2/server.js на /db
  • Флаг req.canQueryDB выставляется в v2/src/router/index.js (applyContext)

Ограничения

  • Только SELECT (через префикс)
  • Нет GUI — только JSON в браузере
  • SQL в URL (логируется в access_log nginx/ingress — это нормально для devops-инструмента)