Внедрение KESL на ВМ2 + замена CLAMAV на KESL
This commit is contained in:
@@ -64,7 +64,6 @@ processing/
|
||||
nginx-internal/docker-compose.yml
|
||||
message-safety/docker-compose.yml
|
||||
bitrix-sync/docker-compose.yml
|
||||
clamav/docker-compose.yml
|
||||
redis/docker-compose.yml
|
||||
observability/docker-compose.yml
|
||||
```
|
||||
@@ -93,7 +92,7 @@ volumes:
|
||||
redis-data:
|
||||
```
|
||||
|
||||
Root Compose ВМ2 включает собственный nginx с public/private server blocks, Message Safety API/worker, `clamd`/`freshclam`, `bitrix-sync`, Redis Safety и локальный OTEL Collector. Секреты, сети и volumes двух projects не общие.
|
||||
Root Compose ВМ2 включает собственный nginx с public/private server blocks, Message Safety API/worker, `bitrix-sync`, Redis Safety и локальный OTEL Collector. `clamd`/`freshclam` удалены из Compose; KESL 12.4 standalone и root-owned fail-closed broker работают на host VM2. Секреты, сети и volumes двух projects не общие.
|
||||
|
||||
### Правила для сервисных compose-файлов
|
||||
|
||||
@@ -254,6 +253,7 @@ Python FastAPI backend.
|
||||
- runtime role читает immutable active `message_safety.config_versions`; создавать/активировать config может только отдельный migration/config-admin job;
|
||||
- использует локальный Redis Safety только для hot cache/rate/wakeup; PostgreSQL владеет task queue/leases;
|
||||
- запускает async workers для file scan из S3-quarantine;
|
||||
- worker монтирует только Unix socket `/run/han-kesl/scan.sock` root-owned broker; KESL и `kesl-control` остаются на host, TCP scanner port отсутствует;
|
||||
- API container получает read-only
|
||||
`/etc/han-chat/message-safety-mode.env` с host contract
|
||||
`root:han-message-safety 0640` и GID `10001`; менять его и перезапускать
|
||||
@@ -262,29 +262,26 @@ Python FastAPI backend.
|
||||
- экспортирует traces/logs в `otel-collector`;
|
||||
- таймауты: POST check 5 s, GET task 2 s, file scan 60 s (см. [`arch-04-settings-and-content.md`](arch-04-settings-and-content.md), переменные `MESSAGE_SAFETY_*`).
|
||||
|
||||
### ClamAV на ВМ2
|
||||
### Host KESL и broker на ВМ2
|
||||
|
||||
`clamd` и `freshclam` используют один immutable image digest, но разные
|
||||
security-профили:
|
||||
KESL 12.4 работает standalone на host и не является Compose service. Отдельный
|
||||
root-owned custom broker слушает только `/run/han-kesl/scan.sock` и вызывает
|
||||
фиксированный `kesl-control --scan-file --action Inform`.
|
||||
|
||||
- оба запускаются через vendor `init-unprivileged`, а не root entrypoint;
|
||||
- `clamd` читает volume signatures read-only, не подключён к signature CDN и
|
||||
имеет healthcheck daemon socket;
|
||||
- `freshclam` один пишет в signatures и имеет только разрешённый egress к CDN;
|
||||
- `/run/clamav` — отдельный runtime volume, `/var/log/clamav` и `/tmp` —
|
||||
ограниченные tmpfs с UID/GID ClamAV;
|
||||
- `freshclam` работает как foreground daemon с заданным interval; inherited
|
||||
healthcheck `clamd` отключён, потому что updater не поднимает daemon socket;
|
||||
- работоспособность updater подтверждается состоянием `Up`, отсутствием
|
||||
restart loop и отдельным контролем возраста/signature version, а не
|
||||
искусственным container healthcheck.
|
||||
- Архитектурная верхняя граница допустимого возраста signatures — `720` часов
|
||||
(30 дней); активный seed-порог `max_signature_age_hours` — `240` часов
|
||||
(10 дней), то есть строже предельного значения.
|
||||
- socket монтируется только в Message Safety worker и доступен выделенной
|
||||
группе; worker не получает host binary, shell, Docker socket или host root;
|
||||
- broker принимает только bounded scan request и fail-closed сопоставляет
|
||||
`clean → allow`, `infected → deny`, а timeout, stale database, неизвестный
|
||||
output/exit code и недоступность KESL → retry/`503`;
|
||||
- `scanner_engine=kesl`; `signatures_version` — hash KESL version + database
|
||||
date;
|
||||
- KESL обновляет database ежечасно на host; update egress не подключает
|
||||
контейнеры к internet;
|
||||
- schema допускает `max_signature_age_hours` до `720`, seed — `240`.
|
||||
|
||||
Смена digest ClamAV требует повторной проверки entrypoint, UID/GID, writable
|
||||
paths, `clamd` health и фактического обновления signatures. Нельзя менять
|
||||
только tag/digest, считая security contract image неизменным.
|
||||
Формат результата `kesl-control`, socket permissions, cleanup и throughput
|
||||
этой custom integration подтверждаются gates на target VM2 с фактическим KESL
|
||||
12.4; repository-only/Compose health не считается достаточным evidence.
|
||||
|
||||
### bitrix-sync
|
||||
|
||||
@@ -400,9 +397,9 @@ Identity provider. **Обязателен** в compose-контуре с пер
|
||||
|
||||
- ВМ1 `public`: edge nginx, Keycloak proxy и frontend entrypoint.
|
||||
- ВМ1 `backend`: `api-backend`, `bitrix-local-app`, Keycloak, SMS API и Redis DB0/DB1.
|
||||
- ВМ2 `backend`: nginx, Safety API/worker, `bitrix-sync`, `clamd` и Redis Safety.
|
||||
- ВМ2 `backend`: nginx, Safety API/worker, `bitrix-sync` и Redis Safety; broker доступен worker только через host Unix socket.
|
||||
- ВМ1 `egress` подключается только к процессам с назначением: `sms-worker` → i-Digital Direct; Keycloak → SmartCaptcha только при включённом feature flag; `api-backend` → S3 и private PG, а вызов Safety идёт к `processing.internal:8443`; local collector → private SigNoz. `sms-service` без совмещённого worker, `bitrix-local-app` и Redis не получают общий internet egress.
|
||||
- ВМ2 `egress` подключается только к процессам с назначением: `freshclam` → signature CDN; `bitrix-sync` → утверждённый Bitrix portal; Safety worker → S3/PG/DNS; collector → private SigNoz. Общего internet egress у Safety API/clamd/Redis нет.
|
||||
- ВМ2 `egress` подключается только к процессам с назначением: `bitrix-sync` → утверждённый Bitrix portal; Safety worker → S3/PG/DNS; collector → private SigNoz. Общего internet egress у Safety API/Redis нет; KESL update egress задаётся отдельно на host.
|
||||
- `observability` существует отдельно на каждой VM и ведёт в её local collector.
|
||||
|
||||
Базы данных, Redis, OTLP receivers и internal service ports не публикуются. Cross-host calls идут через private network, точные SG и TLS.
|
||||
@@ -412,8 +409,8 @@ Identity provider. **Обязателен** в compose-контуре с пер
|
||||
Минимальные persistent volumes:
|
||||
|
||||
- ВМ1: Redis DB0/DB1 data, local OTEL queue;
|
||||
- ВМ2: Redis Safety data (rebuildable), ClamAV signatures и runtime,
|
||||
internal TLS secrets, local OTEL queue.
|
||||
- ВМ2: Redis Safety data (rebuildable), internal TLS secrets, local OTEL queue.
|
||||
KESL database/runtime и `/run/han-kesl` принадлежат host, не Compose volumes.
|
||||
|
||||
Public TLS и ACME на обеих VM — не named volumes. Root-only ACME state остаётся
|
||||
на host в `/etc/letsencrypt`; root hook атомарно копирует только нужные
|
||||
@@ -561,7 +558,7 @@ WAF не заменяет обязательные лимиты, валидац
|
||||
|
||||
- `nginx`: на веб-домене — `308` с `:80` на HTTPS; на API-домене (если выделен) — `:80` не слушает; `:443` — успешная TLS handshake и ожидаемый route response;
|
||||
- `api-backend`: `/health/live` проверяет процесс; `/health/ready` проверяет PostgreSQL `han_app`, Redis DB0/DB1, JWKS/discovery Keycloak и S3 permissions. Недоступность remote Message Safety отражается как degraded dependency и блокирует только send path, но не readiness read API;
|
||||
- `message-safety`: `/health/ready` возвращает process/core status и capability map `text|links|files|worker`; ClamAV/S3 не выключают text, DNS не выключает text без ссылок, Redis hot cache не является core gate;
|
||||
- `message-safety`: `/health/ready` возвращает process/core status и capability map `text|links|files|worker`; KESL broker/stale database/S3 не выключают text, DNS не выключает text без ссылок, Redis hot cache не является core gate;
|
||||
- `bitrix-sync`: `/health/live` проверяет процесс; `/health/ready` проверяет validated config/secrets, PostgreSQL/grants, worker/limiter state и CRM webhook config; invalid credential/config даёт not-ready, краткая CRM outage — degraded по stale policy; при `BITRIX_SYNC_ENABLED=false` ready возвращает not-ready `sync_disabled`;
|
||||
- `bitrix-local-app`: `/health/live` проверяет процесс; `/health/ready` показывает PostgreSQL, OAuth-токены после установки приложения, connector activation и возможность forward в API при включённом `BITRIX_API_FORWARD_URL`;
|
||||
- `keycloak`: health endpoint Keycloak; readiness — подключение к managed PostgreSQL;
|
||||
@@ -591,8 +588,8 @@ host-side secrets/TLS materialized, controlled migrations и seed заверше
|
||||
|
||||
ВМ2 запускается в порядке:
|
||||
|
||||
1. `redis-safety`, `otel-queue-init`, затем local `otel-collector`;
|
||||
2. `freshclam`, затем `clamd` до состояния healthy;
|
||||
1. operator KESL runbook: KESL 12.4/database update, затем enable/start broker socket и проверка status/permissions;
|
||||
2. `redis-safety`, `otel-queue-init`, затем local `otel-collector`;
|
||||
3. Message Safety API/worker и `bitrix-sync`;
|
||||
4. nginx — последним, после успешного config test;
|
||||
5. private HTTPS ВМ1→ВМ2 и capability health проверяются до cutover.
|
||||
|
||||
Reference in New Issue
Block a user