use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WafConfig {
pub engine: WafEngine,
pub ruleset: WafRuleset,
#[serde(default = "default_waf_mode")]
pub mode: WafMode,
#[serde(default = "default_waf_audit")]
pub audit_log: bool,
#[serde(default)]
pub body_inspection: BodyInspectionPolicy,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WafEngine {
ModSecurity,
Coraza,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WafRuleset {
pub crs_version: String,
pub custom_rules_dir: Option<PathBuf>,
#[serde(default = "default_paranoia_level")]
pub paranoia_level: u8,
#[serde(default = "default_anomaly_threshold")]
pub anomaly_threshold: u32,
#[serde(default)]
pub exclusions: Vec<RuleExclusion>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RuleExclusion {
pub rule_ids: Vec<String>,
pub scope: ExclusionScope,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExclusionScope {
Global,
Path(String),
Host(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WafMode {
Off,
Detection,
Prevention,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BodyInspectionPolicy {
#[serde(default = "default_inspect_request_body")]
pub inspect_request_body: bool,
#[serde(default)]
pub inspect_response_body: bool,
#[serde(default = "default_max_inspection_size")]
pub max_inspection_bytes: usize,
#[serde(default = "default_inspected_content_types")]
pub content_types: Vec<String>,
#[serde(default)]
pub decompress: bool,
#[serde(default = "default_max_decompression_ratio")]
pub max_decompression_ratio: f32,
}
impl Default for BodyInspectionPolicy {
fn default() -> Self {
Self {
inspect_request_body: default_inspect_request_body(),
inspect_response_body: false,
max_inspection_bytes: default_max_inspection_size(),
content_types: default_inspected_content_types(),
decompress: false,
max_decompression_ratio: default_max_decompression_ratio(),
}
}
}
fn default_waf_mode() -> WafMode {
WafMode::Prevention
}
fn default_waf_audit() -> bool {
true
}
fn default_paranoia_level() -> u8 {
1
}
fn default_anomaly_threshold() -> u32 {
5
}
fn default_inspect_request_body() -> bool {
true
}
fn default_max_inspection_size() -> usize {
1024 * 1024
}
fn default_inspected_content_types() -> Vec<String> {
vec![
"application/x-www-form-urlencoded".to_string(),
"multipart/form-data".to_string(),
"application/json".to_string(),
"application/xml".to_string(),
"text/xml".to_string(),
]
}
fn default_max_decompression_ratio() -> f32 {
100.0
}