use clap::Parser;
use tracing::info;
use crate::export::ExportError;
use crate::firewall_rule::FirewallRuleError;
use crate::loader::LoaderError;
use crate::{
audit::run_audit,
export::{ExportFormat, export_results},
firewall_rule::{FirewallRuleProvider, PlatformFirewallProvider},
loader::load_audit_criteria,
};
#[derive(Debug, thiserror::Error)]
pub enum FirewallAuditError {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("Validation error: {0}")]
ValidationError(String),
#[error("Loader error: {0}")]
LoaderError(#[from] LoaderError),
#[error("Firewall rule error: {0}")]
FirewallRuleError(#[from] FirewallRuleError),
#[error("Export error: {0}")]
ExportError(#[from] ExportError),
}
#[derive(Parser, Debug)]
#[command(
author,
version,
about = "Cross-platform firewall audit tool (CSV/HTML/JSON export)",
long_about = "This program audits local firewall rules against user-defined criteria \
from a YAML or JSON file. Results can be exported in various formats."
)]
pub struct Args {
#[arg(long, short = 'c')]
pub criteria: Option<String>,
#[arg(long, short = 'e', default_value = "stdout")]
pub export: ExportFormat,
#[arg(long, short = 'o')]
pub output: Option<String>,
#[arg(long, short = 'q')]
pub quiet: bool,
}
pub fn run_firewall_audit(args: Args) -> Result<(), FirewallAuditError> {
let audit_criteria = load_audit_criteria(args.criteria)?;
if audit_criteria.is_empty() {
return Err(FirewallAuditError::ValidationError(
"No valid audit criteria loaded.".into(),
));
}
info!("Loaded {} audit criteria(s).", audit_criteria.len());
let firewall_rules = PlatformFirewallProvider::list_rules()?;
info!("Loaded {} firewall rule(s).", firewall_rules.len());
let audit_results = run_audit(&audit_criteria, &firewall_rules);
export_results(&audit_results, &args.export, args.output)?;
Ok(())
}