From 4bb61aba8b54cbe1d8c0a5c280a2507e23cfcefb Mon Sep 17 00:00:00 2001 From: elipeter Date: Tue, 24 Jun 2025 21:43:26 +0200 Subject: [PATCH] Update default configuration handling and integrate `NyxResult` into `config.rs` - Introduced `DEFAULT_CONFIG_TOML` to simplify default configuration loading. - Replaced `show_progress` with `quiet` in configuration for improved clarity. - Refactored `create_example_config` to use `NyxResult` and streamline logic with fallback handling. - Added `default-nyx.conf` file for default configuration management. - Enhanced `merge_configs` to include new parameters like `scan_timeout_secs` and `quiet`. --- default-nyx.conf | 103 ++++++++++++++++++++++++++++++++++++++++++++ src/errors.rs | 3 ++ src/utils/config.rs | 38 +++++++--------- 3 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 default-nyx.conf diff --git a/default-nyx.conf b/default-nyx.conf new file mode 100644 index 00000000..9a6d32e7 --- /dev/null +++ b/default-nyx.conf @@ -0,0 +1,103 @@ +# -------------------------------------------------------------------- +# nyx Vulnerability Scanner — DEFAULT CONFIGURATION +# +# Copy this file to `nyx.local` in the same directory and override +# only the keys you need. Anything you omit inherits the defaults +# shown here. +# -------------------------------------------------------------------- + +[scanner] + +## Minimum severity level to include in the report +## Possible values: Low | Medium | High | Critical +min_severity = "Low" + +## Maximum file size to scan (MiB); null = unlimited +max_file_size_mb = null + +## File extensions to ignore completely +excluded_extensions = [ + "jpg", "png", "gif", "mp4", "avi", "mkv", + "zip", "tar", "gz", "exe", "dll", "so", +] + +## Directories to ignore completely +excluded_directories = [ + "node_modules", ".git", "target", ".vscode", + ".idea", "build", "dist", +] + +## Individual files to ignore completely +excluded_files = [] + +## Honour global ignore file (e.g. ~/.config/nyx/ignore) +read_global_ignore = false + +## Honour .gitignore / .hgignore, etc. +read_vcsignore = true + +## Require a .git directory to read gitignore files +require_git_to_read_vcsignore = true + +## Limit search to the starting file system only +one_file_system = false + +## Follow symlinks when scanning +follow_symlinks = false + +## Scan hidden files (dot-files) +scan_hidden_files = false + + +[database] + +## Where to store the SQLite database (empty = default path) +path = "" + +## Number of days to keep database files; 0 = no cleanup (UNIMPLEMENTED) +auto_cleanup_days = 30 + +## Maximum database size in MiB; 0 = no limit (UNIMPLEMENTED) +max_db_size_mb = 1024 + +## Run VACUUM on startup (UNIMPLEMENTED) +vacuum_on_startup = false + + +[output] + +## Output format — only "console" exists for now +default_format = "console" + +## Suppress all console output (UNIMPLEMENTED) +quiet = false + +## Cap the number of issues shown; null = unlimited +max_results = null + + +[performance] + +## Maximum search depth; null = unlimited (UNIMPLEMENTED) +max_depth = null + +## Minimum depth for reported entries; null = none (UNIMPLEMENTED) +min_depth = null + +## Stop traversing into matching directories +prune = false + +## Worker threads; null or 0 = auto +worker_threads = null + +## Number of entries to index in a single chunk +batch_size = 100 + +## Channel capacity multiplier (capacity = threads × this) +channel_multiplier = 4 + +## Timeout on individual files (seconds); null = none (UNIMPLEMENTED) +scan_timeout_secs = null + +## Maximum memory to use in MiB; 0 = no limit (UNIMPLEMENTED) +memory_limit_mb = 512 diff --git a/src/errors.rs b/src/errors.rs index ce81de03..a9ce34ae 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -10,6 +10,9 @@ pub enum NyxError { #[error("I/O error: {0}")] Io(#[from] std::io::Error), + #[error("TOML parse error: {0}")] + Toml(#[from] toml::de::Error), + #[error("SQLite error: {0}")] Sql(#[from] rusqlite::Error), diff --git a/src/utils/config.rs b/src/utils/config.rs index 8b77f7be..dfb28cf4 100644 --- a/src/utils/config.rs +++ b/src/utils/config.rs @@ -1,3 +1,4 @@ +use crate::errors::NyxResult; use crate::patterns::Severity; use console::style; use serde::{Deserialize, Serialize}; @@ -5,6 +6,8 @@ use std::fs; use std::path::Path; use toml; +static DEFAULT_CONFIG_TOML: &str = include_str!("../../default-nyx.conf"); + #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(default)] pub struct ScannerConfig { @@ -107,8 +110,8 @@ pub struct OutputConfig { /// The default output format. TODO: IMPLEMENT others pub default_format: String, - /// Whether to show progress or not. TODO: IMPLEMENT - pub show_progress: bool, + /// Whether to print anything to the console or not. TODO: IMPLEMENT + pub quiet: bool, /// The maximum number of results to show. pub max_results: Option, @@ -118,7 +121,7 @@ impl Default for OutputConfig { fn default() -> Self { Self { default_format: "console".into(), - show_progress: true, + quiet: false, max_results: None, } } @@ -181,7 +184,7 @@ pub struct Config { } impl Config { - pub fn load(config_dir: &Path) -> Result> { + pub fn load(config_dir: &Path) -> NyxResult { let mut config = Config::default(); let default_config_path = config_dir.join("nyx.conf"); @@ -220,24 +223,12 @@ impl Config { } } -fn create_example_config(config_dir: &Path) -> Result<(), Box> { +fn create_example_config(config_dir: &Path) -> NyxResult<()> { let example_path = config_dir.join("nyx.conf"); - - let default_config = Config::default(); - let toml_content = toml::to_string_pretty(&default_config)?; - - // Add comments to make it user-friendly - let commented_content = format!( - "# nnyx Vulnerability Scanner Configuration\n\ - # YOU SHOULD NOT MODIFY THIS FILE.\n\ - # Create/modify 'nyx.local' to set configs\n\ - # Only include the sections you want to override\n\n{}", - toml_content - ); - - fs::write(&example_path, commented_content)?; - println!("Example config created at: {}", example_path.display()); - + if !example_path.exists() { + fs::write(&example_path, DEFAULT_CONFIG_TOML)?; + tracing::debug!("Example config created at: {}", example_path.display()); + } Ok(()) } @@ -245,6 +236,7 @@ fn create_example_config(config_dir: &Path) -> Result<(), Box Config { // --- ScannerConfig --- + default.scanner.min_severity = user.scanner.min_severity; default.scanner.max_file_size_mb = user.scanner.max_file_size_mb; default.scanner.read_global_ignore = user.scanner.read_global_ignore; default.scanner.read_vcsignore = user.scanner.read_vcsignore; @@ -268,13 +260,14 @@ fn merge_configs(mut default: Config, user: Config) -> Config { default.scanner.excluded_directories.dedup(); // --- DatabaseConfig --- + default.database.path = user.database.path; default.database.auto_cleanup_days = user.database.auto_cleanup_days; default.database.max_db_size_mb = user.database.max_db_size_mb; default.database.vacuum_on_startup = user.database.vacuum_on_startup; // --- OutputConfig --- default.output.default_format = user.output.default_format; - default.output.show_progress = user.output.show_progress; + default.output.quiet = user.output.quiet; default.output.max_results = user.output.max_results; // --- PerformanceConfig --- @@ -284,6 +277,7 @@ fn merge_configs(mut default: Config, user: Config) -> Config { default.performance.worker_threads = user.performance.worker_threads; default.performance.batch_size = user.performance.batch_size; default.performance.channel_multiplier = user.performance.channel_multiplier; + default.performance.scan_timeout_secs = user.performance.scan_timeout_secs; default.performance.memory_limit_mb = user.performance.memory_limit_mb; default