Files
magistr/docs/SECURITY_RUNBOOK.md
2026-07-13 03:28:18 +03:00

78 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.