* Using latest 0.1.8 wazuh-client-rs craate which fixes issue with

ordering: (#17)
* Improved unmarshaling for indexer responses
* Other minor changes.
This commit is contained in:
Gianluca Brigandi 2025-12-05 15:52:19 -08:00
parent 5f452bac9d
commit 020d19600d
6 changed files with 54 additions and 13 deletions

View File

@ -9,7 +9,7 @@ repository = "https://github.com/gbrigandi/mcp-server-wazuh"
readme = "README.md"
[dependencies]
wazuh-client = "0.1.7"
wazuh-client = "0.1.8"
rmcp = { version = "0.1.5", features = ["server", "transport-io"] }
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false }

View File

@ -79,10 +79,48 @@ impl AlertTools {
.and_then(|l| l.as_u64())
.unwrap_or(0);
let formatted_text = format!(
// Extract source IP from data.srcip (common for SSH, network alerts)
let src_ip = source.get("data")
.and_then(|d| d.get("srcip"))
.and_then(|ip| ip.as_str())
.or_else(|| source.get("data")
.and_then(|d| d.get("src_ip"))
.and_then(|ip| ip.as_str()))
.unwrap_or("");
// Extract destination IP if available
let dst_ip = source.get("data")
.and_then(|d| d.get("dstip"))
.and_then(|ip| ip.as_str())
.or_else(|| source.get("data")
.and_then(|d| d.get("dst_ip"))
.and_then(|ip| ip.as_str()))
.unwrap_or("");
// Extract source user if available
let src_user = source.get("data")
.and_then(|d| d.get("srcuser"))
.and_then(|u| u.as_str())
.or_else(|| source.get("data")
.and_then(|d| d.get("dstuser"))
.and_then(|u| u.as_str()))
.unwrap_or("");
// Build formatted text with optional fields
let mut formatted_text = format!(
"Alert ID: {}\nTime: {}\nAgent: {}\nLevel: {}\nDescription: {}",
id, timestamp, agent_name, rule_level, description
);
if !src_ip.is_empty() {
formatted_text.push_str(&format!("\nSource IP: {}", src_ip));
}
if !dst_ip.is_empty() {
formatted_text.push_str(&format!("\nDestination IP: {}", dst_ip));
}
if !src_user.is_empty() {
formatted_text.push_str(&format!("\nUser: {}", src_user));
}
Content::text(formatted_text)
})
.collect();

View File

@ -101,7 +101,7 @@ impl VulnerabilityTools {
params
.severity
.as_deref()
.and_then(VulnerabilitySeverity::from_str),
.and_then(VulnerabilitySeverity::parse),
)
.await;

View File

@ -54,7 +54,7 @@ impl McpStdioClient {
fn read_response(&mut self) -> Result<Value, Box<dyn std::error::Error>> {
let mut line = String::new();
self.stdout.read_line(&mut line)?;
let response: Value = serde_json::from_str(&line.trim())?;
let response: Value = serde_json::from_str(line.trim())?;
Ok(response)
}

View File

@ -260,7 +260,7 @@ mod tests {
let client = reqwest::Client::new();
let response = client
.post(&format!("{}/security/user/authenticate", mock_server.url()))
.post(format!("{}/security/user/authenticate", mock_server.url()))
.json(&json!({"username": "admin", "password": "admin"}))
.send()
.await
@ -277,7 +277,7 @@ mod tests {
let client = reqwest::Client::new();
let response = client
.post(&format!("{}/wazuh-alerts*/_search", mock_server.url()))
.post(format!("{}/wazuh-alerts*/_search", mock_server.url()))
.json(&json!({"query": {"match_all": {}}}))
.send()
.await
@ -294,9 +294,9 @@ mod tests {
async fn test_empty_alerts_server() {
let mock_server = MockWazuhServer::with_empty_alerts();
let client = reqwest::Client::new();
let response = client
.post(&format!("{}/wazuh-alerts*/_search", mock_server.url()))
.post(format!("{}/wazuh-alerts*/_search", mock_server.url()))
.json(&json!({"query": {"match_all": {}}}))
.send()
.await
@ -312,9 +312,9 @@ mod tests {
async fn test_auth_error_server() {
let mock_server = MockWazuhServer::with_auth_error();
let client = reqwest::Client::new();
let response = client
.post(&format!("{}/security/user/authenticate", mock_server.url()))
.post(format!("{}/security/user/authenticate", mock_server.url()))
.json(&json!({"username": "admin", "password": "wrong"}))
.send()
.await
@ -327,9 +327,9 @@ mod tests {
async fn test_alerts_error_server() {
let mock_server = MockWazuhServer::with_alerts_error();
let client = reqwest::Client::new();
let response = client
.post(&format!("{}/wazuh-alerts*/_search", mock_server.url()))
.post(format!("{}/wazuh-alerts*/_search", mock_server.url()))
.json(&json!({"query": {"match_all": {}}}))
.send()
.await

View File

@ -1,8 +1,11 @@
//! Integration tests for the rmcp-based Wazuh MCP Server
//!
//!
//! These tests verify the MCP server functionality using a mock Wazuh API server.
//! Tests cover tool registration, parameter validation, alert retrieval, and error handling.
// Allow holding mutex guard across await in tests - this is intentional for test serialization
#![allow(clippy::await_holding_lock)]
use std::process::{Child, Command, Stdio};
use std::io::{BufRead, BufReader, Write};
use std::time::Duration;