# Wazuh Indexer API - запросы и работа с данными

> Работа с API Wazuh Indexer на базе OpenSearch - индексные паттерны, DSL-запросы, агрегации, PPL, SQL, шаблоны индексов и устранение неполадок

Source: https://opennix.org/docs/wazuh/infrastructure/wazuh-indexer-api/


Wazuh Indexer построен на базе OpenSearch и предоставляет REST API для поиска, анализа и управления данными безопасности. Через API можно выполнять DSL-запросы к алертам, строить агрегации для аналитических отчетов, использовать PPL и SQL для интерактивного анализа, а также управлять шаблонами индексов и маппингами полей. Понимание работы с Indexer API необходимо для построения кастомных дашбордов, автоматизации и интеграции Wazuh с внешними системами.

## Индексные паттерны Wazuh

Wazuh Indexer хранит данные в нескольких типах индексов, каждый из которых имеет свою функцию и период ротации.

### Основные индексы

| Индекс | Назначение | Ротация |
|---|---|---|
| `wazuh-alerts-*` | Алерты, сгенерированные при срабатывании правил | Ежедневно |
| `wazuh-archives-*` | Все события, включая не вызвавшие алертов | Ежедневно |
| `wazuh-monitoring-*` | Статусы подключения агентов | Еженедельно |
| `wazuh-statistics-*` | Метрики производительности сервера Wazuh | Еженедельно |

### Индексы состояния (State indices)

Начиная с Wazuh 4.14, данные инвентаризации и уязвимостей хранятся в отдельных индексах состояния:

| Индекс | Содержимое |
|---|---|
| `wazuh-states-vulnerabilities-*` | Обнаруженные уязвимости и их критичность |
| `wazuh-states-inventory-packages-*` | Установленное программное обеспечение |
| `wazuh-states-inventory-processes-*` | Запущенные процессы |
| `wazuh-states-inventory-ports-*` | Открытые сетевые порты |
| `wazuh-states-inventory-hardware-*` | CPU, память, оборудование |
| `wazuh-states-inventory-system-*` | ОС, архитектура, hostname |
| `wazuh-states-inventory-networks-*` | Сетевые адреса IPv4/IPv6 |

### Просмотр индексов

Список всех индексов Wazuh:

```bash
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/_cat/indices/wazuh-*?v&s=index"
```

Размер конкретного индекса:

```bash
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/_cat/indices/wazuh-alerts-*?v&h=index,docs.count,store.size&s=index"
```

## Поиск алертов с помощью DSL-запросов

OpenSearch Query DSL (Domain Specific Language) - основной язык запросов для поиска данных в Wazuh Indexer.

### Базовый поиск (match)

Поиск алертов по описанию правила:

```json
GET wazuh-alerts-*/_search
{
  "size": 10,
  "query": {
    "match": {
      "rule.description": "authentication failure"
    }
  },
  "sort": [
    { "timestamp": { "order": "desc" } }
  ]
}
```

### Точное совпадение (term)

Поиск алертов определенного уровня:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "term": {
      "rule.level": 12
    }
  }
}
```

### Составной запрос (bool)

Комбинирование условий с помощью `must`, `should`, `must_not` и `filter`:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "rule.groups": "authentication_failed" } }
      ],
      "filter": [
        { "range": { "timestamp": { "gte": "now-24h" } } },
        { "term": { "agent.name": "web-server-01" } }
      ],
      "must_not": [
        { "term": { "rule.level": 3 } }
      ]
    }
  },
  "sort": [{ "timestamp": "desc" }],
  "size": 50
}
```

### Диапазонный запрос (range)

Поиск алертов за определенный период:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "timestamp": {
              "gte": "2025-01-01T00:00:00",
              "lte": "2025-01-31T23:59:59",
              "format": "yyyy-MM-dd'T'HH:mm:ss"
            }
          }
        },
        {
          "range": {
            "rule.level": { "gte": 10 }
          }
        }
      ]
    }
  }
}
```

### Поиск по вложенным полям

Wazuh хранит данные MITRE ATT&CK в структурированных полях:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "bool": {
      "must": [
        { "term": { "rule.mitre.id": "T1110" } },
        { "term": { "rule.mitre.tactic": "Credential Access" } }
      ]
    }
  },
  "_source": ["timestamp", "rule.description", "rule.level", "agent.name"]
}
```

### Wildcard и regex

Поиск с использованием подстановочных символов:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "wildcard": {
      "data.srcip": "192.168.1.*"
    }
  }
}
```

Поиск с регулярным выражением:

```json
GET wazuh-alerts-*/_search
{
  "query": {
    "regexp": {
      "data.url": ".*\\.(php|asp|jsp)\\?.*id=.*"
    }
  }
}
```

## Агрегации

Агрегации позволяют получать статистику и аналитические отчеты по данным Wazuh без необходимости выгружать все документы.

### Terms - топ значений

Топ-10 правил, которые срабатывали чаще всего:

```json
GET wazuh-alerts-*/_search
{
  "size": 0,
  "query": {
    "range": { "timestamp": { "gte": "now-7d" } }
  },
  "aggs": {
    "top_rules": {
      "terms": {
        "field": "rule.id",
        "size": 10,
        "order": { "_count": "desc" }
      },
      "aggs": {
        "rule_description": {
          "terms": { "field": "rule.description.keyword", "size": 1 }
        }
      }
    }
  }
}
```

### Date histogram - временная шкала

Количество алертов по часам за последние сутки:

```json
GET wazuh-alerts-*/_search
{
  "size": 0,
  "query": {
    "range": { "timestamp": { "gte": "now-24h" } }
  },
  "aggs": {
    "alerts_over_time": {
      "date_histogram": {
        "field": "timestamp",
        "fixed_interval": "1h"
      },
      "aggs": {
        "by_level": {
          "range": {
            "field": "rule.level",
            "ranges": [
              { "key": "low", "from": 0, "to": 7 },
              { "key": "medium", "from": 7, "to": 12 },
              { "key": "critical", "from": 12, "to": 16 }
            ]
          }
        }
      }
    }
  }
}
```

### Cardinality - уникальные значения

Количество уникальных агентов, IP-адресов и правил:

```json
GET wazuh-alerts-*/_search
{
  "size": 0,
  "query": {
    "range": { "timestamp": { "gte": "now-24h" } }
  },
  "aggs": {
    "unique_agents": {
      "cardinality": { "field": "agent.id" }
    },
    "unique_source_ips": {
      "cardinality": { "field": "data.srcip" }
    },
    "unique_rules": {
      "cardinality": { "field": "rule.id" }
    }
  }
}
```

### Вложенные агрегации

Топ-5 агентов с разбивкой по тактикам MITRE ATT&CK:

```json
GET wazuh-alerts-*/_search
{
  "size": 0,
  "aggs": {
    "by_agent": {
      "terms": { "field": "agent.name", "size": 5 },
      "aggs": {
        "by_tactic": {
          "terms": { "field": "rule.mitre.tactic", "size": 5 }
        },
        "max_level": {
          "max": { "field": "rule.level" }
        }
      }
    }
  }
}
```

## Шаблоны индексов и маппинги полей

### Просмотр текущего шаблона

```bash
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/_template/wazuh?pretty"
```

### Основные поля Wazuh-алертов

| Поле | Тип | Описание |
|---|---|---|
| `timestamp` | date | Время события |
| `rule.id` | keyword | Идентификатор правила |
| `rule.level` | integer | Уровень критичности (0-15) |
| `rule.description` | text/keyword | Описание правила |
| `rule.groups` | keyword | Группы правила |
| `rule.mitre.id` | keyword | MITRE ATT&CK technique ID |
| `rule.mitre.tactic` | keyword | MITRE ATT&CK тактика |
| `agent.id` | keyword | Идентификатор агента |
| `agent.name` | keyword | Имя агента |
| `agent.ip` | ip | IP-адрес агента |
| `data.srcip` | ip | IP-адрес источника |
| `data.dstip` | ip | IP-адрес назначения |
| `data.srcport` | integer | Порт источника |
| `data.dstport` | integer | Порт назначения |
| `location` | keyword | Источник лога |
| `full_log` | text | Полный текст лог-записи |

### Обновление шаблона

Для добавления кастомного индексного паттерна:

```bash
# Скачать текущий шаблон
curl -so template.json \
  "https://raw.githubusercontent.com/wazuh/wazuh/v4.14.4/extensions/elasticsearch/7.x/wazuh-template.json"

# Добавить кастомный паттерн в index_patterns
# Загрузить обновленный шаблон
curl -sk -u admin:$PASSWORD \
  -XPUT "https://localhost:9200/_template/wazuh-custom" \
  -H "Content-Type: application/json" \
  -d @template.json
```

### Конфликты маппингов

Если поле имеет разные типы в разных индексах, возникает конфликт маппинга. Проверка:

```bash
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/wazuh-alerts-*/_mapping?pretty" | \
  jq '.. | .type? // empty' | sort | uniq -c | sort -rn
```

## Dev Tools - консоль в Dashboard

Wazuh Dashboard включает консоль Dev Tools (унаследованную от OpenSearch Dashboards), которая позволяет выполнять API-запросы без использования curl.

### Доступ к Dev Tools

1. Откройте Wazuh Dashboard
2. Перейдите в меню OpenSearch Dashboards - Dev Tools
3. Или используйте URL: `https://<dashboard>:443/app/dev_tools#/console`

### Примеры использования

В консоли Dev Tools не нужно указывать URL и аутентификацию:

```
# Проверить состояние кластера
GET _cluster/health

# Поиск последних критических алертов
GET wazuh-alerts-*/_search
{
  "size": 5,
  "query": {
    "bool": {
      "filter": [
        { "range": { "rule.level": { "gte": 12 } } },
        { "range": { "timestamp": { "gte": "now-1h" } } }
      ]
    }
  },
  "sort": [{ "timestamp": "desc" }]
}

# Статистика по агентам
GET wazuh-alerts-*/_search
{
  "size": 0,
  "aggs": {
    "agents": {
      "terms": { "field": "agent.name", "size": 20 }
    }
  }
}
```

### Автодополнение

Dev Tools поддерживает автодополнение имен индексов, полей и ключевых слов DSL. Используйте `Ctrl+Space` для вызова подсказок.

## PPL - Piped Processing Language

PPL предоставляет синтаксис, аналогичный Unix-пайпам, для запросов к данным. Удобен для аналитиков, знакомых с Splunk SPL.

### Базовый синтаксис

```
source = wazuh-alerts-* | where rule.level >= 10 | sort - timestamp | head 20
```

### Фильтрация и агрегация

```
source = wazuh-alerts-*
| where timestamp > '2025-01-01 00:00:00'
| where rule.level >= 7
| stats count() as alert_count by rule.id, rule.description
| sort - alert_count
| head 10
```

### Выполнение PPL через API

```bash
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/_plugins/_ppl" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "source = wazuh-alerts-* | where rule.level >= 12 | stats count() by agent.name | sort - count()"
  }'
```

### Временные фильтры в PPL

```
source = wazuh-alerts-*
| where timestamp > DATE_SUB(NOW(), INTERVAL 24 HOUR)
| stats count() as alerts by span(timestamp, 1h) as hour
| sort hour
```

### Группировка с несколькими метриками

```
source = wazuh-alerts-*
| where timestamp > DATE_SUB(NOW(), INTERVAL 7 DAY)
| stats count() as total, max(rule.level) as max_level, dc(agent.id) as agents
  by rule.mitre.tactic
| sort - total
```

## SQL Plugin

OpenSearch SQL plugin позволяет использовать привычный SQL-синтаксис для запросов к данным Wazuh.

### Базовые запросы

```sql
SELECT timestamp, rule.id, rule.level, rule.description, agent.name
FROM wazuh-alerts-*
WHERE rule.level >= 10
  AND timestamp > NOW() - INTERVAL 24 HOUR
ORDER BY timestamp DESC
LIMIT 50
```

### Агрегации в SQL

```sql
SELECT rule.id, rule.description, COUNT(*) as count
FROM wazuh-alerts-*
WHERE timestamp > NOW() - INTERVAL 7 DAY
GROUP BY rule.id, rule.description
ORDER BY count DESC
LIMIT 10
```

### Выполнение SQL через API

```bash
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/_plugins/_sql" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "SELECT agent.name, COUNT(*) as alerts FROM wazuh-alerts-* WHERE rule.level >= 7 GROUP BY agent.name ORDER BY alerts DESC"
  }'
```

### Перевод SQL в DSL

Полезно для отладки - преобразование SQL в эквивалентный DSL-запрос:

```bash
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/_plugins/_sql/_explain" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "SELECT * FROM wazuh-alerts-* WHERE rule.level >= 12 LIMIT 10"
  }'
```

## Bulk-операции

Массовые операции полезны для управления данными и автоматизации.

### Bulk-поиск (msearch)

Выполнение нескольких запросов за один вызов:

```bash
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/_msearch" \
  -H "Content-Type: application/x-ndjson" \
  -d '
{"index":"wazuh-alerts-*"}
{"size":0,"query":{"range":{"rule.level":{"gte":12}}},"aggs":{"count":{"value_count":{"field":"_id"}}}}
{"index":"wazuh-alerts-*"}
{"size":0,"query":{"range":{"timestamp":{"gte":"now-1h"}}},"aggs":{"count":{"value_count":{"field":"_id"}}}}
'
```

### Scroll API для больших выборок

При необходимости получить более 10 000 документов используйте Scroll API:

```bash
# Инициализация scroll
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/wazuh-alerts-*/_search?scroll=5m" \
  -H "Content-Type: application/json" \
  -d '{
    "size": 1000,
    "query": { "range": { "timestamp": { "gte": "now-30d" } } },
    "sort": [{ "timestamp": "asc" }]
  }'

# Продолжение scroll (использовать _scroll_id из ответа)
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/_search/scroll" \
  -H "Content-Type: application/json" \
  -d '{
    "scroll": "5m",
    "scroll_id": "<SCROLL_ID>"
  }'
```

### Удаление по запросу (delete by query)

Удаление старых алертов низкого уровня:

```bash
curl -sk -u admin:$PASSWORD \
  -XPOST "https://localhost:9200/wazuh-alerts-*/_delete_by_query" \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "bool": {
        "filter": [
          { "range": { "timestamp": { "lte": "now-90d" } } },
          { "range": { "rule.level": { "lte": 3 } } }
        ]
      }
    }
  }'
```

## Сравнение с другими SIEM-системами

### Elasticsearch Query DSL

Wazuh Indexer (OpenSearch) использует синтаксис, полностью совместимый с Elasticsearch 7.x Query DSL. Основные отличия:

| Функция | Wazuh Indexer (OpenSearch) | Elasticsearch |
|---|---|---|
| Базовый DSL | Идентичный синтаксис | Идентичный синтаксис |
| SQL Plugin | `_plugins/_sql` | `_sql` (X-Pack) |
| PPL | `_plugins/_ppl` | Отсутствует |
| Alerting | `_plugins/_alerting` | X-Pack Watcher |
| Безопасность | Security Plugin (встроено) | X-Pack Security (платно) |

Миграция запросов из Elasticsearch в Wazuh Indexer не требует изменений в DSL-синтаксисе.

### Splunk SPL

| Задача | Wazuh PPL | Splunk SPL |
|---|---|---|
| Поиск | `source = index \| where field = 'value'` | `index=main field=value` |
| Агрегация | `stats count() by field` | `stats count by field` |
| Сортировка | `sort - field` | `sort - field` |
| Лимит | `head N` | `head N` |
| Временной фильтр | `where timestamp > ...` | `earliest=-24h` |

PPL в OpenSearch наиболее близок к SPL по синтаксису, что упрощает миграцию для аналитиков из Splunk.

### QRadar AQL

| Задача | Wazuh SQL | QRadar AQL |
|---|---|---|
| Поиск событий | `SELECT * FROM wazuh-alerts-*` | `SELECT * FROM events` |
| Фильтрация | `WHERE rule.level >= 10` | `WHERE severity >= 7` |
| Агрегация | `GROUP BY rule.id` | `GROUP BY qid` |
| Временной фильтр | `WHERE timestamp > NOW() - INTERVAL 1 HOUR` | `WHERE starttime > NOW - 1 HOURS` |

SQL-синтаксис в OpenSearch близок к стандартному SQL, что упрощает адаптацию для пользователей QRadar.

## Устранение неполадок

### Медленные запросы

**Симптом**: запросы выполняются дольше 10 секунд.

Диагностика:

```bash
# Проверка нагрузки на кластер
curl -sk -u admin:$PASSWORD "https://localhost:9200/_nodes/stats/os,jvm?pretty"

# Проверка медленных запросов (включить slow log)
curl -sk -u admin:$PASSWORD \
  -XPUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{
    "index.search.slowlog.threshold.query.warn": "5s",
    "index.search.slowlog.threshold.query.info": "2s"
  }'

# Просмотр slow log
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/_cat/indices/.opendistro-slow-log-*?v"
```

Решения:

- Используйте `filter` вместо `must` для условий, не требующих релевантности
- Ограничивайте временной диапазон запроса - не запрашивайте данные за все время
- Добавьте `"size": 0` если нужны только агрегации
- Избегайте `wildcard` и `regexp` на полях без keyword-маппинга
- Увеличьте JVM heap, если сборщик мусора работает слишком часто

### Конфликты маппингов полей

**Симптом**: ошибка `illegal_argument_exception` при запросе.

```bash
# Проверка маппинга конкретного поля
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/wazuh-alerts-*/_mapping/field/data.srcip?pretty"
```

Решение: поле определено с разными типами в разных индексах. Необходимо обновить шаблон и переиндексировать данные или использовать `keyword` суффикс:

```json
{ "term": { "rule.description.keyword": "Authentication failure" } }
```

### Индекс не найден (index_not_found_exception)

**Симптом**: ошибка `no such index [wazuh-alerts-*]`.

Диагностика:

```bash
# Проверить существующие индексы
curl -sk -u admin:$PASSWORD "https://localhost:9200/_cat/indices/wazuh-*?v"

# Проверить алиасы
curl -sk -u admin:$PASSWORD "https://localhost:9200/_cat/aliases/wazuh-*?v"

# Проверить, что Filebeat отправляет данные
curl -sk -u admin:$PASSWORD \
  "https://localhost:9200/_cat/indices/wazuh-alerts-*?v&s=index:desc&h=index,docs.count,store.size"
```

Решения:

- Убедитесь, что Filebeat запущен и подключен к Indexer
- Проверьте конфигурацию Filebeat: `filebeat.yml` должен содержать корректный `output.elasticsearch.hosts`
- Проверьте шаблон индекса: `_template/wazuh`
- Для архивных данных убедитесь, что `logall_json` включен в `ossec.conf`

### Превышение лимита результатов

**Симптом**: ошибка `Result window is too large` при запросе с `"from": 10000`.

OpenSearch по умолчанию ограничивает `from + size` значением 10 000. Решения:

- Используйте Scroll API для полной выгрузки данных
- Используйте `search_after` для пагинации
- Для аналитики используйте агрегации вместо выгрузки документов

```json
GET wazuh-alerts-*/_search
{
  "size": 100,
  "query": { "match_all": {} },
  "sort": [{ "timestamp": "desc" }, { "_id": "asc" }],
  "search_after": ["2025-01-15T10:30:00.000Z", "abc123"]
}
```

## Дополнительные материалы

- [Установка Wazuh Indexer](/docs/wazuh/installation/wazuh-indexer-installation/) - развертывание и настройка
- [Настройка Wazuh Dashboard](/docs/wazuh/infrastructure/wazuh-dashboard-configuration/) - визуализация и анализ данных
- [Архитектура Wazuh](/docs/wazuh/getting-started/wazuh-architecture/) - обзор компонентов платформы
- [Сбор логов](/docs/wazuh/capabilities/wazuh-log-data-collection/) - настройка источников данных

