Wazuh Client for Rust

A comprehensive Rust client library for interacting with Wazuh API and Wazuh Indexer. This library provides a type-safe, async interface for managing Wazuh deployments, agents, rules, and security monitoring.
Features
- 🚀 Async/Await Support - Built on tokio for high-performance async operations
- 🔒 Type Safety - Strongly typed API with comprehensive error handling
- 🛡️ Security First - Support for TLS/SSL with certificate validation
- 📊 Comprehensive API Coverage - Full Wazuh Manager API support plus core Indexer operations
- 🔧 Flexible Configuration - Easy configuration with builder patterns
Supported Wazuh Components
Wazuh Manager API
- Agent Management - Add, remove, configure, and monitor agents
- Rule Management - Create, update, and manage detection rules
- Cluster Operations - Monitor and manage cluster nodes
- Configuration Management - Update and retrieve configurations
- Active Response - Trigger and manage active responses
- Log Analysis - Query and analyze security logs
Wazuh Indexer
- Alert Queries - Search and retrieve security alerts
Quick Start
Add this to your Cargo.toml:
[dependencies]
wazuh-client = "0.1.7"
tokio = { version = "1.0", features = ["full"] }
Basic Usage
use wazuh_client_rs::{WazuhClientFactory, WazuhClients};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder()
.api_host(env::var("WAZUH_API_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()))
.api_port(env::var("WAZUH_API_PORT").unwrap_or_else(|_| "55000".to_string()).parse().unwrap_or(55000))
.api_credentials(
env::var("WAZUH_API_USERNAME").unwrap_or_else(|_| "wazuh".to_string()),
env::var("WAZUH_API_PASSWORD").unwrap_or_else(|_| "wazuh".to_string()),
)
.indexer_host(env::var("WAZUH_INDEXER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()))
.indexer_port(env::var("WAZUH_INDEXER_PORT").unwrap_or_else(|_| "9200".to_string()).parse().unwrap_or(9200))
.indexer_credentials(
env::var("WAZUH_INDEXER_USERNAME").unwrap_or_else(|_| "admin".to_string()),
env::var("WAZUH_INDEXER_PASSWORD").unwrap_or_else(|_| "admin".to_string()),
)
.verify_ssl(env::var("WAZUH_VERIFY_SSL").unwrap_or_else(|_| "false".to_string()).parse().unwrap_or(false))
.protocol("https") .build();
let mut clients: WazuhClients = factory.create_all_clients();
let summary = clients.agents.get_agents_summary().await?;
println!("Total agents: {}", summary.connection.total);
let rules = clients.rules.get_rules(Some(5), None, None, None, None).await?;
println!("Fetched {} rules.", rules.len());
Ok(())
}
Agent Management
use wazuh_client_rs::{WazuhClientFactory, WazuhClients, agents::AgentAddBody};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder()
.api_host("127.0.0.1")
.api_credentials("wazuh", "wazuh")
.build();
let mut clients: WazuhClients = factory.create_all_clients();
match clients.agents.get_agent("001").await {
Ok(agent) => println!("Agent 001 Status: {}", agent.status),
Err(e) => eprintln!("Error getting agent 001: {}", e),
}
Ok(())
}
Rule Management
use wazuh_client_rs::{WazuhClientFactory, WazuhClients};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder()
.api_host("127.0.0.1")
.api_credentials("wazuh", "wazuh")
.build();
let mut clients: WazuhClients = factory.create_all_clients();
let rules = clients.rules.get_rules(Some(5), None, None, None, None).await?;
println!("Fetched {} rules.", rules.len());
let ssh_rules = clients.rules.get_rules_by_group("ssh").await?;
println!("Found {} rules in the 'ssh' group.", ssh_rules.len());
Ok(())
}
Cluster Monitoring
use wazuh_client_rs::{WazuhClientFactory, WazuhClients};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder()
.api_host("127.0.0.1")
.api_credentials("wazuh", "wazuh")
.build();
let mut clients: WazuhClients = factory.create_all_clients();
match clients.cluster.get_cluster_status().await {
Ok(status) => println!("Cluster enabled: {}", status.enabled),
Err(e) => eprintln!("Error getting cluster status: {}", e),
}
match clients.cluster.get_cluster_nodes(None, None, None).await {
Ok(nodes) => println!("Found {} cluster nodes.", nodes.len()),
Err(e) => eprintln!("Error getting cluster nodes: {}", e),
}
Ok(())
}
Log Analysis with Indexer
use wazuh_client_rs::{WazuhClientFactory, WazuhClients};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder()
.indexer_host("127.0.0.1")
.indexer_credentials("admin", "admin")
.build();
let clients: WazuhClients = factory.create_all_clients();
match clients.indexer.get_alerts(Some(10)).await {
Ok(alerts) => println!("Retrieved {} alerts.", alerts.len()),
Err(e) => eprintln!("Error getting alerts: {}", e),
}
Ok(())
}
Configuration
Environment Variables
You can configure the client using environment variables:
export WAZUH_API_HOST="https://your-wazuh-manager.com"
export WAZUH_API_PORT="55000"
export WAZUH_API_USERNAME="wazuh"
export WAZUH_API_PASSWORD="your-password"
export WAZUH_VERIFY_SSL="true"
export WAZUH_INDEXER_HOST="your-wazuh-indexer.com"
export WAZUH_INDEXER_PORT="9200"
export WAZUH_INDEXER_USERNAME="admin"
export WAZUH_INDEXER_PASSWORD="admin"
Client Factory Initialization
The WazuhClientFactory is used to configure and create clients using a builder pattern.
use wazuh_client_rs::WazuhClientFactory;
use std::env;
let factory = WazuhClientFactory::builder()
.api_host(env::var("WAZUH_API_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()))
.api_port(env::var("WAZUH_API_PORT").unwrap_or_else(|_| "55000".to_string()).parse().unwrap_or(55000))
.api_credentials(
env::var("WAZUH_API_USERNAME").unwrap_or_else(|_| "wazuh".to_string()),
env::var("WAZUH_API_PASSWORD").unwrap_or_else(|_| "wazuh".to_string()),
)
.indexer_host(env::var("WAZUH_INDEXER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()))
.indexer_port(env::var("WAZUH_INDEXER_PORT").unwrap_or_else(|_| "9200".to_string()).parse().unwrap_or(9200))
.indexer_credentials(
env::var("WAZUH_INDEXER_USERNAME").unwrap_or_else(|_| "admin".to_string()),
env::var("WAZUH_INDEXER_PASSWORD").unwrap_or_else(|_| "admin".to_string()),
)
.verify_ssl(env::var("WAZUH_VERIFY_SSL").unwrap_or_else(|_| "false".to_string()).parse().unwrap_or(false))
.protocol("https")
.build();
Error Handling
The library provides comprehensive error handling with detailed error types:
use wazuh_client_rs::{WazuhClientFactory, WazuhClients, WazuhApiError};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let factory = WazuhClientFactory::builder().build();
let mut clients: WazuhClients = factory.create_all_clients();
match clients.agents.get_agent("invalid-id-123").await {
Ok(agent) => println!("Agent: {:?}", agent.name),
Err(WazuhApiError::HttpError { status, message, .. }) => {
eprintln!("HTTP Error {}: {}", status, message);
}
Err(e) => eprintln!("An unexpected error occurred: {}", e),
}
Ok(())
}
Examples
The examples/ directory contains comprehensive examples:
Run examples with:
cargo run --example basic_usage
cargo run --example agent_management
Features
Default Features
tls - Enable TLS support using native TLS
Optional Features
rustls - Use rustls instead of native TLS
Enable features in your Cargo.toml:
[dependencies]
wazuh-client = { version = "0.1.0", features = ["rustls"] }
Compatibility
- Rust: 1.70.0 or later
- Wazuh: 4.12 or later
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch
- Make your changes
- Add test
- Submit a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support