CI/CD security, architecture doc, monitoring, security audit

- .github/workflows/security.yml: npm audit, pip-audit, gitleaks, dependency-review
- .github/workflows/ci.yml: lint required, ENABLE_DEV_AUTH/DEV_TOKEN for tests
- .gitleaks.toml: secret scan config and allowlist
- docs/ARCHITECTURE.md: high-level design, layers, auth, deployment
- docs/ops/MONITORING.md: Prometheus, health, alerting, Grafana
- docs/SECURITY_AUDIT.md: audit tools and procedures (ZAP, Bandit, Trivy)
- config/prometheus.yml: example scrape config
- README: CI/CD and docs links

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Yuriy 2026-02-14 21:56:02 +03:00
parent a7da43be0e
commit 1ec7f62a03
8 changed files with 625 additions and 0 deletions

93
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,93 @@
name: КЛГ АСУ ТК CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
backend-tests:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15-alpine
env:
POSTGRES_USER: klg
POSTGRES_PASSWORD: klg
POSTGRES_DB: klg
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
cd backend
pip install -r requirements.txt
pip install pytest pytest-cov openpyxl reportlab
- name: Run migrations
env:
DATABASE_URL: postgresql://klg:klg@localhost:5432/klg
run: |
for f in backend/migrations/*.sql; do
PGPASSWORD=klg psql -h localhost -U klg -d klg -f "$f" || true
done
- name: Run tests
env:
DATABASE_URL: postgresql://klg:klg@localhost:5432/klg
ENABLE_DEV_AUTH: "true"
DEV_TOKEN: test
run: |
cd backend
python -m pytest -v --tb=short --junitxml=results.xml
- name: Upload results
uses: actions/upload-artifact@v4
if: always()
with:
name: backend-test-results
path: backend/results.xml
frontend-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run build
docker-build:
runs-on: ubuntu-latest
needs: [backend-tests, frontend-lint]
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Build backend image
run: docker build -t klg-backend:latest ./backend
- name: Build frontend image
run: docker build -t klg-frontend:latest .

69
.github/workflows/security.yml vendored Normal file
View File

@ -0,0 +1,69 @@
# Проверки безопасности: зависимости, секреты, статический анализ
name: Security
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Еженедельно по понедельникам 06:00 UTC
- cron: '0 6 * * 1'
jobs:
npm-audit:
name: npm audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- name: Audit production dependencies
run: npm audit --audit-level=high
continue-on-error: true # не ломать пайплайн; отчёт в логах
pip-audit:
name: pip audit (Python)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install pip-audit
run: pip install pip-audit
- name: Audit backend dependencies
run: |
cd backend
pip-audit -r requirements.txt
continue-on-error: true
secret-scan:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
with:
config-path: .gitleaks.toml
continue-on-error: true
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4
with:
fail-on-severity: high
continue-on-error: true

35
.gitleaks.toml Normal file
View File

@ -0,0 +1,35 @@
# Gitleaks: правила поиска секретов в репозитории
# https://github.com/gitleaks/gitleaks
title = "KLG ASUTK - Secret detection"
[extend]
useDefault = true
# Дополнительные паттерны под проект
[[rules]]
id = "generic-api-key"
description = "Generic API Key"
regex = '''(?i)(api[_-]?key|apikey|api_key)\s*[:=]\s*['"]?[a-zA-Z0-9_\-]{16,}['"]?'''
tags = ["key", "api"]
[[rules]]
id = "database-url"
description = "Database URL with password"
regex = '''(postgres|mysql|mongodb)(:\/\/|:)['"]?[^'"\s]+:([^'"\s@]+)@'''
tags = ["database"]
# Исключения: примеры и тестовые значения
[allowlist]
description = "Allowlist for test/example values"
paths = [
'''\.env\.example''',
'''backend/\.env\.example''',
'''docs/''',
'''\.md$''',
]
regexes = [
'''(change-me|example|test|dummy|xxx|your[-_]?key)''',
'''postgresql://klg:klg@''',
'''redis://localhost''',
]

View File

@ -75,6 +75,22 @@ Annex 1, 6, 7, 8, 19 · Doc 9734, 9760, 9859
### EASA ### EASA
Part-21 · Part-66 · Part-M · Part-CAMO · Part-145 · Part-ARO Part-21 · Part-66 · Part-M · Part-CAMO · Part-145 · Part-ARO
## CI/CD
- **`.github/workflows/ci.yml`** — тесты backend (pytest), lint и сборка frontend, сборка Docker-образов при push в `main`.
- **`.github/workflows/security.yml`** — проверки безопасности: `npm audit`, `pip-audit`, Gitleaks (секреты), Dependency Review в PR; запуск при push/PR в `main` и по расписанию (еженедельно).
Подробнее: [docs/SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md).
## Документация
| Документ | Описание |
|----------|----------|
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | Архитектура системы (слои, потоки данных, безопасность) |
| [docs/ops/MONITORING.md](docs/ops/MONITORING.md) | Мониторинг production (Prometheus, health, алертинг, Grafana) |
| [docs/SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md) | Security-аудит: инструменты и процедуры |
| [docs/SECURITY.md](docs/SECURITY.md) | Правила безопасности и отчёт об уязвимостях |
## Тесты ## Тесты
```bash ```bash

17
config/prometheus.yml Normal file
View File

@ -0,0 +1,17 @@
# Пример конфигурации Prometheus для КЛГ АСУ ТК
# Использование: см. docs/ops/MONITORING.md
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'klg-backend'
metrics_path: /api/v1/metrics
static_configs:
- targets: ['localhost:8000']
scrape_interval: 15s
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']

119
docs/ARCHITECTURE.md Normal file
View File

@ -0,0 +1,119 @@
# Архитектура КЛГ АСУ ТК
Документ описывает архитектуру системы контроля лётной годности для крупного проекта (frontend + backend + инфраструктура).
---
## 1. Высокоуровневая схема
```
┌─────────────────────────────────────────────────────────┐
│ Пользователи / Браузер │
└─────────────────────────────┬─────────────────────────────┘
│ HTTPS
┌─────────────────────────────▼─────────────────────────────┐
│ Frontend (Next.js 14) │
│ · SSR/CSR · PWA · Tailwind · api-client → Backend │
│ · next-auth / Keycloak OIDC (JWT) │
└─────────────────────────────┬─────────────────────────────┘
│ /api/v1/* (proxy или прямой)
┌─────────────────────────────▼─────────────────────────────┐
│ Backend (FastAPI) │
│ · REST API · RBAC · RLS (multi-tenant) · Prometheus │
└──┬──────────┬──────────┬──────────┬──────────┬────────────┘
│ │ │ │ │
┌─────────────▼──┐ ┌───▼───┐ ┌──▼──┐ ┌────▼────┐ ┌──▼─────────────┐
│ PostgreSQL │ │ Redis │ │MinIO │ │Keycloak │ │ Внешние (ФГИС, │
│ (данные, RLS) │ │(кэш) │ │(S3) │ │ (OIDC) │ │ СМЭВ, email) │
└────────────────┘ └───────┘ └─────┘ └─────────┘ └────────────────┘
```
---
## 2. Слои системы
### 2.1 Frontend
| Компонент | Технологии | Назначение |
|-----------|------------|------------|
| Фреймворк | Next.js 14, React 18 | SSR, App Router, API routes (proxy) |
| Стили | Tailwind CSS | Единый UI |
| Данные | SWR, единый `lib/api/api-client.ts` | Запросы к Backend с токеном и 401-обработкой |
| Авторизация | next-auth (beta), Keycloak OIDC | JWT в заголовке `Authorization` |
| PWA | Service Worker, manifest | Офлайн-режим, установка на устройство |
- **Страницы:** дашборд, парк ВС, контроль ЛГ (директивы, SB, ресурсы, компоненты), наряды ТО, дефекты, персонал ПЛГ, чек-листы, риски, регулятор, нормативная база, настройки и др.
- **Прокси:** в dev `next.config.js` переписывает `/api/v1/*` на Backend (`BACKEND_URL`).
### 2.2 Backend
| Компонент | Технологии | Назначение |
|-----------|------------|------------|
| API | FastAPI | REST, OpenAPI, зависимости (DB, auth) |
| БД | SQLAlchemy 2, Alembic | Модели, миграции |
| Авторизация | JWT (Keycloak) или DEV-токен | `app.api.deps.get_current_user`, `require_roles` |
| Мультитенантность | PostgreSQL RLS, `set_tenant(db, org_id)` | Изоляция по организации |
| Файлы | MinIO (S3-совместимый) | Вложения, документы |
| Фоновые задачи | APScheduler (risk_scheduler и др.) | Сканирование рисков, уведомления |
- **Роуты:** разбиты по доменам (aircraft, airworthiness_core, work_orders, defects, personnel_plg, legal, fgis_revs, regulator и т.д.).
- **Единая точка БД:** `get_db` из `app.api.deps` (реэкспорт из `app.db.session`), в тестах переопределяется в conftest.
### 2.3 Инфраструктура
| Сервис | Роль |
|--------|------|
| **PostgreSQL** | Основное хранилище, RLS по `app.current_org_id` |
| **Redis** | Кэш, сессии, опционально очереди |
| **MinIO** | Хранилище файлов (S3 API) |
| **Keycloak** | OIDC: выдача JWT, роли, realm `klg` |
| **ФГИС РЭВС** | Внешний API реестра ВС и СЛГ (REST / СМЭВ 3.0) |
---
## 3. Потоки данных
### 3.1 Авторизация
1. Пользователь входит через Keycloak (или в dev — токен `DEV_TOKEN`).
2. Frontend сохраняет JWT (sessionStorage / next-auth) и передаёт в заголовке `Authorization: Bearer <token>`.
3. Backend в `get_current_user` проверяет токен (OIDC или dev), извлекает `organization_id` и роли.
4. Для мультитенантности перед запросами к БД вызывается `set_tenant(db, user.organization_id)` (RLS).
### 3.2 Сквозные сценарии (ЛГ)
- **ДЛГ (AD)** → создание наряда (WO) → выполнение → CRS → статус «выполнено».
- **Дефект** → WO → устранение → CRS.
- **Ресурс (Life Limit)** → контроль остатка → WO при достижении лимита.
- **Персонал ПЛГ** → scheduler проверяет сроки квалификации → risk alert при просрочке.
---
## 4. Безопасность
- **Секреты:** не в коде; `.env` в `.gitignore`, шаблоны `.env.example` и `backend/.env.example`.
- **CORS:** только разрешённые домены из `CORS_ORIGINS`.
- **Авторизация:** в production `ENABLE_DEV_AUTH=false`, только OIDC/JWT.
- **RBAC:** роли admin, authority_inspector, operator_manager, operator_user, mro_*; чувствительные эндпоинты через `require_roles`.
- **SQL:** параметризованные запросы (в т.ч. `set_tenant` через `bindparams`), без конкатенации пользовательского ввода.
---
## 5. Развёртывание
- **Локально:** `docker compose --profile base up -d`, затем backend (uvicorn) и frontend (npm run dev).
- **Production:** `docker compose --profile full` или Kubernetes (Helm chart в `./helm/klg-asutk`).
- **CI/CD:** GitHub Actions — тесты backend, lint и build frontend, сборка образов; отдельный workflow Security (npm audit, pip-audit, gitleaks).
---
## 6. Связанные документы
- [SECURITY.md](SECURITY.md) — правила безопасности и отчёт об уязвимостях.
- [docs/ops/MONITORING.md](ops/MONITORING.md) — мониторинг и алертинг в production.
- [docs/SECURITY_AUDIT.md](SECURITY_AUDIT.md) — проведение security-аудита и внешние инструменты.
- [ANALYSIS_AND_RECOMMENDATIONS.md](ANALYSIS_AND_RECOMMENDATIONS.md) — анализ и рекомендации по коду.
---
© АО «REFLY» — Разработчик АСУ ТК КЛГ

129
docs/SECURITY_AUDIT.md Normal file
View File

@ -0,0 +1,129 @@
# Security-аудит: инструменты и процедуры
Рекомендации по проведению проверок безопасности с помощью внешних и встроенных инструментов.
---
## 1. Инструменты, встроенные в CI
В репозитории настроен workflow **`.github/workflows/security.yml`**, который запускается при push в `main`, при pull request в `main` и по расписанию (еженедельно).
### 1.1 npm audit (Frontend)
- **Что проверяет:** известные уязвимости в зависимостях npm.
- **В CI:** job `npm-audit`, уровень `--audit-level=high`.
- **Локально:**
```bash
npm audit
npm audit --audit-level=high # только high/critical
npm audit fix # автоматическое обновление, с осторожностью
```
### 1.2 pip-audit (Backend)
- **Что проверяет:** уязвимости в Python-пакетах (аналог safety).
- **В CI:** job `pip-audit`, зависимости из `backend/requirements.txt`.
- **Локально:**
```bash
pip install pip-audit
cd backend && pip-audit -r requirements.txt
```
### 1.3 Gitleaks (сканирование секретов)
- **Что проверяет:** утечка секретов и ключей в коде и истории коммитов.
- **В CI:** job `secret-scan`, конфиг `.gitleaks.toml` (allowlist для примеров и тестов).
- **Локально:**
```bash
docker run --rm -v "$(pwd):/path" zricethezav/gitleaks:latest detect --source /path
```
или установить [gitleaks](https://github.com/gitleaks/gitleaks) и выполнить `gitleaks detect`.
### 1.4 Dependency Review (Pull Request)
- При открытии PR запускается **actions/dependency-review-action**: проверка добавленных зависимостей на известные уязвимости.
---
## 2. Дополнительные проверки (вручную или отдельным job)
### 2.1 OWASP ZAP (базовое сканирование веб-приложения)
Подходит для проверки фронтенда и API на типовые уязвимости (XSS, инъекции, небезопасные заголовки).
**Базовый запуск (Docker):**
```bash
# Запустить приложение (frontend + backend), затем:
docker run -t --rm -v $(pwd):/zap/wrk:rw \
-u $(id -u):$(id -g) \
ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
-t http://host.docker.internal:3000 \
-r zap_report.html
```
Для API:
```bash
docker run -t --rm -v $(pwd):/zap/wrk:rw \
ghcr.io/zaproxy/zaproxy:stable zap-baseline.py \
-t http://host.docker.internal:8000/docs \
-r zap_api_report.html
```
Результаты в `zap_report.html` / `zap_api_report.html`. Критичные и высокие риски нужно разбирать и устранять.
### 2.2 SAST (статический анализ кода)
- **Frontend:** в CI уже используется ESLint (в т.ч. правила безопасности); при необходимости можно добавить `eslint-plugin-security` или SonarQube/SonarCloud.
- **Backend:** можно подключить Bandit (`pip install bandit`, `bandit -r backend/app`) или Semgrep; при необходимости — отдельный job в CI.
Пример Bandit (локально):
```bash
pip install bandit
cd backend && bandit -r app -ll
```
### 2.3 Контейнеры (образы Docker)
- Сканирование образов на уязвимости: **Trivy**, **Snyk**, **docker scout**.
- Пример Trivy:
```bash
docker build -t klg-backend:latest ./backend
trivy image klg-backend:latest
```
---
## 3. Регулярность проверок
| Проверка | Частота | Где |
|----------|---------|-----|
| npm audit, pip-audit, gitleaks | При каждом push/PR в main + еженедельно | GitHub Actions |
| Dependency Review | Каждый PR в main | GitHub Actions |
| OWASP ZAP | Перед релизом или ежеквартально | Вручную / отдельный job |
| SAST (Bandit/Semgrep) | По желанию в CI или перед релизом | Вручную / job |
| Сканирование образов (Trivy) | При сборке образов или перед деплоем | Вручную / job |
---
## 4. Что делать при обнаружении уязвимости
1. **Критичная/высокая в зависимостях:** обновить пакет до безопасной версии или найти обход (patch/workaround); при необходимости временно задокументировать риск.
2. **Секрет в репозитории:** считать секрет скомпрометированным, сменить его, удалить из истории (git filter-branch / BFG) или использовать allowlist в gitleaks только для нечувствительных примеров.
3. **Уязвимость в коде (ZAP, SAST):** исправить по рекомендациям инструмента и перепроверить.
4. Не создавать публичные issue с детальным описанием уязвимости до её устранения; отчёт направлять ответственным за безопасность (см. [SECURITY.md](SECURITY.md)).
---
## 5. Чек-лист перед релизом
- [ ] `npm audit` и `pip-audit` без критичных/высоких рисков или риски приняты и задокументированы.
- [ ] Gitleaks не находит новых секретов (с учётом allowlist).
- [ ] Базовое сканирование OWASP ZAP выполнено, критичные находки устранены.
- [ ] Образы Docker отсканированы (Trivy/Snyk), критичные уязвимости устранены или приняты.
---
© АО «REFLY» — Разработчик АСУ ТК КЛГ

147
docs/ops/MONITORING.md Normal file
View File

@ -0,0 +1,147 @@
# Мониторинг production-окружения КЛГ АСУ ТК
Рекомендации по настройке мониторинга для промышленной эксплуатации.
---
## 1. Метрики Backend (Prometheus)
Backend отдаёт метрики в формате Prometheus на эндпоинте:
- **URL:** `GET /api/v1/metrics`
- **Формат:** text/plain (Prometheus exposition format)
### Метрики
| Метрика | Тип | Описание |
|---------|-----|----------|
| `klg_http_requests_total` | counter | Число запросов по method и path |
| `klg_http_request_duration_seconds` | counter | Сумма длительности запросов по method и path |
| `klg_http_errors_total` | counter | Ошибки по коду ответа (4xx, 5xx) |
### Пример конфигурации Prometheus (scrape)
Добавьте в `prometheus.yml`:
```yaml
scrape_configs:
- job_name: 'klg-backend'
metrics_path: /api/v1/metrics
static_configs:
- targets: ['backend:8000'] # или host:port вашего backend
scrape_interval: 15s
```
В Kubernetes используйте Service и при необходимости аннотации для Prometheus Operator.
---
## 2. Health Check
Используйте для проверки живости и готовности:
| Эндпоинт | Назначение |
|----------|------------|
| `GET /api/v1/health` | Общий статус: БД, Redis, risk_scanner, версия |
| `GET /api/v1/health/health/detailed` | Расширенная проверка: диск, память, счётчики данных |
Использование в Docker/Kubernetes:
- **livenessProbe:** `GET /api/v1/health` каждые 1030 с.
- **readinessProbe:** тот же или `/api/v1/health` с проверкой `status == "healthy"` или `"ok"`.
Пример для Kubernetes:
```yaml
livenessProbe:
httpGet:
path: /api/v1/health
port: 8000
initialDelaySeconds: 30
periodSeconds: 15
readinessProbe:
httpGet:
path: /api/v1/health
port: 8000
initialDelaySeconds: 5
periodSeconds: 10
```
---
## 3. Логирование
- **Backend:** Python `logging`; при деплое направляйте stdout/stderr в централизованную систему (например, Loki, CloudWatch, ELK).
- **Frontend:** ошибки можно отправлять в Sentry (`NEXT_PUBLIC_SENTRY_DSN`).
- Не логировать секреты и персональные данные в открытом виде.
---
## 4. Алертинг (рекомендуемые правила)
Настройте алерты в Prometheus/Alertmanager или аналоге.
| Алерт | Условие | Действие |
|-------|---------|----------|
| Backend down | `up{job="klg-backend"} == 0` | Уведомление on-call |
| Высокий % ошибок | `rate(klg_http_errors_total[5m]) / rate(klg_http_requests_total[5m]) > 0.05` | Разбор инцидента |
| Высокая задержка | Например, p99 latency по метрикам (если добавить histogram) | Деградация качества |
| Health degraded | Периодический probe к `/api/v1/health` возвращает `status != healthy` | Проверка БД/Redis |
---
## 5. Grafana (пример дашборда)
Импортируйте или создайте дашборд с панелями:
- **Requests:** `sum(rate(klg_http_requests_total[5m])) by (method, path)`.
- **Errors:** `sum(rate(klg_http_errors_total[5m])) by (status)`.
- **Health:** результат последнего запроса к `/api/v1/health` (через Blackbox exporter или скрипт).
Источник данных — Prometheus, указывающий на scrape целевого backend.
---
## 6. Docker Compose (локальный стек мониторинга)
Опционально для разработки/стенда можно добавить в `docker-compose`:
```yaml
prometheus:
image: prom/prometheus:latest
volumes:
- ./config/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
depends_on:
- backend
grafana:
image: grafana/grafana:latest
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
GF_USERS_ALLOW_SIGN_UP: "false"
ports:
- "3001:3000"
depends_on:
- prometheus
```
Создайте `config/prometheus.yml` с job `klg-backend` по образцу из раздела 1.
---
## 7. Чек-лист перед production
- [ ] Prometheus собирает метрики с `/api/v1/metrics`.
- [ ] Liveness/readiness настроены на `/api/v1/health`.
- [ ] Логи backend и frontend попадают в централизованное хранилище.
- [ ] Настроены алерты на падение сервиса и рост ошибок.
- [ ] Контакты on-call заданы в Alertmanager/канале уведомлений.
---
© АО «REFLY» — Разработчик АСУ ТК КЛГ