# 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.
