# Инфраструктурный тест HAN Chat Автономный тест запускается непосредственно на ВМ и проверяет managed PostgreSQL и три приватных Selectel S3-бакета в соответствии с контрактами HAN Chat. Для запуска приложение и Docker Compose не требуются. Тест не создаёт постоянных данных: - PostgreSQL DDL/DML выполняются в транзакции и завершаются `ROLLBACK`; - S3-объекты создаются только под уникальным префиксом `infratest//`; - все 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 (`.`). У 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 ```