исправление багов

This commit is contained in:
Zuev
2026-07-13 03:28:18 +03:00
parent 39c58440cf
commit 85f61436b6
76 changed files with 9219 additions and 1258 deletions

77
docs/SECURITY_RUNBOOK.md Normal file
View File

@@ -0,0 +1,77 @@
# Runbook безопасности production-секретов
Этот документ описывает действия оператора, которые нельзя выполнять автоматически из репозитория. Он не содержит и не должен содержать значения секретов, паролей, токенов, cookie или строк подключения.
## Обязательные Kubernetes Secrets
Production-манифесты только ссылаются на заранее созданные объекты:
| Secret | Обязательные ключи | Потребитель |
|---|---|---|
| `app-secret` | `JWT_SECRET`, `POSTGRES_USER`, `POSTGRES_PASSWORD` | Backend |
| `tenants-secret` | `tenants.json` | Backend, файл `/config/tenants.json` |
| `otel-postgres-secret` | `MAGISTR_DB_ENDPOINT`, `MAGISTR_DB_USERNAME`, `MAGISTR_DB_PASSWORD`, `MAGISTR_DB_NAME`, `N8N_DB_ENDPOINT`, `N8N_DB_USERNAME`, `N8N_DB_PASSWORD`, `N8N_DB_NAME` | OTel Collector |
| `gitea-registry` | стандартный ключ Docker registry | Kubernetes image pull |
Предпочтительный источник — External Secrets, SOPS/Sealed Secrets либо корпоративный secret manager. Kubernetes Secret, созданный вручную, допустим как переходный вариант, если в кластере включено шифрование etcd и значения никогда не сохраняются в Git.
Для переходного создания из защищённых файлов на рабочей станции оператора:
```bash
kubectl create namespace magistr --dry-run=client -o yaml | kubectl apply -f -
kubectl -n magistr create secret generic app-secret \
--from-env-file=/secure/path/app-secret.env \
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n magistr create secret generic tenants-secret \
--from-file=tenants.json=/secure/path/tenants.json \
--dry-run=client -o yaml | kubectl apply -f -
kubectl -n magistr create secret generic otel-postgres-secret \
--from-env-file=/secure/path/otel-postgres-secret.env \
--dry-run=client -o yaml | kubectl apply -f -
```
Не перенаправляйте YAML из этих команд в файл и не используйте `kubectl get secret -o yaml` в логах CI/CD.
## Порядок ротации
1. Зафиксировать владельца, область и версию каждого скомпрометированного значения в закрытой системе управления инцидентами.
2. Создать новые значения средствами secret manager. JWT-ключ должен быть криптографически случайным и содержать не менее 32 байт.
3. Сначала сменить пароли в каждой tenant-БД, затем атомарно обновить соответствующую версию `tenants-secret`.
4. Обновить OTel credentials и `otel-postgres-secret`, после чего перезапустить только collector и проверить поступление метрик.
5. Обновить `JWT_SECRET` в `app-secret` и выполнить контролируемый rollout backend. Смена ключа немедленно аннулирует ранее выданные access JWT.
6. Если политика инцидента требует завершить все пользовательские сессии, очистить `auth_refresh_tokens` отдельно в каждой tenant-БД через утверждённую DBA-процедуру. Эта операция не должна затрагивать пользователей или демонстрационные данные.
7. Проверить readiness, вход, refresh, logout и доступ каждого tenant. Только после этого отозвать предыдущие версии DB/OTel credentials в secret manager.
8. Хранить предыдущую версию секрета только в защищённом менеджере на период согласованного rollback window; не создавать резервные YAML-файлы.
Команда `../k8s/deploy.sh` проверяет наличие объектов и обязательных ключей, но намеренно не читает и не выводит их значения.
## Очистка истории
Переписывание истории и force-push выполняются только после отдельного согласования со всеми владельцами клонов и CI/CD:
1. Создать закрытый mirror-клон и резервную копию refs.
2. Подготовить вне репозитория файл замен для `git filter-repo`; не помещать исходные или новые значения в аргументы shell, issue или CI-логи.
3. Запустить в mirror-клоне:
```bash
git filter-repo --replace-text /secure/path/replacements.txt --force
```
4. Выполнить secret scan переписанной истории и проверить теги/ветви.
5. В согласованное окно выполнить force-push, инвалидировать старые CI caches/artifacts и потребовать повторное клонирование.
6. Отдельно проверить историю репозитория, которому принадлежат файлы `../k8s/`: эта директория не входит в Git-корень Magistr.
Переписывание истории не заменяет ротацию: опубликованные значения считаются скомпрометированными даже после удаления из Git.
## Проверка после rollout
```bash
bash ../k8s/deploy.sh status
kubectl rollout status deployment/backend -n magistr --timeout=300s
kubectl rollout status deployment/otel-collector-db -n magistr --timeout=180s
```
Дополнительно оператор должен проверить audit-события secret manager, шифрование etcd, минимальные RBAC-права и отсутствие значений секретов в логах, событиях pod и артефактах CI.