Внедрение KESL на ВМ2 + замена CLAMAV на KESL
This commit is contained in:
@@ -31,7 +31,7 @@ Test-only правила по первому символу, случайные
|
||||
| Safety Service Owner | lifecycle v2, API/data contracts, service-owned config, capacity и cutover sign-off |
|
||||
| Rule Pack Owner | версия rules bundle, corpus, monitor rollout и release notes |
|
||||
| Security Owner | approval `monitor → deny` и config changes, ослабляющих policy; threat model, egress/secrets и risk acceptance |
|
||||
| Operations Owner | VM2, ClamAV signatures, alerts, rollback/reprovision и restore rehearsal |
|
||||
| Operations Owner | VM2, host KESL/broker, антивирусные базы, alerts, rollback/reprovision и restore rehearsal |
|
||||
|
||||
Один человек может выполнять несколько ролей, но для каждого production release роли и approvals должны быть записаны в release checklist.
|
||||
|
||||
@@ -45,7 +45,7 @@ Test-only правила по первому символу, случайные
|
||||
- валидацию file metadata и фактического формата;
|
||||
- чтение файла из S3-quarantine по read-only credentials;
|
||||
- вычисление authoritative SHA-256;
|
||||
- антивирусную проверку файла через ClamAV;
|
||||
- антивирусную проверку файла через root-owned fail-closed broker по Unix socket `/run/han-kesl/scan.sock`; broker вызывает host KESL 12.4 standalone;
|
||||
- выбор sync/async режима;
|
||||
- создание и исполнение async safety tasks;
|
||||
- sticky final verdict, verdict cache и audit в схеме `message_safety`;
|
||||
@@ -78,7 +78,7 @@ Test-only правила по первому символу, случайные
|
||||
| `MOCK=true`, `TEXT_FREE=false`, `FILE_FREE=true` | forced `403 deny` | forced `200 allow` |
|
||||
| `MOCK=true`, `TEXT_FREE=false`, `FILE_FREE=false` | forced `403 deny` | forced `403 deny` |
|
||||
|
||||
При `MOCK=true` не выполняются normalization/rules, URL extraction/DNS, S3 read/checksum/format/ClamAV, verdict caches, task creation и async worker. Service authentication, body-size/JSON/strict DTO validation, idempotency conflict protection, PostgreSQL audit и rate limits остаются обязательными controls.
|
||||
При `MOCK=true` не выполняются normalization/rules, URL extraction/DNS, S3 read/checksum/format/KESL scan, verdict caches, task creation и async worker. Service authentication, body-size/JSON/strict DTO validation, idempotency conflict protection, PostgreSQL audit и rate limits остаются обязательными controls.
|
||||
|
||||
Forced allow использует `rule_id=safety.mock_forced_allow`; forced deny — `rule_id=safety.mock_forced_deny`, `reason_code=message_blocked`. Mock никогда не возвращает `202`. Internal response содержит `processing_mode=mock`; `api-backend` не раскрывает mode/rule клиенту. Mode фиксируется при первом принятии `message_id`: ранее созданный standard task/idempotency result не переклассифицируется и завершается в standard, а новый mock request не создаёт task. Это исключает смену verdict посередине обработки.
|
||||
|
||||
@@ -118,8 +118,8 @@ Rules не заменяют безопасный rendering. Frontend и Bitrix i
|
||||
| Недопустимый размер/MIME | Сверка DTO с allow-list и лимитами | `403 deny` |
|
||||
| Подмена MIME | Magic-byte/content sniffing, сверка declared MIME | `403 deny` |
|
||||
| Подмена содержимого после complete | Version-specific read + ETag + полный SHA-256 | `403 deny` |
|
||||
| Malware | ClamAV scan актуальными сигнатурами | `403 deny` |
|
||||
| Архивная бомба/ресурсное истощение | Лимиты размера, stream scan, ClamAV limits/timeouts | deny при policy hit; error при сбое |
|
||||
| Malware | Host KESL 12.4 scan через fail-closed broker с актуальной базой | `403 deny` |
|
||||
| Архивная бомба/ресурсное истощение | Лимиты размера, bounded staging и KESL/broker limits/timeouts | deny при policy hit; error при сбое |
|
||||
| Polyglot/неоднозначный формат | Строгий формат detector и deny при mismatch/ambiguity | `403 deny` |
|
||||
| Повтор известного файла | Cache по SHA-256 + versions | Sticky cached verdict |
|
||||
|
||||
@@ -179,7 +179,7 @@ flowchart TD
|
||||
task --> worker[File_worker]
|
||||
worker --> objectRead[S3_stream_and_SHA256]
|
||||
objectRead --> formatCheck[Format_validation]
|
||||
formatCheck --> avScan[ClamAV_scan]
|
||||
formatCheck --> avScan[KESL_broker_scan]
|
||||
avScan --> finalVerdict[Persist_sticky_verdict]
|
||||
finalVerdict --> taskGet[GET_task_200_or_403]
|
||||
```
|
||||
@@ -255,7 +255,7 @@ Rules поставляются как статический read-only bundle `a
|
||||
| `file.encrypted_content` | file_content | deny | encrypted/password-protected container |
|
||||
| `file.active_content` | file_content | deny | PDF JavaScript/OpenAction/Launch/XFA/embedded |
|
||||
| `file.parser_limit` | file_content | deny | parser resource/decompression/object limit |
|
||||
| `file.malware_detected` | file_content | deny | ClamAV FOUND |
|
||||
| `file.malware_detected` | file_content | deny | KESL сообщает infected |
|
||||
|
||||
Все domain deny используют `reason_code=message_blocked`; детализация остаётся во внутреннем `rule_id`. DTO/schema/authorization errors не получают `rule_id`.
|
||||
|
||||
@@ -389,29 +389,28 @@ Worker:
|
||||
5. определяет реальный формат по содержимому;
|
||||
6. сверяет detector result с declared MIME;
|
||||
7. запрещает encrypted/password-protected и неподдерживаемые containers;
|
||||
8. передаёт поток в `clamd` через internal network;
|
||||
8. передаёт bounded file broker-у через Unix socket `/run/han-kesl/scan.sock`; root-owned broker вызывает `kesl-control --scan-file --action Inform`;
|
||||
9. сохраняет sticky final verdict и audit;
|
||||
10. записывает cache только для terminal результата;
|
||||
11. завершает lease.
|
||||
|
||||
Чистый файл получает allow только если успешно завершились **все** обязательные проверки. `ClamAV FOUND`, checksum mismatch, format mismatch, unsupported encrypted content или policy limit дают deny с отдельным `rule_id`.
|
||||
Чистый файл получает allow только если успешно завершились **все** обязательные проверки и broker однозначно вернул `clean`. KESL `infected`, checksum mismatch, format mismatch, unsupported encrypted content или policy limit дают deny с отдельным `rule_id`.
|
||||
|
||||
ClamAV timeout, protocol error, недоступность S3/DB/Redis или потеря lease не являются deny. Task остаётся pending/retryable в пределах deadline; после исчерпания retry получает terminal infrastructure failure, который API отдаёт как `503`, а не `403`.
|
||||
KESL/broker timeout, ошибка запуска или разбора результата `kesl-control`, stale database, недоступность S3/DB/Redis или потеря lease не являются ни allow, ни domain deny. Task остаётся pending/retryable в пределах deadline; после исчерпания retry получает terminal infrastructure failure, который API отдаёт как `503`, а не `403`.
|
||||
|
||||
### 7.3. AV runtime
|
||||
### 7.3. KESL runtime и broker
|
||||
|
||||
MVP использует отдельный `clamd` sidecar/service в private Docker network:
|
||||
MVP использует установленный на VM2 host KESL 12.4 standalone и отдельный custom integration broker:
|
||||
|
||||
- порт не публикуется наружу;
|
||||
- сигнатуры обновляет `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.
|
||||
- KESL и broker не входят в Compose; `clamd`/`freshclam`, их volumes, healthchecks и egress из Compose удалены;
|
||||
- root-owned broker слушает только Unix socket `/run/han-kesl/scan.sock`; ожидаемые права socket — `root:han-message-safety 0660`, socket монтируется в worker, TCP listener отсутствует;
|
||||
- broker fail-closed: принимает только bounded scan request, не принимает произвольные command/arguments/path traversal и вызывает фиксированный `kesl-control --scan-file --action Inform`;
|
||||
- `clean` разрешает продолжить allow-ветку, `infected` даёт domain deny; неизвестный формат/exit code, timeout, недоступность KESL и stale database дают retry, затем `503`;
|
||||
- readiness проверяет broker, KESL version/database date и допустимый возраст базы; `max_signature_age_hours` допускается в диапазоне `1..720`, seed — `240`;
|
||||
- KESL обновляет базы на host ежечасно по операторскому KESL runbook; egress к источникам обновления принадлежит host KESL, не Compose;
|
||||
- worker не передаёт object key, имя пользователя или иные PII; временный файл и broker state очищаются по завершении.
|
||||
|
||||
Недоступность AV переводит capability `files` в `unavailable` и запрещает новые file allow, но оставляет core/text readiness доступной.
|
||||
Broker — custom integration: точный формат и exit semantics `kesl-control`, безопасная передача файла, очистка и throughput обязаны пройти gates на target VM2 с фактическим KESL 12.4. Недоступность scanner переводит capability `files` в `unavailable` и запрещает новые file allow, но оставляет core/text readiness доступной.
|
||||
|
||||
### 7.4. Исполнимая матрица форматов
|
||||
|
||||
@@ -425,7 +424,7 @@ MVP использует отдельный `clamd` sidecar/service в private D
|
||||
|
||||
Parser выполняется с CPU/memory/wall-time limits в отдельном sandboxed subprocess. Detector ambiguity, resource limit и disagreement detector↔declared MIME дают соответствующий `403 rule_id`. Immutable `detector-manifest.json` содержит bundle version, package/native library versions, supported MIME и hard limits; `detector_version` вычисляется как hash manifest, а не задаётся env. Active config ссылается на доступные `rules_version`/`detector_version` и может только сузить MIME/limits. Изменение manifest или active file policy инвалидирует file verdict cache через versioned cache key.
|
||||
|
||||
`scanner_engine=clamav`. `signatures_version` формируется из ClamAV engine version и CVD/CLD metadata/hash после успешного `freshclam` activate/reload; значение входит в verdict/cache/audit и readiness.
|
||||
`scanner_engine=kesl`. `signatures_version` — стабильный hash канонической строки из KESL version и database date, полученных после успешной проверки broker/KESL; значение входит в verdict/cache/audit и readiness.
|
||||
|
||||
## 8. Internal API
|
||||
|
||||
@@ -697,14 +696,14 @@ Public `422` содержит стандартный error envelope без inter
|
||||
- strict DTO, body/text/URL/file limits и запрет unknown fields;
|
||||
- read-only S3-quarantine access, без list/write/delete;
|
||||
- **запрет HTTP fetch/render/redirect follow** к пользовательским URL; link pipeline использует только доверенный DNS;
|
||||
- egress по назначению: worker → DNS/S3/PostgreSQL, app → local Redis/OTLP/clamd; внешнего reputation API нет;
|
||||
- egress по назначению: worker → DNS/S3/PostgreSQL, app → local Redis/OTLP; KESL update egress принадлежит host и ограничен операторским KESL runbook; внешнего reputation API нет;
|
||||
- parameterized SQL и least-privilege DB role только на schema `message_safety`;
|
||||
- Redis Safety ACL только prefixes `han:safety:*`;
|
||||
- dependency pinning, SBOM/image scanning;
|
||||
- non-root, read-only root fs, tmpfs `/tmp`, dropped capabilities, no-new-privileges;
|
||||
- OpenAPI UI выключен в production;
|
||||
- безопасные generic errors без stack/internal addresses;
|
||||
- правила и AV signatures обновляются только trusted deployment process.
|
||||
- rules и KESL database обновляются только trusted deployment/operator process.
|
||||
- MOCK не имеет runtime/public API; mode file root-owned, а `deploy` имеет sudo только на argument-validating helper и approved restart.
|
||||
|
||||
## 13. Observability и privacy
|
||||
@@ -726,10 +725,10 @@ Metrics:
|
||||
- `message_safety_mock_enabled` gauge и forced outcomes по `text|file`/`allow|deny`;
|
||||
- rule hits по low-cardinality `rule_id`;
|
||||
- task queue/age/attempts/lease conflicts/timeouts;
|
||||
- scan latency/bytes buckets/AV outcome;
|
||||
- scan latency/bytes buckets/KESL outcome;
|
||||
- signatures age/version info;
|
||||
- cache hit/miss;
|
||||
- PostgreSQL/Redis/S3/ClamAV latency and errors;
|
||||
- PostgreSQL/Redis/S3/KESL broker latency and errors;
|
||||
- active/used `config_version`, activation result и config refresh age;
|
||||
- auth rejects/rate limit/readiness.
|
||||
|
||||
@@ -748,7 +747,7 @@ Telemetry collector unavailable не влияет на safety verdict и readine
|
||||
- Redis Safety status как degraded accelerator, не core gate;
|
||||
- worker heartbeat/lease processing;
|
||||
- S3-quarantine Head/Get read permission на безопасный canary object;
|
||||
- ClamAV PING и допустимый возраст signatures;
|
||||
- broker socket, KESL status и допустимый возраст database;
|
||||
- trusted DNS resolver для `links`;
|
||||
- OpenAPI/runtime parity проверяется на startup/CI, а не сетевым probe каждого ready request.
|
||||
|
||||
@@ -777,7 +776,7 @@ Telemetry collector unavailable не влияет на safety verdict и readine
|
||||
}
|
||||
```
|
||||
|
||||
Core `HTTP 503 status=not_ready` используется только для invalid config/rules/PostgreSQL. Потеря worker heartbeat делает `worker=unavailable` и `files=unavailable`, но сохраняет text/links; ClamAV/S3 down выключает только `files`; DNS down — только `links`; Redis down прогревается из PostgreSQL и не выключает core. Каждый POST повторно проверяет требуемую capability и остаётся источником correctness; api-backend может кэшировать health snapshot не дольше 5 с только для fast-fail. Через private nginx ВМ2 endpoint доступен как exact `GET /internal/safety/status`, который проксируется в `/health/ready`; прямой `/health/ready` остаётся локальным container health. Private alias ограничен SG/source allow-list, не требует service token и не раскрывает credentials/hostnames.
|
||||
Core `HTTP 503 status=not_ready` используется только для invalid config/rules/PostgreSQL. Потеря worker heartbeat делает `worker=unavailable` и `files=unavailable`, но сохраняет text/links; KESL broker/S3 down или stale KESL database выключает только `files`; DNS down — только `links`; Redis down прогревается из PostgreSQL и не выключает core. Каждый POST повторно проверяет требуемую capability и остаётся источником correctness; api-backend может кэшировать health snapshot не дольше 5 с только для fast-fail. Через private nginx ВМ2 endpoint доступен как exact `GET /internal/safety/status`, который проксируется в `/health/ready`; прямой `/health/ready` остаётся локальным container health. Private alias ограничен SG/source allow-list, не требует service token и не раскрывает credentials/hostnames.
|
||||
|
||||
В MOCK health всегда явно возвращает `processing_mode=mock`, `mock_policy.text=allow|deny`, `mock_policy.file=allow|deny` и `status=degraded`, даже если forced responses доступны. Normal pipeline dependencies показываются как `bypassed`, не `ok`. Active alert не закрывается до возврата в `standard`.
|
||||
|
||||
@@ -793,7 +792,7 @@ Core `HTTP 503 status=not_ready` используется только для in
|
||||
### 15.1. Seed active config в `message_safety`
|
||||
|
||||
```yaml
|
||||
schema_version: 1
|
||||
schema_version: 2
|
||||
rules_bundle_ref: rules-2026-01-01
|
||||
detector_manifest_ref: detector-2026-08-03
|
||||
task:
|
||||
@@ -820,7 +819,7 @@ link:
|
||||
url_max_length: 2048
|
||||
dns_lookup_timeout_sec: 1
|
||||
pipeline_timeout_sec: 2
|
||||
clamav:
|
||||
kesl:
|
||||
scan_timeout_sec: 45
|
||||
max_signature_age_hours: 240
|
||||
file_policy:
|
||||
@@ -850,8 +849,7 @@ activation. Image-only rollback после активации несовмест
|
||||
APP_ENV=production-like
|
||||
MESSAGE_SAFETY_WORKER_CONCURRENCY=5
|
||||
MESSAGE_SAFETY_DNS_RESOLVERS=<VPC-resolver-IP>
|
||||
MESSAGE_SAFETY_CLAMAV_HOST=clamd
|
||||
MESSAGE_SAFETY_CLAMAV_PORT=3310
|
||||
MESSAGE_SAFETY_KESL_SOCKET=/run/han-kesl/scan.sock
|
||||
SELECTEL_S3_ENDPOINT_URL=https://s3.storage.selcloud.ru
|
||||
SELECTEL_S3_BUCKET_QUARANTINE=han-chat-quarantine
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
|
||||
@@ -875,7 +873,7 @@ Availability SLO для MVP не утверждается. До cutover обяз
|
||||
| File | sustained 2 checks/s, 5 worker slots | среднее processing ≤2.5 с, p95 final ≤60 с, p99/public wait ≤300 с |
|
||||
| Pending/backpressure | до 100 active tasks | queue age p95 ≤5 с; при 100 новый file POST получает retryable `503` без task |
|
||||
|
||||
File corpus: 70% JPEG/PNG/WebP до 1 MiB, 20% PDF/HEIC до 2 MiB, 10% boundary samples до 5 MiB; включает clean, EICAR, malformed, encrypted и parser-limit cases. Если 5 slots не подтверждают 2 file/s и среднее ≤2.5 с, Safety Service Owner до cutover увеличивает slots/CPU/scan lanes и повторяет тест.
|
||||
File corpus: 70% JPEG/PNG/WebP до 1 MiB, 20% PDF/HEIC до 2 MiB, 10% boundary samples до 5 MiB; включает clean, EICAR, malformed, encrypted и parser-limit cases. Если 5 slots не подтверждают 2 file/s и среднее ≤2.5 с, Safety Service Owner до cutover корректирует slots/CPU/broker concurrency в пределах подтверждённой KESL capacity и повторяет target-VM test.
|
||||
|
||||
Превышение text/file token bucket → `429 rate_limit_exceeded` + `Retry-After`. Pending считается authoritative запросом PostgreSQL; Redis используется как быстрый счётчик. При Redis outage rate limiter использует conservative in-process limits, а pending gate остаётся в PostgreSQL.
|
||||
|
||||
@@ -920,7 +918,7 @@ Runtime schema сравнивается с committed artifact contract test. Ter
|
||||
- PostgreSQL claim/lease/fencing concurrency/recovery; Redis cache loss;
|
||||
- pending=100 backpressure, token buckets и 5 worker slots;
|
||||
- S3 versioned read, ETag/version changed/missing/timeout;
|
||||
- ClamAV clean, EICAR, FOUND, timeout, daemon down, stale signatures;
|
||||
- KESL broker clean, EICAR/infected, timeout, scanner down, stale database и неизвестный формат `kesl-control`;
|
||||
- full SHA-256 and size mismatch;
|
||||
- duplicate concurrent request and worker retry;
|
||||
- dependency recovery without changed final verdict.
|
||||
@@ -972,10 +970,10 @@ Runtime schema сравнивается с committed artifact contract test. Ter
|
||||
### 18.2. Definition of Done
|
||||
|
||||
- production v2 `200/202/403` contract реализован без stub divergence;
|
||||
- MOCK 2×2 text/file matrix даёт только sync `200/403`; тест доказывает отсутствие calls к rules/DNS/S3/ClamAV/cache/workers и сохранение auth/DTO/idempotency/audit/rate limits;
|
||||
- MOCK 2×2 text/file matrix даёт только sync `200/403`; тест доказывает отсутствие calls к rules/DNS/S3/KESL broker/cache/workers и сохранение auth/DTO/idempotency/audit/rate limits;
|
||||
- text-rules cache, text rules, link cache и URL pipeline покрывают threat model и false-positive corpus;
|
||||
- fetch/render/redirect follow к пользовательским URL отсутствует по design и тестам;
|
||||
- files проходят metadata, authoritative SHA-256, format detector и ClamAV;
|
||||
- files проходят metadata, authoritative SHA-256, format detector и KESL broker;
|
||||
- final task verdict sticky и durable;
|
||||
- idempotency/concurrency/recovery доказаны тестами;
|
||||
- PG schema `message_safety`, Redis Safety и S3 version-specific read работают по least privilege;
|
||||
@@ -985,13 +983,13 @@ Runtime schema сравнивается с committed artifact contract test. Ter
|
||||
- mock mode сохраняется internal, не раскрывается public; forced file allow получает `scan_status=bypassed`, не `clean`;
|
||||
- public deny использует `safety.chat.blocked` и не раскрывает internal rule;
|
||||
- blocked/failed content не попадает в Bitrix и не promote-ится;
|
||||
- health/readiness и capability-specific POST отражают PG/Redis/S3/workers/ClamAV/DNS/rules;
|
||||
- health/readiness и capability-specific POST отражают PG/Redis/S3/workers/KESL broker/database age/DNS/rules;
|
||||
- performance acceptance §15.4 пройден на target sizing;
|
||||
- immutable/versioned S3 negative tests и conditional promote пройдены;
|
||||
- OpenAPI 3.1 и runtime parity зелёные;
|
||||
- logs/metrics/traces не содержат содержимое сообщений, файлов и secrets;
|
||||
- hardened containers запускаются без public port;
|
||||
- runbook описывает signature update, stale signatures, AV outage, retry и rollback.
|
||||
- runbook описывает hourly KESL update, stale database, broker/KESL outage, retry и rollback.
|
||||
- `deploy` может выполнить все пять exact mode commands, но не читать/писать mode config и не получить Docker/general sudo; helper rollback, persistent MOCK alert и возврат в standard испытаны.
|
||||
|
||||
## 19. Размещение проекта и вынос на отдельную ВМ
|
||||
@@ -1016,7 +1014,7 @@ Stub в `codebase/backend/message-safety/` не является целевой
|
||||
|
||||
### 19.2. Целевая топология
|
||||
|
||||
Message Safety и `bitrix-sync` выносятся **за пределы ВМ HAN_CHAT (ВМ1)** на самостоятельную **ВМ2 Processing** в той же private network/VPC. Цель — снять с ВМ1 ClamAV/file scan, DNS classification, S3 streaming, CRM sync и входящий CRM webhook. Message Safety остаётся private API; Bitrix24 обращается напрямую к отдельному public host nginx ВМ2.
|
||||
Message Safety и `bitrix-sync` выносятся **за пределы ВМ HAN_CHAT (ВМ1)** на самостоятельную **ВМ2 Processing** в той же private network/VPC. Цель — снять с ВМ1 file scan, DNS classification, S3 streaming, CRM sync и входящий CRM webhook. Host KESL 12.4 standalone и broker работают на VM2 вне Compose. Message Safety остаётся private API; Bitrix24 обращается напрямую к отдельному public host nginx ВМ2.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
@@ -1030,7 +1028,7 @@ flowchart LR
|
||||
gateway[VM2_nginx_public_private]
|
||||
safety[message-safety_api_worker]
|
||||
sync[bitrix-sync]
|
||||
clamav[clamd]
|
||||
kesl[KESL_12_4_and_broker]
|
||||
redis2[Redis_Safety]
|
||||
collector[otel-collector]
|
||||
end
|
||||
@@ -1046,13 +1044,13 @@ flowchart LR
|
||||
safety --> redis2
|
||||
safety --> managedPg
|
||||
safety --> s3q
|
||||
safety --> clamav
|
||||
safety -->|"Unix socket"| kesl
|
||||
sync --> managedPg
|
||||
sync --> bitrix
|
||||
collector --> signoz
|
||||
```
|
||||
|
||||
На ВМ2 один root Compose включает собственный nginx с public webhook `443` и private `8443`, `message-safety` API/worker, `clamd`/`freshclam`, `bitrix-sync`, Redis Safety и local OTEL Collector. Managed PostgreSQL и S3 остаются вне VM. Внешнего URL reputation provider нет.
|
||||
На ВМ2 один root Compose включает собственный nginx с public webhook `443` и private `8443`, `message-safety` API/worker, `bitrix-sync`, Redis Safety и local OTEL Collector. `clamd`/`freshclam` в Compose отсутствуют; host KESL 12.4 standalone и root-owned broker управляются отдельно. Managed PostgreSQL и S3 остаются вне VM. Внешнего URL reputation provider нет.
|
||||
|
||||
### 19.3. Исключение из docker compose HAN_CHAT
|
||||
|
||||
@@ -1079,7 +1077,7 @@ flowchart LR
|
||||
| `arch-03` | один Compose ВМ1 | один root Compose на каждой VM |
|
||||
| `arch-04` | local Docker URLs | remote HTTPS URL ВМ1; service-specific env/secrets ВМ2 |
|
||||
| CI/CD | build из backend tree | отдельный pipeline artifact `codebase/message-safety` |
|
||||
| Security groups | intra-docker network | internet→nginx ВМ2:80/443 с exact route policy; ВМ1→ВМ2:8443; ВМ2→PG/S3/DNS/Bitrix/SigNoz/signature CDN по назначению |
|
||||
| Security groups | intra-docker network | internet→nginx ВМ2:80/443 с exact route policy; ВМ1→ВМ2:8443; containers→PG/S3/DNS/Bitrix/SigNoz, host KESL→approved update sources по назначению |
|
||||
|
||||
Схема **`han_app` не получает новых таблиц** для remote safety: orchestration и recovery по-прежнему владеет `api-backend`. Меняется только сетевой адрес internal API и deployment boundary.
|
||||
|
||||
@@ -1087,7 +1085,7 @@ flowchart LR
|
||||
|
||||
- отдельный public IP/host nginx ВМ2 допускает только ACME/redirect policy на `80` и два exact CRM webhook на `443`; public Safety, generic `/internal/*`, admin и health запрещены;
|
||||
- inbound: private TCP 8443 только с SG ВМ1/ops; server-auth TLS internal CA + service token;
|
||||
- outbound по container identity: worker→PostgreSQL/S3/DNS; `freshclam`→signature CDN; `bitrix-sync`→Bitrix24; collector→SigNoz;
|
||||
- outbound по identity: worker→PostgreSQL/S3/DNS; `bitrix-sync`→Bitrix24; collector→SigNoz; host KESL→approved update sources по операторскому runbook;
|
||||
- capability health Safety доступен api-backend и ops как exact `/internal/safety/status` на private `8443`; container `/health/live` и `/health/ready` наружу не публикуются;
|
||||
- при недоступности ВМ2 `api-backend` возвращает `503 dependency_unavailable`, не отправляет сообщения в Bitrix.
|
||||
|
||||
@@ -1102,7 +1100,7 @@ flowchart LR
|
||||
3. **Text/rules** — normalization, versioned bundle/schema, monitor corpus и hard active-content deny.
|
||||
4. **URL policy** — parser/IDNA/IP/DNS, cache split, NXDOMAIN monitor и запрет fetch.
|
||||
5. **File/S3** — immutable version precondition, authoritative checksum, detector manifest и hard matrix.
|
||||
6. **ClamAV** — clamd streaming, freshclam activate/rollback/signature age и EICAR tests.
|
||||
6. **KESL broker** — host KESL 12.4 standalone, root-owned fail-closed Unix-socket broker, hourly update/database age и EICAR tests; формат `kesl-control` и throughput проверяются на target VM.
|
||||
7. **api-backend integration** — v2 adapter, Location polling, M8/company replica/mnemonic, conditional promote.
|
||||
8. **VM2/observability/MOCK** — root Compose, internal nginx/TLS, egress, local collector, root-owned five-command mode helper, persistent alert и dashboards.
|
||||
9. **Acceptance** — contract/security/failure/load tests §15–18 и S3 negative gate.
|
||||
|
||||
Reference in New Issue
Block a user