78 lines
6.5 KiB
Markdown
78 lines
6.5 KiB
Markdown
# 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.
|