Поменял настройки актуальности clamav

This commit is contained in:
mi
2026-08-14 10:39:47 +03:00
parent 99605b1c77
commit 9eb8b2bc6e
11 changed files with 196 additions and 16 deletions
@@ -255,6 +255,9 @@ security-профили:
- работоспособность updater подтверждается состоянием `Up`, отсутствием
restart loop и отдельным контролем возраста/signature version, а не
искусственным container healthcheck.
- Архитектурная верхняя граница допустимого возраста signatures — `720` часов
(30 дней); активный seed-порог `max_signature_age_hours``240` часов
(10 дней), то есть строже предельного значения.
Смена digest ClamAV требует повторной проверки entrypoint, UID/GID, writable
paths, `clamd` health и фактического обновления signatures. Нельзя менять
+1 -1
View File
@@ -199,7 +199,7 @@ worker.lease_seconds=90
## Service-owned настройки `message-safety`
Runtime policy хранится в версионированной `message_safety.config_versions`, а не в `.env` и не в `han_app.app_settings`. Сюда входят task lease/deadline/attempts, internal rate/pending limits, retention/cache TTL, URL/DNS pipeline limits, ClamAV policy timeout/signature age и enabled file MIME/size policy. Полный schema/seed/activation contract — module-05 §10.1 и §15.
Runtime policy хранится в версионированной `message_safety.config_versions`, а не в `.env` и не в `han_app.app_settings`. Сюда входят task lease/deadline/attempts, internal rate/pending limits, retention/cache TTL, URL/DNS pipeline limits, ClamAV policy timeout/signature age и enabled file MIME/size policy. Для ClamAV schema допускает возраст сигнатур не более `720` часов (30 дней), seed `max_signature_age_hours` равен `240` часам (10 дней). Полный schema/seed/activation contract — module-05 §10.1 и §15.
`han_app.app_settings:chat.attachments.*` остаётся бизнес-настройкой api-backend. Message Safety не получает cross-schema read к `han_app`; файл допускается только при пересечении business allow-list, active safety policy и immutable detector manifest. Active policy может сузить manifest, но не добавить parser и не увеличить hard limit.
@@ -479,7 +479,9 @@ certificate/key проверяются preflight.
не превращала успешный one-shot exit в download loop/rate limit;
- унаследованный healthcheck, проверяющий отсутствующий в updater-контейнере
daemon, отключается; updater контролируется по `Up`, restart count, логам и
возрасту сигнатур.
возрасту сигнатур;
- security policy разрешает настроить порог возраста не выше `720` часов
(30 дней); production-like seed использует более строгие `240` часов.
Ошибки `read-only file system` устраняются точечным writable mount. Запрещено
лечить их глобальным `read_only: false`, root, `privileged` или broad
+3 -4
View File
@@ -75,16 +75,15 @@ Host signoz-private
IdentityFile C:\Users\MI\.ssh\hansel-private
ProxyJump han-jump
```
Затем ssh signoz-ui -N
(устаревшее:
На рабочем компьютере откройте туннель до SigNoz через HAN_CHAT:
```powershell
ssh -L 8080:127.0.0.1:8080 signoz-private -N
```
Пока есть доступ снаружи, можно проще:
ssh -i C:\Users\MI\.ssh\hansel-private -L 8080:127.0.0.1:8080 root@135.106.166.7 -N
)
Маршрут SSH: Windows → публичный адрес HAN_CHAT → `192.168.0.5:22`.
Назначение `127.0.0.1:8080` в `-L` открывает конечная VM SigNoz, а не
HAN_CHAT.
@@ -504,6 +504,36 @@ deployment/preflight.sh
новый монотонный номер и отдельные значения `--actor`/`--approved-by`; повторно
активировать старую версию нельзя. Alembic downgrade запрещён.
При обновлении ClamAV policy образ Message Safety должен содержать согласованные
seed и schema: seed `max_signature_age_hours=240`, schema maximum `720`
(30 дней). После обновления immutable image digest создайте новую config
version; существующую active version не редактируйте и не активируйте повторно:
```sh
NEXT_VERSION='<СЛЕДУЮЩИЙ_МОНОТОННЫЙ_НОМЕР>'
/usr/local/sbin/han-vm2-compose --profile ops pull \
message-safety-migrate
/usr/local/sbin/han-vm2-compose --profile ops run --rm \
--entrypoint message-safety-config message-safety-migrate \
validate /app/app/artifacts/seed-config.yaml
/usr/local/sbin/han-vm2-compose --profile ops run --rm \
--entrypoint message-safety-config message-safety-migrate \
create /app/app/artifacts/seed-config.yaml \
--version "$NEXT_VERSION" --actor '<OPERATOR>'
/usr/local/sbin/han-vm2-compose --profile ops run --rm \
--entrypoint message-safety-config message-safety-migrate \
activate --version "$NEXT_VERSION" --approved-by '<APPROVER>'
/usr/local/sbin/han-vm2-compose up -d --no-deps --force-recreate \
message-safety-api message-safety-worker
/usr/local/sbin/han-vm2-compose ps \
message-safety-api message-safety-worker clamd freshclam
unset NEXT_VERSION
```
Старый image, schema которого ограничивает поле значением `168`, нельзя
оставлять после активации значения `240`: сначала обновите
`MESSAGE_SAFETY_IMAGE` на новый digest и проверьте `config --quiet`.
### Gate 4 — конфигурация nginx до запуска
После выпуска public TLS в `/etc/letsencrypt` и материализации internal TLS
@@ -819,3 +849,69 @@ han-message-safety-mode mock --text-free false --file-free false
задокументируйте минимальные writable пути для сигнатур/runtime и
компенсируйте сетевыми и ресурсными лимитами. Egress к signature-CDN
получает только `freshclam`; `clamd` — нет.
# Gate 9 завершает техническую приёмку VM2, но не означает production cutover сервисов.
Дальнейший порядок:
1. Проверить автозапуск:
```sh
systemctl is-enabled \
docker.service \
han-chat-vm2-docker-firewall.service \
han-secrets-vm2.service \
han-processing.service \
certbot.timer
systemctl is-active \
docker.service \
han-chat-vm2-docker-firewall.service \
han-processing.service \
certbot.timer
/usr/local/sbin/han-vm2-compose ps
```
2. Провести reboot-gate. Только после проверки отдельного входа `admin` и доступа к консоли Selectel:
```sh
systemctl reboot
```
После переподключения повторить команды выше и кратко Gate 68: HTTPS, firewall, private Safety API.
3. Зафиксировать итог релиза:
```sh
/usr/local/sbin/han-vm2-compose config --images
/usr/local/sbin/han-vm2-compose ps
systemctl list-timers certbot.timer
journalctl --no-pager -u han-processing.service -u han-secrets-vm2.service
```
Сохранить версии образов, дату приёмки и результаты gates без значений секретов.
4. Настроить эксплуатационный мониторинг:
- container unhealthy/restart/OOM;
- срок TLS;
- возраст ClamAV signatures;
- OTEL queue/export errors;
- disk/RAM;
- активный MOCK mode;
- недоступность private Safety API.
5. Далее — отдельный controlled cutover Message Safety на VM1: private URL, internal CA, service token, API integration, rollback rehearsal и функциональные проверки.
6. `bitrix-sync` пока оставить:
```dotenv
BITRIX_SYNC_ENABLED=false
BITRIX_SYNC_MODE=disabled
```
Public allow-list — только `deny all;`. Включать Bitrix можно лишь после выполнения gates `module-07`: поля портала, webhooks, migrations, grants, backfill/watermark и rollback rehearsal.
Таким образом, ближайший шаг сейчас — reboot-gate и фиксация приёмки VM2. Затем переход к интеграции VM1, а не немедленное включение Bitrix.
@@ -50,7 +50,7 @@
},
"clamav": {
"type": "object", "additionalProperties": false, "required": ["scan_timeout_sec", "max_signature_age_hours"],
"properties": {"scan_timeout_sec": {"type": "integer", "minimum": 1, "maximum": 120}, "max_signature_age_hours": {"type": "integer", "minimum": 1, "maximum": 168}}
"properties": {"scan_timeout_sec": {"type": "integer", "minimum": 1, "maximum": 120}, "max_signature_age_hours": {"type": "integer", "minimum": 1, "maximum": 720}}
},
"file_policy": {
"type": "object", "additionalProperties": false, "required": ["enabled_mime_types", "max_size_bytes"],
@@ -23,7 +23,7 @@ link:
pipeline_timeout_sec: 2
clamav:
scan_timeout_sec: 45
max_signature_age_hours: 24
max_signature_age_hours: 240
file_policy:
enabled_mime_types:
[image/jpeg, image/png, image/webp, image/heic, image/heif, application/pdf]
@@ -7,6 +7,7 @@ from pathlib import Path
import pytest
import yaml
from jsonschema import ValidationError
from app.config import validate_config
from app.db import Base
@@ -34,6 +35,16 @@ def test_config_cross_field_and_manifest_subset(artifacts: Path) -> None:
validate_config(bad, artifacts)
def test_clamav_signature_age_policy_bounds(artifacts: Path) -> None:
document = seed(artifacts)
assert document["clamav"]["max_signature_age_hours"] == 240
document["clamav"]["max_signature_age_hours"] = 720
validate_config(document, artifacts)
document["clamav"]["max_signature_age_hours"] = 721
with pytest.raises(ValidationError):
validate_config(document, artifacts)
def test_normative_tables_are_in_service_schema() -> None:
expected = {
"safety_requests",
+4 -2
View File
@@ -405,6 +405,8 @@ MVP использует отдельный `clamd` sidecar/service в private D
- порт не публикуется наружу;
- сигнатуры обновляет `freshclam`;
- readiness требует daemon PING и допустимый возраст signatures;
- `max_signature_age_hours` допускается в диапазоне `1..720` часов
(не более 30 дней); seed policy использует `240` часов (10 дней);
- limits согласованы с максимальным размером файла;
- контейнер non-root, read-only root filesystem где возможно, отдельный writable volume только для signatures/runtime;
- worker не передаёт в clamd object key, имя пользователя или иные PII.
@@ -820,7 +822,7 @@ link:
pipeline_timeout_sec: 2
clamav:
scan_timeout_sec: 45
max_signature_age_hours: 24
max_signature_age_hours: 240
file_policy:
enabled_mime_types:
- image/jpeg
@@ -832,7 +834,7 @@ file_policy:
max_size_bytes: 5242880
```
JSON Schema задаёт типы/ranges и cross-field constraints: `heartbeat_sec < lease_sec < execution_deadline_sec`, scan/pipeline timeout не больше execution deadline, TTL/retention положительны. `enabled_mime_types` — непустое уникальное подмножество detector manifest; `max_size_bytes` и последующие format overrides не превышают hard limits manifest. Referenced rules/detector artifacts обязаны быть доступны и пройти hash/signature verification до activation.
JSON Schema задаёт типы/ranges и cross-field constraints: `heartbeat_sec < lease_sec < execution_deadline_sec`, scan/pipeline timeout не больше execution deadline, TTL/retention положительны, `max_signature_age_hours` не превышает `720` часов (30 дней). `enabled_mime_types` — непустое уникальное подмножество detector manifest; `max_size_bytes` и последующие format overrides не превышают hard limits manifest. Referenced rules/detector artifacts обязаны быть доступны и пройти hash/signature verification до activation.
### 15.2. Env и secrets Message Safety на ВМ2
+1 -1
View File
@@ -1318,7 +1318,7 @@ Root устанавливает helper и `/etc/sudoers.d/deploy-message-safety-
Перед включением operator фиксирует incident/change ID и выбранные text/file policies; после команды проверяет `processing_mode=mock`, forced canaries, отсутствие `202`, metric/active alert и audit actor. Ранее принятые standard tasks сохраняют mode и завершаются без переклассификации; только новые requests используют MOCK. Автоматического timeout нет: mode действует без ограничения по времени до явного `standard`. Поэтому перед закрытием incident обязателен возврат в standard, проверка normal capabilities и text/link/EICAR canary. File, разрешённый в MOCK, маркируется `scan_status=bypassed`, а не `clean`.
`freshclam` имеет controlled egress только к утверждённому signature CDN. Max signature age 24 ч; stale/failed update выключает только `files` и поднимает alert. Новая база проходит integrity/load/EICAR canary и atomic activate/reload; при regression возвращается последняя валидная база.
`freshclam` имеет controlled egress только к утверждённому signature CDN. Seed `max_signature_age_hours` равен `240` ч (10 дней), а schema запрещает значения выше `720` ч (30 дней); stale/failed update выключает только `files` и поднимает alert. Новая база проходит integrity/load/EICAR canary и atomic activate/reload; при regression возвращается последняя валидная база.
Initial ВМ2: 4 vCPU/8 GiB/80 GiB, resource/PID limits и backpressure. Workers масштабируются первыми по queue depth, `clamd` — scan lanes. ВМ3/scale-out инициируются при sustained CPU/RAM >70%, queue age >30 с, провале module-05 performance gates, contention `bitrix-sync` или независимом release cadence.
+72 -5
View File
@@ -47,11 +47,11 @@ docker push $REGISTRY/han-bitrix-sync:1.0.3
docker image inspect $REGISTRY/han-bitrix-sync:1.0.3 --format '{{index .RepoDigests 0}}'
cd /mnt/c/Users/MI/Documents/Assistent/HAN_chat_specification/codebase/services/message-safety
docker build -t han-message-safety:1.0.1 .
docker build -t han-message-safety:1.0.2 .
REGISTRY=cr.selcloud.ru/han-images # ваш registry
docker tag han-message-safety:1.0.1 $REGISTRY/han-message-safety:1.0.1
docker push $REGISTRY/han-message-safety:1.0.1
docker image inspect $REGISTRY/han-message-safety:1.0.1 --format '{{index .RepoDigests 0}}'
docker tag han-message-safety:1.0.2 $REGISTRY/han-message-safety:1.0.2
docker push $REGISTRY/han-message-safety:1.0.2
docker image inspect $REGISTRY/han-message-safety:1.0.2 --format '{{index .RepoDigests 0}}'
@@ -890,4 +890,71 @@ docker run --rm --network han-processing_observability \
после успешной проверки нужно удалить
docker rmi ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Проверка финальная
1. Проверить автозапуск:
```sh
systemctl is-enabled \
docker.service \
han-chat-vm2-docker-firewall.service \
han-secrets-vm2.service \
han-processing.service \
certbot.timer
(все enabled)
systemctl is-active \
docker.service \
han-chat-vm2-docker-firewall.service \
han-processing.service \
certbot.timer
(все active)
/usr/local/sbin/han-vm2-compose ps --format "table {{.Service}}\t{{.Status}}\t{{.Ports}}"
```
2. Провести reboot-gate. Только после проверки отдельного входа `admin` и доступа к консоли Selectel:
```sh
systemctl reboot
```
После переподключения повторить команды выше и кратко Gate 68: HTTPS, firewall, private Safety API.
3. Зафиксировать итог релиза:
```sh
/usr/local/sbin/han-vm2-compose config --images
/usr/local/sbin/han-vm2-compose ps
systemctl list-timers certbot.timer
journalctl --no-pager -u han-processing.service -u han-secrets-vm2.service
```
Сохранить версии образов, дату приёмки и результаты gates без значений секретов.
4. Настроить эксплуатационный мониторинг:
- container unhealthy/restart/OOM;
- срок TLS;
- возраст ClamAV signatures;
- OTEL queue/export errors;
- disk/RAM;
- активный MOCK mode;
- недоступность private Safety API.
5. Далее — отдельный controlled cutover Message Safety на VM1: private URL, internal CA, service token, API integration, rollback rehearsal и функциональные проверки.
6. `bitrix-sync` пока оставить:
```dotenv
BITRIX_SYNC_ENABLED=false
BITRIX_SYNC_MODE=disabled
```
Public allow-list — только `deny all;`. Включать Bitrix можно лишь после выполнения gates `module-07`: поля портала, webhooks, migrations, grants, backfill/watermark и rollback rehearsal.
Таким образом, ближайший шаг сейчас — reboot-gate и фиксация приёмки VM2. Затем переход к интеграции VM1, а не немедленное включение Bitrix.