Лицензионный портал: от идеи до production
Как я создал полноценную систему управления лицензиями для собственного
SaaS-продукта за 3 недели
Рассказываю о разработке лицензионного портала — системы, которая контролирует
выдачу ключей, мониторит активации и автоматизирует весь цикл работы с
клиентами IT Budget Manager.
Ключевые цифры проекта
- 11 таблиц в базе данных
- 33 разрешения в системе RBAC
- 5 ролей пользователей
- ECDSA P-256 — криптографическая подпись лицензий
- FastAPI + React — современный стек
- Docker Compose — полная контейнеризация
Предыстория: зачем понадобился отдельный портал
Budget Manager — это веб-система управления бюджетом, которую я
разрабатываю как самостоятельный продукт. Когда проект вырос до уровня, где
его можно предлагать внешним клиентам, встал вопрос:
как контролировать лицензии?
Варианты были такие:
- Ручной контроль в Excel — не масштабируется, легко потерять
данные - Готовые SaaS-решения — дорого, избыточно, нет контроля
- Свой портал — полный контроль, интеграция с продуктом,
кастомная логика
Выбрал третий путь. Да, это больше работы, но зато:
- Полная интеграция с основным продуктом
- Криптографическая защита лицензий
- Автоматический мониторинг установок
- Гибкая система ролей под мою команду
Архитектура решения
Портал построен по классической схеме с разделением на frontend и backend:

Технологический стек
Backend:
- FastAPI — асинхронный Python-фреймворк
- SQLAlchemy + Alembic — ORM и миграции
- PostgreSQL — основная БД
- Redis — кэширование и rate limiting
- cryptography — ECDSA подпись лицензий
- Pydantic — валидация данных
Frontend:
- React 18 + TypeScript
- Ant Design — UI-компоненты
- Zustand — state management
- Vite — сборка
Инфраструктура:
- Docker Compose — локальная разработка и production
- GitHub Actions — CI/CD
- Nginx — reverse proxy
Модель данных: что храним в БД
Проектирование схемы БД — один из самых важных этапов. Вот что получилось:
Основные сущности
Клиенты (clients) — юрлица с ИНН, сегментом
(SMB/Enterprise/Government) и типом внедрения (on-prem/SaaS).
Лицензии (licenses) — ключевая таблица:
- Уникальный ключ (LIC-XXXXXX)
- План (Basic/Advanced/Enterprise)
- Список модулей (JSON)
- Лимиты: пользователи, отделы, интеграции, API rate
- Сроки действия + grace period
- Статус: draft/active/expired/revoked/suspended

Активации (license_activations) — записи об установках:
- ID сервера клиента
- IP-адрес
- Версия продукта
- Последний heartbeat
- Метрики использования
Организации (organizations) — для self-service регистрации
клиентов на портале.
ENUM-типы для консистентности
clientsegment: smb, enterprise, government
deploymenttype: on_prem, saas
licenseplan: basic, advanced, enterprise
licensestatus: draft, active, expired, revoked, suspended
paymentstatus: pending, paid, overdue, cancelled, refunded
Криптографическая подпись лицензий
Это ядро всей системы. Каждая лицензия подписывается приватным ключом, а
клиентская установка проверяет подпись публичным ключом.
Почему ECDSA P-256?
- Компактные ключи — в отличие от RSA
- Быстрая верификация — важно для клиентских установок
- Стандарт NIST — FIPS 186-4, проверенная криптография
- Эквивалент RSA-3072 — по уровню безопасности
Формат лицензионного токена
Использую JWT-подобный формат из трёх частей:
<base64(payload)>.<base64(metadata)>.<base64(signature)>
Payload содержит все данные лицензии:
Metadata — служебная информация: {
{
"version": 1,
"license_key": "LIC-ABC123...",
"client_id": 123,
"client_name": "ООО Компания",
"plan": "enterprise",
"modules": ["basic_budgeting", "ai_forecast", "multi_department"],
"limits": {
"max_users": 100,
"max_departments": 50,
"max_integrations": 10,
"api_rate_limit": 1000
},
"validity": {
"start_date": "2025-01-01T00:00:00Z",
"end_date": "2026-01-01T00:00:00Z",
"grace_period_days": 30
},
"technical": {
"domain": "budget.company.com",
"product_version": "2.5.0"
},
"issued_at": "2024-12-15T10:30:00Z",
"issued_by": "admin@portal.com"
}
"checksum": "a1b2c3d4...", // SHA-256 от payload
"algorithm": "ECDSA-P256",
"signed_at": "2024-12-15T10:30:05Z"
}
Защита от подделки
| Атака | Защита |
|---|---|
| Модификация данных | ✅ Цифровая подпись ECDSA |
| Подмена payload | ✅ SHA-256 checksum + подпись |
| Подмена клиента | ✅ client_id в подписанном payload |
| Изменение сроков | ✅ validity в подписанном payload |
| Replay атаки | ✅ Уникальный license_key + heartbeat |
Система ролей и прав доступа (RBAC)
Для управления доступом реализовал полноценную RBAC-систему с 5 ролями и 33
разрешениями.
Роли пользователей
| Роль | Описание | Ключевые права |
|---|---|---|
| Admin | Руководитель/DevOps | Полный доступ ко всему |
| Sales Manager | Менеджер по продажам | Клиенты, лицензии, оплаты |
| Implementation | Инженер внедрения | Активации, мониторинг, конфигурации |
| Support | Техподдержка | Только чтение + заметки |
| Audit | Финансы/юристы | Только чтение + отчёты |
Категории разрешений
- Клиенты: read, create, update, delete
- Лицензии: read, create, update, delete, activate, revoke,
generate - Активации: read, manage
- Платежи: read, create, update, delete
- Пользователи: read, create, update, delete, manage_roles
- Аудит: read
- Отчёты: view, export
Использование в коде
# Проверка одного разрешения
@router.get("/clients")
async def get_clients(
user: User = Depends(require_permission(Permission.CLIENTS_READ))
):
...
# Проверка роли
@router.post("/critical")
async def critical_operation(
user: User = Depends(require_role("admin"))
):
...
API для клиентских установок
Отдельный набор endpoints для взаимодействия продукта с порталом. Защищён
API-ключами (не JWT).
Основные endpoints
POST /api/v1/license-verification/verify — проверка
валидности ключа
Headers: X-API-Key: <api_key>
Body: {
"license_key": "LIC-ABC123..."
}
Response: {
"valid": true,
"status": "active",
"organization": "ООО Компания",
"expires_at": "2026-01-01T00:00:00Z",
"modules": ["basic_budgeting", "ai_forecast"]
}
POST /api/v1/product/licenses/activate — активация лицензии
POST /api/v1/product/licenses/heartbeat — периодический пинг
от установки
Workflow активации
- Пользователь регистрирует организацию на портале
- Администратор создаёт лицензию и привязывает к организации
- Клиент вводит ключ в своей установке IT Budget Manager
- Установка делает запрос к API портала с API-ключом
- Портал проверяет подпись, срок, статус
- При успехе — возвращает конфигурацию модулей и лимитов
- Продукт активируется с полученными параметрами
Деплой и CI/CD
Проект полностью контейнеризирован и деплоится через GitHub Actions.
Автоматический деплой
При push в main:
- GitHub Actions подключается к серверу по SSH
- Пуллит изменения
- Пересобирает контейнеры
- Применяет миграции БД
- Перезапускает сервисы
Что реализовано на текущий момент
✅ Полностью готово
- Инфраструктура (Docker, PostgreSQL, Redis)
- Модели данных и миграции Alembic
- Система RBAC с 5 ролями
- Криптографическая подпись лицензий (ECDSA P-256)
- API аутентификации (JWT + API Keys)
- CRUD для клиентов, лицензий, организаций
- API проверки лицензионных ключей
- Dashboard со статистикой
- CI/CD через GitHub Actions
- Документация (OpenAPI, README, инструкции)
🚧 В процессе
- Мастер создания лицензий (step-by-step wizard)
- Дашборд мониторинга активаций
- Система уведомлений (email, Telegram)
- Интеграция с биллингом
Уроки и выводы
Что сработало хорошо
1. FastAPI + Pydantic — отличная комбинация. Автоматическая
валидация, генерация OpenAPI-документации, асинхронность из коробки.
2. Alembic для миграций — версионирование схемы БД спасает
при командной разработке и откатах.
3. Docker Compose — одна команда для запуска всего окружения.
Идентичность dev и prod.
4. ECDSA вместо RSA — компактные токены, быстрая верификация
на клиенте.
Сложности
1. Проектирование RBAC — пришлось несколько раз
пересматривать список разрешений. Важно продумать заранее.
2. Хранение приватного ключа — в dev просто файл, в prod
нужен Vault или KMS. Заложил абстракцию сразу.
3. Миграции с ENUM — PostgreSQL требует особого подхода при
изменении ENUM-типов.
Рекомендации
- Начинайте с модели данных — это фундамент
- Закладывайте RBAC с первого дня
- Используйте криптографию правильно — не изобретайте велосипед
- Документируйте API сразу (OpenAPI)
- Контейнеризируйте с самого начала
Планы развития
Ближайшие задачи:
- Мастер создания лицензий с пошаговым wizard
- Мониторинг активных установок в реальном времени
- Email-уведомления об истечении лицензий
- Telegram-бот для алертов
Долгосрочные цели:
- Интеграция с 1С для импорта платежей
- Self-service кабинет для клиентов
- Аналитика использования модулей
- 2FA для критических операций
Итог
Лицензионный портал — это не просто «база данных с ключами». Это полноценная
система, которая:
- Защищает продукт криптографически
- Автоматизирует выдачу и контроль лицензий
- Мониторит все установки в реальном времени
- Масштабируется вместе с бизнесом
Разработка заняла около 3 недель активной работы. Основное время ушло на
проектирование модели данных и криптографическую часть. UI и API —
относительно быстро благодаря FastAPI и Ant Design.
Если вы разрабатываете SaaS-продукт и думаете о лицензировании — не
откладывайте. Чем раньше заложите правильную архитектуру, тем меньше проблем
будет при масштабировании.

Стек проекта: Python, FastAPI, PostgreSQL, Redis, React,
TypeScript, Docker, GitHub Actions
Статус: В активной разработке, MVP готов

