Wazuh REST API 4.14 - полный справочник

REST API Wazuh 4.14 предоставляет программный доступ ко всем функциям платформы: управление агентами, просмотр алертов, администрирование правил и декодеров, мониторинг кластера и управление безопасностью через RBAC. API работает на порту 55000 сервера Wazuh Manager и использует JWT-аутентификацию.

Аутентификация

Получение JWT-токена

Все запросы к API требуют JWT-токен, который получается через эндпоинт аутентификации:

TOKEN=$(curl -sk -u wazuh-wui:YOUR_PASSWORD \
  -X POST "https://localhost:55000/security/user/authenticate?raw=true")

Параметр raw=true возвращает только строку токена без JSON-обертки.

Использование токена

Токен передается в заголовке Authorization:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?limit=5"

Срок действия токена

По умолчанию JWT-токен действует 15 минут (900 секунд). Для изменения срока действия используйте эндпоинт настроек безопасности:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X PUT "https://localhost:55000/security/config" \
  -H "Content-Type: application/json" \
  -d '{"auth_token_exp_timeout": 3600}'

Python SDK - аутентификация

import requests
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

WAZUH_API = "https://localhost:55000"
CREDENTIALS = ("wazuh-wui", "YOUR_PASSWORD")

def get_token() -> str:
    """Obtain a JWT token from the Wazuh API."""
    response = requests.post(
        f"{WAZUH_API}/security/user/authenticate?raw=true",
        auth=CREDENTIALS,
        verify=False,
    )
    response.raise_for_status()
    return response.text

def api_request(method: str, endpoint: str, **kwargs) -> dict:
    """Execute an authenticated API request."""
    token = get_token()
    headers = {"Authorization": f"Bearer {token}"}
    response = requests.request(
        method,
        f"{WAZUH_API}{endpoint}",
        headers=headers,
        verify=False,
        **kwargs,
    )
    response.raise_for_status()
    return response.json()

Пагинация, фильтрация и сортировка

Пагинация

Все эндпоинты, возвращающие списки, поддерживают пагинацию:

ПараметрОписаниеПо умолчаниюМаксимум
offsetСмещение от начала0-
limitКоличество записей500100000
curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?offset=0&limit=10"

Фильтрация

API поддерживает фильтрацию через query-параметры:

# Фильтрация агентов по статусу
curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?status=active"

# Фильтрация по нескольким параметрам
curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?status=active&os.platform=ubuntu"

Поиск

Параметр search выполняет полнотекстовый поиск:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?search=web-server"

Сортировка

Параметр sort определяет порядок результатов:

# Сортировка по имени (по возрастанию)
curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?sort=+name"

# Сортировка по ID (по убыванию)
curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?sort=-id"

Выбор полей

Параметр select ограничивает возвращаемые поля:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?select=id,name,status,os.name"

Эндпоинты: Агенты

GET /agents

Получение списка агентов с поддержкой фильтрации:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents?status=active&limit=5" | jq '.data.affected_items[] | {id, name, status}'

Ответ:

{
  "data": {
    "affected_items": [
      {"id": "001", "name": "web-server-01", "status": "active"},
      {"id": "002", "name": "db-server-01", "status": "active"}
    ],
    "total_affected_items": 2,
    "total_failed_items": 0,
    "failed_items": []
  }
}

GET /agents/{agent_id}

Детальная информация об агенте:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/agents/001" | jq '.data.affected_items[0]'

DELETE /agents

Удаление агентов (поддерживает массовое удаление):

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X DELETE "https://localhost:55000/agents?agents_list=005,006&status=disconnected&older_than=7d"

PUT /agents/{agent_id}/restart

Перезапуск агента:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X PUT "https://localhost:55000/agents/001/restart"

PUT /agents/group/{group_id}

Добавление агентов в группу:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X PUT "https://localhost:55000/agents/group/web-servers" \
  -H "Content-Type: application/json" \
  -d '{"agents_list": ["001", "002"]}'

Python SDK - работа с агентами

# Получение списка активных агентов
agents = api_request("GET", "/agents", params={"status": "active", "limit": 100})
for agent in agents["data"]["affected_items"]:
    print(f"Agent {agent['id']}: {agent['name']} ({agent['status']})")

# Перезапуск агента
api_request("PUT", "/agents/001/restart")

# Получение информации об ОС агента
agent_info = api_request("GET", "/agents/001", params={"select": "os.name,os.version,os.platform"})

Эндпоинты: Менеджер

GET /manager/info

Информация о сервере Wazuh Manager:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/manager/info" | jq '.data.affected_items[0]'

GET /manager/status

Статус всех демонов Wazuh:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/manager/status" | jq '.data.affected_items[0]'

GET /manager/configuration

Текущая конфигурация менеджера:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/manager/configuration?section=global"

GET /manager/logs

Логи менеджера:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/manager/logs?limit=20&sort=-timestamp"

GET /manager/stats

Статистика обработки событий:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/manager/stats?date=$(date +%Y-%m-%d)"

Эндпоинты: Кластер

GET /cluster/status

Статус кластера:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/cluster/status"

GET /cluster/nodes

Список нод кластера:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/cluster/nodes" | jq '.data.affected_items[] | {name, type, version}'

GET /cluster/healthcheck

Проверка здоровья кластера:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/cluster/healthcheck"

GET /cluster/{node_id}/info

Информация о конкретной ноде:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/cluster/node01/info"

Эндпоинты: Правила

GET /rules

Получение списка правил:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/rules?limit=10&level=12-15" | jq '.data.affected_items[] | {id, level, description}'

GET /rules/{rule_id}

Детальная информация о правиле:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/rules/5710"

GET /rules/groups

Список групп правил:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/rules/groups"

GET /rules/files

Список файлов правил:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/rules/files?status=custom"

PUT /rules/files/{filename}

Обновление пользовательского файла правил:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X PUT "https://localhost:55000/rules/files/local_rules.xml" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @local_rules.xml

Эндпоинты: Декодеры

GET /decoders

Получение списка декодеров:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/decoders?limit=10&search=sshd"

GET /decoders/{decoder_name}

Информация о конкретном декодере:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/decoders/sshd"

GET /decoders/files

Список файлов декодеров:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/decoders/files?status=custom"

PUT /decoders/files/{filename}

Обновление пользовательского файла декодеров:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X PUT "https://localhost:55000/decoders/files/local_decoder.xml" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @local_decoder.xml

Эндпоинты: SCA (Security Configuration Assessment)

GET /sca/{agent_id}

Результаты SCA-проверок для агента:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/sca/001" | jq '.data.affected_items[] | {policy_id, pass, fail, score}'

GET /sca/{agent_id}/checks/{policy_id}

Детальные результаты проверок по политике:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/sca/001/checks/cis_ubuntu22-04" \
  | jq '.data.affected_items[] | select(.result == "failed") | {id, title, result}'

Python SDK - SCA отчет

def get_sca_report(agent_id: str) -> list[dict]:
    """Generate an SCA compliance report for an agent."""
    policies = api_request("GET", f"/sca/{agent_id}")
    report = []
    for policy in policies["data"]["affected_items"]:
        total = policy["pass"] + policy["fail"] + policy.get("invalid", 0)
        report.append({
            "policy": policy["policy_id"],
            "score": f"{policy['score']}%",
            "passed": policy["pass"],
            "failed": policy["fail"],
            "total": total,
        })
    return report

Эндпоинты: Уязвимости

GET /vulnerability/{agent_id}

Обнаруженные уязвимости на агенте:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/vulnerability/001?limit=10&severity=Critical" \
  | jq '.data.affected_items[] | {cve, name, severity, version}'

GET /vulnerability/{agent_id}/summary/{field}

Сводка уязвимостей по полю:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/vulnerability/001/summary/severity"

Python SDK - отчет об уязвимостях

def get_vulnerability_summary(agent_id: str) -> dict:
    """Get vulnerability summary grouped by severity."""
    vulns = api_request(
        "GET",
        f"/vulnerability/{agent_id}",
        params={"limit": 500},
    )

    summary = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0}
    for vuln in vulns["data"]["affected_items"]:
        severity = vuln.get("severity", "Low")
        summary[severity] = summary.get(severity, 0) + 1

    return summary

Эндпоинты: Syscollector (системная инвентаризация)

GET /syscollector/{agent_id}/os

Информация об операционной системе:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/os"

GET /syscollector/{agent_id}/packages

Установленные пакеты:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/packages?limit=20&sort=-size"

GET /syscollector/{agent_id}/ports

Открытые порты:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/ports?state=listening"

GET /syscollector/{agent_id}/processes

Запущенные процессы:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/processes?limit=20&sort=-resident_size"

GET /syscollector/{agent_id}/netiface

Сетевые интерфейсы:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/netiface"

GET /syscollector/{agent_id}/hardware

Аппаратная информация:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/syscollector/001/hardware"

Wazuh 4.14 добавляет расширенные поля syscollector, включая детальную информацию о CPU, RAM и дисковой подсистеме. Существующие поля остаются обратно совместимыми.

Эндпоинты: Безопасность и RBAC

GET /security/users

Список пользователей API:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/security/users"

POST /security/users

Создание пользователя:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X POST "https://localhost:55000/security/users" \
  -H "Content-Type: application/json" \
  -d '{"username": "analyst", "password": "SecureP@ss123!"}'

GET /security/roles

Список ролей RBAC:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/security/roles"

POST /security/roles

Создание роли:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X POST "https://localhost:55000/security/roles" \
  -H "Content-Type: application/json" \
  -d '{"name": "read-only-analyst", "rule": {"FIND": {"r^agent": ["read"]}}}'

POST /security/user/{user_id}/roles

Назначение роли пользователю:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  -X POST "https://localhost:55000/security/user/100/roles?role_ids=2"

GET /security/policies

Список политик RBAC:

curl -sk -H "Authorization: Bearer ${TOKEN}" \
  "https://localhost:55000/security/policies"

Коды ошибок

API Wazuh использует стандартные HTTP-коды и собственные коды ошибок:

HTTP-коды

КодОписание
200Успешный запрос
400Некорректный запрос (невалидные параметры)
401Неавторизованный запрос (недействительный токен)
403Доступ запрещен (недостаточно прав RBAC)
404Ресурс не найден
405Метод не поддерживается
429Превышен лимит запросов
500Внутренняя ошибка сервера

Коды ошибок Wazuh

КодОписаниеРешение
1000Wazuh Internal ErrorПроверьте логи менеджера
1001Error in API callПроверьте параметры запроса
1002Resource not foundУбедитесь, что ресурс существует
1003Permission deniedПроверьте роли и политики RBAC
1017Invalid credentialsПроверьте логин/пароль
1760Agent already belongs to a groupАгент уже в указанной группе

Обработка ошибок в Python

import requests

def safe_api_request(method: str, endpoint: str, **kwargs) -> dict:
    """Execute an API request with error handling."""
    try:
        result = api_request(method, endpoint, **kwargs)
        if result.get("error", 0) != 0:
            error_msg = result.get("message", "Unknown error")
            raise RuntimeError(f"Wazuh API error: {error_msg}")
        return result
    except requests.exceptions.ConnectionError:
        raise RuntimeError("Cannot connect to Wazuh API")
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 401:
            raise RuntimeError("Authentication failed - check credentials")
        elif e.response.status_code == 403:
            raise RuntimeError("Access denied - check RBAC permissions")
        raise

Postman Collection

Для тестирования API через Postman создайте коллекцию со следующей структурой:

Переменные окружения

{
  "wazuh_url": "https://localhost:55000",
  "wazuh_user": "wazuh-wui",
  "wazuh_password": "YOUR_PASSWORD",
  "wazuh_token": ""
}

Pre-request Script (для автоматического обновления токена)

const authUrl = pm.environment.get("wazuh_url") + "/security/user/authenticate?raw=true";

pm.sendRequest({
    url: authUrl,
    method: "POST",
    header: {
        "Authorization": "Basic " + btoa(
            pm.environment.get("wazuh_user") + ":" +
            pm.environment.get("wazuh_password")
        )
    }
}, function(err, response) {
    if (!err) {
        pm.environment.set("wazuh_token", response.text());
    }
});

Рекомендуемая структура коллекции

Wazuh API v4.14/
├── Authentication/
│   └── POST Authenticate
├── Agents/
│   ├── GET List Agents
│   ├── GET Agent Details
│   ├── PUT Restart Agent
│   └── DELETE Remove Agents
├── Manager/
│   ├── GET Info
│   ├── GET Status
│   └── GET Logs
├── Rules/
│   ├── GET List Rules
│   ├── GET Rule Details
│   └── PUT Update Rules File
├── Decoders/
│   ├── GET List Decoders
│   └── PUT Update Decoders File
├── SCA/
│   ├── GET Policies
│   └── GET Checks
├── Vulnerability/
│   └── GET Agent Vulnerabilities
├── Syscollector/
│   ├── GET OS Info
│   ├── GET Packages
│   ├── GET Ports
│   └── GET Processes
└── Security/
    ├── GET Users
    ├── POST Create User
    ├── GET Roles
    └── POST Assign Role

Ограничения и лимиты API

ПараметрЗначение
Максимальный limit100000 записей
Время жизни токена (по умолчанию)900 секунд (15 минут)
Rate limitingНастраивается в конфигурации API
Максимальный размер тела запроса10 MB
Параллельные соединенияЗависит от конфигурации сервера

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

API недоступен

  1. Проверьте статус демона API:
/var/ossec/bin/wazuh-control status | grep wazuh-apid
  1. Проверьте, что порт 55000 открыт:
ss -tlnp | grep 55000
  1. Просмотрите логи API:
tail -f /var/ossec/logs/api.log

Ошибка 401 при аутентификации

  • Убедитесь, что пользователь существует: GET /security/users
  • Проверьте корректность пароля
  • Убедитесь, что токен не истек (срок жизни по умолчанию - 15 минут)

Ошибка 403 при запросе

  • Проверьте назначенные роли: GET /security/users/{user_id}/roles
  • Убедитесь, что политика RBAC разрешает запрошенное действие
  • Для отладки временно используйте пользователя wazuh с полными правами

Медленные ответы API

  • Используйте select для ограничения возвращаемых полей
  • Уменьшите limit для пагинированных запросов
  • Используйте фильтры для сужения выборки
  • Проверьте нагрузку на сервер менеджера

Подробнее о создании пользовательских интеграций с использованием API читайте в разделе Разработка пользовательских интеграций . Обзор встроенных интеграций доступен в разделе Интеграции .

Last updated on