Проект разделен на два репозитория

This commit is contained in:
mi
2026-08-14 15:42:45 +03:00
parent e06a77ee1d
commit bbef7a30c9
521 changed files with 2597 additions and 2302 deletions
+186
View File
@@ -0,0 +1,186 @@
# Инфраструктурный тест HAN Chat
Автономный тест запускается непосредственно на ВМ и проверяет managed PostgreSQL и
три приватных Selectel S3-бакета в соответствии с контрактами HAN Chat. Для запуска
приложение и Docker Compose не требуются.
Тест не создаёт постоянных данных:
- PostgreSQL DDL/DML выполняются в транзакции и завершаются `ROLLBACK`;
- S3-объекты создаются только под уникальным префиксом `infratest/<uuid>/`;
- все S3-объекты удаляются в блоке очистки даже при ошибке одной из проверок.
## Что проверяется
### PostgreSQL
- подключение пяти сервисных ролей с TLS `verify-full`;
- `current_user`, `search_path`, наличие своей схемы и отсутствие `USAGE` на четыре
чужие схемы;
- `CREATE TABLE`, `INSERT`, `SELECT` и фактическое отсутствие таблицы после
`ROLLBACK`;
- расширение `pgcrypto`;
- опционально — ключевые таблицы и Alembic revision после миграций.
Проверяются роли:
- `han_app``han_app`;
- `bitrix_local_app``bitrix_local`;
- `bitrix_sync_user``bitrix_sync`;
- `message_safety_app``message_safety`;
- `keycloak_user``keycloak`.
### S3
- `HeadBucket` для quarantine, attachments и documents;
- прямые `PutObject`, `HeadObject`, `GetObject`, `ListObjectsV2` с ВМ;
- presigned PUT и GET с побайтовой проверкой содержимого;
- проектный переход `CopyObject` из quarantine в attachments с удалением
исходного объекта;
- запрет анонимного GET;
- CORS preflight для точного `PUBLIC_WEB_URL`;
- отдельный ключ message-safety: чтение/list только quarantine, запрет записи,
удаления и доступа к attachments/documents.
Multipart API не проверяется: текущая реализация HAN Chat использует single PUT.
Прикладные сценарии авторизации, создания диалога и отправки сообщения также не
входят в этот инструмент — это E2E приложения, а не проверка инфраструктуры.
## Подготовка на ВМ
Рекомендуется скопировать всю папку в отдельный каталог:
```bash
mkdir -p /opt/han-chat/infratest
cd /opt/han-chat/infratest
```
Установите Python 3.10+ и создайте изолированное окружение:
```bash
python3 -m venv .venv
. .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements.txt
```
Создайте настройки:
```bash
cp .env.example .env
chmod 600 .env
nano .env
```
В `.env` нужны сервисные пароли PostgreSQL, основной S3 RW-ключ и отдельный
quarantine read-only ключ. Административный пароль PostgreSQL не используется.
`HAN_PG_SSLROOTCERT` должен указывать на CA-файл по пути, доступному из процесса
на ВМ, а не на контейнерный путь `/run/secrets/pg-ca.pem`.
Не передавайте секреты аргументами командной строки и не прикладывайте `.env` к
отчётам. Файл исключён через `.gitignore`.
## Запуск
Полная самочищающаяся проверка:
```bash
cd /opt/han-chat/infratest
. .venv/bin/activate
python3 infratest.py --mode full
```
Проверка без DDL и записи в S3:
```bash
python3 infratest.py --mode readonly
```
Другой файл настроек и JSON-отчёт:
```bash
python3 infratest.py \
--env-file /secure/path/infratest.env \
--mode full \
--json-report report.json
```
Скрипт возвращает:
- `0` — нет проваленных проверок;
- `1` — одна или несколько инфраструктурных проверок завершились ошибкой;
- `2` — неверная конфигурация или отсутствуют Python-зависимости.
В консоль и JSON не выводятся пароли, access keys и query-параметры presigned URL.
## Запуск до и после миграций
До запуска Alembic оставьте:
```dotenv
INFRATEST_CHECK_MIGRATIONS=false
```
После успешного `deployment/scripts/migrate.sh` измените значение на:
```dotenv
INFRATEST_CHECK_MIGRATIONS=true
```
В этом режиме дополнительно проверяются ключевые таблицы схем `han_app`,
`bitrix_local`, `bitrix_sync` и ожидаемая revision `0001_initial` для `han_app`.
## Ожидаемая IAM-модель
Основной `SELECTEL_S3_ACCESS_KEY` должен иметь:
- RW на quarantine, attachments и documents;
- `ListBucket`, `GetBucketLocation`, `PutObject`, `GetObject`, `DeleteObject`;
- `CopyObject` обеспечивается правами чтения источника и записи назначения.
Ключ `SELECTEL_S3_QUARANTINE_READ_ACCESS_KEY` должен иметь только:
- `ListBucket`, `GetBucketLocation`, `GetObject` для quarantine;
- никаких прав на Put/Delete;
- никаких прав на attachments и documents.
Если IAM-политика ограничивает основной ключ другими object prefixes, разрешите
служебный префикс `infratest/*` либо запускайте только `--mode readonly`.
## CORS
При `INFRATEST_CHECK_CORS=true` quarantine должен отвечать на preflight по
**vHosted** URL (`<bucket>.<s3_domain>`). У Selectel CORS не работает на
path-style адресации, даже если presigned PUT с сервера проходит.
Требования к правилу CORS на `han-chat-quarantine`:
- бакет с включённой Virtual-Hosted адресацией;
- origin — точное значение `PUBLIC_WEB_URL`, без wildcard;
- method — `PUT` (можно также `GET`, `HEAD`, `POST`);
- headers — минимум `content-type`; wildcard `x-amz-*` в панели Selectel обычно
**не работает**, надёжнее указать `*` или перечислить заголовки явно.
Чтобы временно исключить CORS из диагностики:
```dotenv
INFRATEST_CHECK_CORS=false
```
## Интерпретация результата
- `PASS` — контракт подтверждён реальной операцией;
- `FAIL` — контракт нарушен или ресурс недоступен;
- `SKIP` — проверка отключена режимом или настройкой.
При `FAIL` сначала проверьте сетевые ACL ВМ, CA/hostname PostgreSQL, GRANT и
`search_path`, затем IAM/CORS бакетов. После аварийного прерывания процесса можно
найти остатки только под префиксом `infratest/`; удалять другие ключи не требуется.
## Локальные unit-тесты
Они не обращаются к PostgreSQL или S3:
```bash
python3 -m unittest -v test_infratest.py
```