Введение
В предыдущей статье мы встроили локальную модель Ollama прямо в чат Wazuh Dashboard через ML Commons. Этот подход обеспечивает полный контроль над данными без облачных зависимостей. В этой серии мы пойдём параллельным путём: будем использовать AWS Bedrock — конкретно Claude Sonnet 4.5 — как бэкенд для инференса, при этом все данные безопасности остаются строго внутри локальной Docker-сети.
Архитектура, которую мы строим, состоит из трёх слоёв:
- Часть 1 (эта статья) — конверсационный агент ML Commons на базе Bedrock Claude с PPLTool для запросов к алертам на естественном языке и чат-виджетом в Wazuh Dashboard
- Часть 2 —
opensearch-mcp-server-pyкак сайдкар-сервис в Docker, открывающий данные Wazuh Indexer через Model Context Protocol для внешних клиентов вроде Claude Desktop - Часть 3 — RAG-пайплайн с использованием Bedrock Titan Embeddings v2 и k-NN-индекса OpenSearch для семантического поиска по threat intelligence и SOC-плейбукам
По итогам Части 1 у вас будет работающий AI-аналитик в чате Wazuh Dashboard, который отвечает на вопросы об алертах на естественном языке, генерирует сводки угроз и транслирует запросы на английском языке в PPL-запросы к индексам wazuh-alerts-*.
Требования
- Docker и Docker Compose v2
- Репозиторий wazuh-docker, ветка
v4.14.3 - AWS-аккаунт с включённым доступом к моделям Bedrock (Claude Sonnet 4.5 и Titan Embed Text v2) в нужном регионе
- IAM-пользователь с разрешением
bedrock:InvokeModelна соответствующие ARN моделей - Минимум 8 ГБ RAM для Docker
Примечание о конфиденциальности. Содержимое алертов, отправляемых в Bedrock для инференса, обрабатывается AWS в соответствии с их условиями работы с данными. Для сред со строгими требованиями по месту хранения данных используйте подход с локальным Ollama из предыдущей статьи.
Подготовка стека
Клонирование и генерация сертификатов
git clone https://github.com/wazuh/wazuh-docker.git -b v4.14.3
cd wazuh-docker/single-node
docker compose -f generate-indexer-certs.yml run --rm generator
Создание файла .env
Все учётные данные хранятся в единственном файле .env в корне директории single-node/. Сразу добавьте его в .gitignore.
cat > single-node/.env << 'EOF'
# AWS Bedrock
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=...
AWS_SESSION_TOKEN=
AWS_REGION=us-east-1
EOF
Добавляем файл .env в .gitignore:
echo ".env" >> .gitignore
Оставьте AWS_SESSION_TOKEN пустым, если используете долгосрочные учётные данные IAM-пользователя. Для временных STS-credentials вставьте значение session token.
Скачивание Dashboard-плагинов ML Commons
Образ Wazuh Dashboard не включает UI-плагины ML Commons. Мы извлекаем их из соответствующего архива OpenSearch Dashboards.
curl https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/2.19.4/opensearch-dashboards-2.19.4-linux-x64.tar.gz -o opensearch-dashboards.tar.gz
tar -xzf opensearch-dashboards.tar.gz
mkdir -p config/wazuh_dashboard/plugins
cp -r opensearch-dashboards-2.19.4/plugins/observabilityDashboards config/wazuh_dashboard/plugins/
cp -r opensearch-dashboards-2.19.4/plugins/mlCommonsDashboards config/wazuh_dashboard/plugins/
cp -r opensearch-dashboards-2.19.4/plugins/assistantDashboards config/wazuh_dashboard/plugins/
rm -rf opensearch-dashboards-2.19.4* opensearch-dashboards.tar.gz
Скачивание Indexer-плагинов ML Commons
На стороне Indexer нужны два дополнительных плагина: opensearch-skills (содержит PPLTool, VectorDBTool и другие инструменты агентов) и opensearch-flow-framework.
mkdir -p config/wazuh_indexer/plugins
cd config/wazuh_indexer/plugins
curl -L -O https://repo1.maven.org/maven2/org/opensearch/plugin/opensearch-flow-framework/2.19.4.0/opensearch-flow-framework-2.19.4.0.zip
curl -L -O https://repo1.maven.org/maven2/org/opensearch/plugin/opensearch-skills/2.19.4.0/opensearch-skills-2.19.4.0.zip
mkdir -p opensearch-flow-framework opensearch-skills
unzip opensearch-flow-framework-2.19.4.0.zip -d opensearch-flow-framework/
unzip opensearch-skills-2.19.4.0.zip -d opensearch-skills/
rm -f *.zip
cd ../../..
Обновление opensearch_dashboards.yml
Добавьте следующие строки в config/wazuh_dashboard/opensearch_dashboards.yml:
assistant.chat.enabled: true
observability.query_assist.enabled: true
opensearch.requestTimeout: 300000
opensearch.shardTimeout: 300000
opensearch.pingTimeout: 300000
Обновление docker-compose.yml
Добавьте монтирование плагинов через volumes в сервисы wazuh.indexer и wazuh.dashboard.
Для wazuh.indexer в раздел volumes:
- ./config/wazuh_indexer/plugins/opensearch-flow-framework:/usr/share/wazuh-indexer/plugins/opensearch-flow-framework
- ./config/wazuh_indexer/plugins/opensearch-skills:/usr/share/wazuh-indexer/plugins/opensearch-skills
Для wazuh.dashboard в раздел volumes:
- ./config/wazuh_dashboard/plugins/assistantDashboards:/usr/share/wazuh-dashboard/plugins/assistantDashboards
- ./config/wazuh_dashboard/plugins/mlCommonsDashboards:/usr/share/wazuh-dashboard/plugins/mlCommonsDashboards
- ./config/wazuh_dashboard/plugins/observabilityDashboards:/usr/share/wazuh-dashboard/plugins/observabilityDashboards
Должен получиться примерно такой вид:
# Wazuh App Copyright (C) 2017, Wazuh Inc. (License GPLv2)
services:
wazuh.manager:
image: wazuh/wazuh-manager:4.14.3
hostname: wazuh.manager
restart: always
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 655360
hard: 655360
ports:
- "1514:1514"
- "1515:1515"
- "514:514/udp"
- "55000:55000"
environment:
- INDEXER_URL=https://wazuh.indexer:9200
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=SecretPassword
- FILEBEAT_SSL_VERIFICATION_MODE=full
- SSL_CERTIFICATE_AUTHORITIES=/etc/ssl/root-ca.pem
- SSL_CERTIFICATE=/etc/ssl/filebeat.pem
- SSL_KEY=/etc/ssl/filebeat.key
- API_USERNAME=wazuh-wui
- API_PASSWORD=MyS3cr37P450r.*-
volumes:
- wazuh_api_configuration:/var/ossec/api/configuration
- wazuh_etc:/var/ossec/etc
- wazuh_logs:/var/ossec/logs
- wazuh_queue:/var/ossec/queue
- wazuh_var_multigroups:/var/ossec/var/multigroups
- wazuh_integrations:/var/ossec/integrations
- wazuh_active_response:/var/ossec/active-response/bin
- wazuh_agentless:/var/ossec/agentless
- wazuh_wodles:/var/ossec/wodles
- filebeat_etc:/etc/filebeat
- filebeat_var:/var/lib/filebeat
- ./config/wazuh_indexer_ssl_certs/root-ca-manager.pem:/etc/ssl/root-ca.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.manager.pem:/etc/ssl/filebeat.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.manager-key.pem:/etc/ssl/filebeat.key
- ./config/wazuh_cluster/wazuh_manager.conf:/wazuh-config-mount/etc/ossec.conf
wazuh.indexer:
image: wazuh/wazuh-indexer:4.14.3
hostname: wazuh.indexer
restart: always
ports:
- "9200:9200"
environment:
- "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- wazuh-indexer-data:/var/lib/wazuh-indexer
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-indexer/config/certs/root-ca.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer-key.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.key
- ./config/wazuh_indexer_ssl_certs/wazuh.indexer.pem:/usr/share/wazuh-indexer/config/certs/wazuh.indexer.pem
- ./config/wazuh_indexer_ssl_certs/admin.pem:/usr/share/wazuh-indexer/config/certs/admin.pem
- ./config/wazuh_indexer_ssl_certs/admin-key.pem:/usr/share/wazuh-indexer/config/certs/admin-key.pem
- ./config/wazuh_indexer/wazuh.indexer.yml:/usr/share/wazuh-indexer/config/opensearch.yml
- ./config/wazuh_indexer/internal_users.yml:/usr/share/wazuh-indexer/config/opensearch-security/internal_users.yml
- ./config/wazuh_indexer/plugins/opensearch-flow-framework:/usr/share/wazuh-indexer/plugins/opensearch-flow-framework
- ./config/wazuh_indexer/plugins/opensearch-skills:/usr/share/wazuh-indexer/plugins/opensearch-skills
wazuh.dashboard:
image: wazuh/wazuh-dashboard:4.14.3
hostname: wazuh.dashboard
restart: always
ports:
- 443:5601
environment:
- INDEXER_USERNAME=admin
- INDEXER_PASSWORD=SecretPassword
- WAZUH_API_URL=https://wazuh.manager
- DASHBOARD_USERNAME=kibanaserver
- DASHBOARD_PASSWORD=kibanaserver
- API_USERNAME=wazuh-wui
- API_PASSWORD=MyS3cr37P450r.*-
volumes:
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard.pem
- ./config/wazuh_indexer_ssl_certs/wazuh.dashboard-key.pem:/usr/share/wazuh-dashboard/certs/wazuh-dashboard-key.pem
- ./config/wazuh_indexer_ssl_certs/root-ca.pem:/usr/share/wazuh-dashboard/certs/root-ca.pem
- ./config/wazuh_dashboard/opensearch_dashboards.yml:/usr/share/wazuh-dashboard/config/opensearch_dashboards.yml
- ./config/wazuh_dashboard/wazuh.yml:/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml
- wazuh-dashboard-config:/usr/share/wazuh-dashboard/data/wazuh/config
- wazuh-dashboard-custom:/usr/share/wazuh-dashboard/plugins/wazuh/public/assets/custom
- ./config/wazuh_dashboard/plugins/assistantDashboards:/usr/share/wazuh-dashboard/plugins/assistantDashboards
- ./config/wazuh_dashboard/plugins/mlCommonsDashboards:/usr/share/wazuh-dashboard/plugins/mlCommonsDashboards
- ./config/wazuh_dashboard/plugins/observabilityDashboards:/usr/share/wazuh-dashboard/plugins/observabilityDashboards
depends_on:
- wazuh.indexer
links:
- wazuh.indexer:wazuh.indexer
- wazuh.manager:wazuh.manager
volumes:
wazuh_api_configuration:
wazuh_etc:
wazuh_logs:
wazuh_queue:
wazuh_var_multigroups:
wazuh_integrations:
wazuh_active_response:
wazuh_agentless:
wazuh_wodles:
filebeat_etc:
filebeat_var:
wazuh-indexer-data:
wazuh-dashboard-config:
wazuh-dashboard-custom:
Запуск стека
docker compose up -d
docker compose ps
Также можно мониторить процесс запуска через docker compose logs -f.
Все три контейнера wazuh.indexer, wazuh.manager, wazuh.dashboard должны иметь статус Up.
Dashboard доступен по адресу https://localhost:443.
Настройка ML Commons
Откройте Wazuh Dashboard, перейдите в Indexer Management -> Dev Tools и выполните следующий запрос.
Активация agent framework
PUT /_cluster/settings
{
"persistent": {
"plugins.ml_commons.only_run_on_ml_node": false,
"plugins.ml_commons.native_memory_threshold": 99,
"plugins.ml_commons.agent_framework_enabled": true,
"plugins.ml_commons.memory_feature_enabled": true,
"plugins.ml_commons.rag_pipeline_feature_enabled": true,
"plugins.ml_commons.connector_access_control_enabled": true,
"plugins.ml_commons.connector.private_ip_enabled": true,
"plugins.ml_commons.trusted_connector_endpoints_regex": [
"^https://bedrock-runtime\\.[a-z0-9-]+\\.amazonaws\\.com/.*$"
]
}
}
Создание Bedrock-коннектора
POST /_plugins/_ml/connectors/_create
{
"name": "Bedrock Claude Sonnet 4.5",
"description": "Bedrock Claude Sonnet 4.5 for Wazuh security analytics",
"version": 1,
"protocol": "aws_sigv4",
"credential": {
"access_key": "<AWS_ACCESS_KEY_ID>",
"secret_key": "<AWS_SECRET_ACCESS_KEY>"
},
"parameters": {
"region": "us-east-1",
"service_name": "bedrock",
"response_filter": "$.content[0].text",
"max_tokens_to_sample": "8000",
"anthropic_version": "bedrock-2023-05-31",
"model": "us.anthropic.claude-sonnet-4-5-20250929-v1:0"
},
"actions": [{
"action_type": "predict",
"method": "POST",
"headers": { "content-type": "application/json" },
"url": "https://bedrock-runtime.${parameters.region}.amazonaws.com/model/${parameters.model}/invoke",
"request_body": "{\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"${parameters.prompt}\"}]},{\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"{\"}]}],\"anthropic_version\":\"${parameters.anthropic_version}\",\"max_tokens\":${parameters.max_tokens_to_sample}}"
}]
}
Сохраните connector_id из ответа.
Регистрация и деплой модели
POST /_plugins/_ml/models/_register?deploy=true
{
"name": "claude-sonnet-4-5",
"function_name": "remote",
"description": "Bedrock Claude Sonnet 4.5 для Wazuh",
"connector_id": "<connector_id>"
}
Сохраните model_id из ответа.
Выполните быстрый smoke-тест:
POST /_plugins/_ml/models/<model_id>/_predict
{
"parameters": {
"inputs": "Reply with exactly one word: WORKING"
}
}
В ответе должно быть WORKING.
Создание агента-аналитика безопасности
POST /_plugins/_ml/agents/_register
{
"name": "wazuh_bedrock_analyst",
"type": "conversational",
"description": "Wazuh Bedrock Claude",
"llm": {
"model_id": "<model_id>",
"parameters": {
"max_iteration": 5,
"stop_when_no_tool_found": true,
"response_filter": "$.content[0].text",
"system_instruction": "You are a senior SOC analyst specialized in Wazuh SIEM. Analyze alerts, identify threats, map findings to MITRE ATT&CK, and provide actionable recommendations. Be concise and precise."
}
},
"memory": { "type": "conversation_index" },
"tools": [
{
"type": "PPLTool",
"name": "WazuhAlertQuery",
"description": "Translates natural language security questions to PPL queries over wazuh-alerts-4.x-* indices. Use for: counting alerts, filtering by agent, rule level, source IP, or time range, and top-N aggregations.",
"parameters": {
"model_id": "<model_id>",
"index": "wazuh-alerts-4.x-*",
"execute": true
}
},
{
"type": "SearchIndexTool",
"name": "WazuhAlertSearch",
"description": "Searches wazuh-alerts-4.x-* using Query DSL. Use for exact field filtering on rule.level, rule.id, agent.name, data.srcip, and @timestamp.",
"parameters": { "index": "wazuh-alerts-4.x-*" }
},
{
"type": "CatIndexTool",
"name": "ListWazuhIndices",
"description": "Lists all wazuh-* indices with document counts and disk size."
},
{
"type": "IndexMappingTool",
"name": "DiscoverAlertFields",
"description": "Returns field mappings for any Wazuh index. Use before constructing a query to confirm field names."
}
],
"app_type": "os_chat"
}
Сохраните agent_id.
Подключение агента к чату Dashboard
docker compose exec wazuh.indexer curl -k -X PUT \
"https://localhost:9200/.plugins-ml-config/_doc/os_chat" \
--cert /usr/share/wazuh-indexer/config/certs/admin.pem \
--key /usr/share/wazuh-indexer/config/certs/admin-key.pem \
--cacert /usr/share/wazuh-indexer/config/certs/root-ca.pem \
-H "Content-Type: application/json" \
-d '{
"type": "os_chat_root_agent",
"configuration": {
"agent_id": "<agent_id>"
}
}'
Ожидаемый ответ:
{
"_index":".plugins-ml-config",
"_id":"os_chat",
"_version":2,
"result":"updated",
"_shards":{
"total":1,
"successful":1,
"failed":0
},
"_seq_no":2,
"_primary_term":1
}
Тестирование агента
Откройте Wazuh Dashboard и нажмите иконку чата в правом верхнем углу. Попробуйте следующие вопросы:
Show me the top 10 rules by alert count in the last 24 hours
или
Summarize all critical alerts (rule level 7 or above) from the past 6 hours.
Include affected agents, source IPs, and recommended actions.
Агент работает по циклу рассуждений ReAct: сначала может вызвать DiscoverAlertFields для проверки имён полей, затем WazuhAlertQuery для генерации и выполнения PPL-запроса, и наконец синтезирует ответ на естественном языке с помощью Bedrock Claude.
Заключение
В этой части мы развернули полный стек Wazuh в Docker с поддержкой ML Commons, подключили AWS Bedrock Claude Sonnet 4.5 в качестве LLM-бэкенда и создали конверсационного агента с набором инструментов для анализа алертов безопасности на естественном языке. В следующей части мы добавим opensearch-mcp-server-py как сайдкар-сервис, чтобы открыть данные Wazuh Indexer через Model Context Protocol для внешних клиентов.
Навигация по серии:
- Часть 1: ИИ-аналитика безопасности в Docker (вы здесь)
- Часть 2: MCP-сервер для внешних клиентов (скоро)
- Часть 3: RAG-пайплайн с Bedrock Titan Embeddings (скоро)
Рекомендуемое чтение
- Улучшение Wazuh с помощью Ollama: Часть 1
- Wazuh LLM: Fine-Tuned Llama 3.1 для анализа безопасности
- RAG для документации Wazuh: Часть 1