86aa452ed6
- bj-license-server: активация по коду и продление токенов (API /v1), кабинет администратора (клиенты, лицензии, установки, журнал, администраторы) - защита: доверенные IP установок, jail fail2ban api/admin, раздел «Защита» с режимом обороны, белым списком и сроками блокировок (root-помощник fw-apply) - доступ к кабинету: свой адрес вместо /admin, вход только из белого списка, второй фактор — TOTP или подтверждение в «ЗЕТИТ Ключ» (push/код) - deploy/license: unit-файлы, fail2ban, path/timer помощника; контракт API в docs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
83 lines
4.6 KiB
Markdown
83 lines
4.6 KiB
Markdown
# Сервер лицензирования и обновлений bj — контракт API
|
||
|
||
Сервер: **https://lic.zetit.ru** (ВМ 46.173.19.220, Ubuntu 26.04). Адрес зашит в bj
|
||
(`internal/lkgateway`, константа), в интерфейсе не меняется. С этого же сервера bj
|
||
получает обновления.
|
||
|
||
## Модель
|
||
|
||
- Лицензия — прежний токен `internal/license`: подписанный Ed25519 JSON `License`,
|
||
строка `base64(payload).base64(sig).keyid`. Ключ подписи — `~/keys/license.priv`
|
||
(keyid `main`); открытый ключ зашит в bj.
|
||
- Клиенту выдаётся **код активации** (`BJ-XXXX-XXXX-XXXX`), один на лицензию; им
|
||
активируется до `max_nodes` установок (0 — без лимита).
|
||
- При активации сервер выдаёт токен **на 60 дней** (`expires_at`), но не дольше
|
||
`contract_until`; в токене `install_id` установки и `contract_until` договора.
|
||
- bj продлевает токен **раз в сутки**. Отзыв = сервер больше не продлевает; уже
|
||
выданный токен доживает свой срок (запас на недоступность сервера).
|
||
- Офлайн-ключи (`bj-license issue`, без `install_id`) продолжают работать — для
|
||
закрытых контуров без интернета.
|
||
|
||
## Идентификатор установки
|
||
|
||
`install_id` — UUID v4, создаётся bj при первом запуске и хранится в
|
||
`/var/lib/bj/.bj/setup.json` (`license.install_id`). Вместе с ним bj передаёт
|
||
`machine` — sha256(`/etc/machine-id`) в hex (для учёта и обнаружения клонов, не для
|
||
отказа).
|
||
|
||
## Запросы
|
||
|
||
Все тела — JSON, `Content-Type: application/json`. Ошибки — HTTP 4xx/5xx и
|
||
`{"error": "<код>", "message": "<текст по-русски>"}`.
|
||
|
||
### POST /v1/activate
|
||
|
||
```json
|
||
{"code": "BJ-7K3M-Q9XP-2HDA", "install_id": "…uuid…", "machine": "…sha256…",
|
||
"hostname": "bj-server-01", "version": "0.1.0"}
|
||
```
|
||
|
||
200:
|
||
```json
|
||
{"token": "<payload.sig.main>", "license_id": "…uuid…", "tenant": "ИК Фонтвьель",
|
||
"expires_at": "2026-11-14T10:00:00Z", "contract_until": "2027-09-14T00:00:00Z",
|
||
"renew_after_sec": 86400}
|
||
```
|
||
|
||
Коды ошибок: `bad_request`, `unknown_code`, `revoked`, `contract_expired`,
|
||
`max_nodes` (лимит установок исчерпан). Повторная активация той же `install_id` —
|
||
не новая установка, просто новый токен.
|
||
|
||
### POST /v1/renew
|
||
|
||
```json
|
||
{"token": "<текущий токен>", "install_id": "…", "machine": "…", "hostname": "…", "version": "…"}
|
||
```
|
||
|
||
Сервер проверяет подпись токена (срок **не** проверяет — продлить можно и
|
||
истёкший), совпадение `install_id` с токеном, что установка известна и лицензия не
|
||
отозвана. 200 — тот же формат, что у activate. Ошибки: `bad_token`,
|
||
`install_mismatch`, `unknown_install`, `revoked`, `contract_expired`.
|
||
Каждый успешный renew обновляет `last_seen`, `version`, `hostname`, IP установки.
|
||
|
||
### Обновления
|
||
|
||
- `GET /v1/{channel}/manifest.json` — подписанный манифест (`internal/release`),
|
||
без авторизации.
|
||
- `GET /v1/{channel}/files/{file}` — только с заголовком
|
||
`Authorization: License <token>`: подпись верна, срок не истёк, лицензия не
|
||
отозвана, в признаках есть `updates` (или план `enterprise`). Иначе 401/403 с
|
||
JSON-ошибкой. Ключ подписи манифестов отдельный от лицензионного.
|
||
|
||
### GET /healthz
|
||
|
||
`ok`.
|
||
|
||
## Кабинет администратора
|
||
|
||
`https://lic.zetit.ru/admin/` — вход по логину и паролю (bcrypt), только для нас:
|
||
клиенты (название, ИНН), лицензии (план, признаки, max_nodes, contract_until, код
|
||
активации, отзыв/восстановление), установки (install_id, hostname, версия, IP,
|
||
последнее продление, срок токена), журнал событий, выпуск офлайн-ключа для
|
||
закрытого контура.
|