|
1 | | -use anyhow::Result; |
| 1 | +use anyhow::{Context, Result}; |
2 | 2 | use clap::Parser; |
3 | 3 | use httpjail::jail::{JailConfig, create_jail}; |
4 | 4 | use httpjail::proxy::ProxyServer; |
@@ -175,7 +175,20 @@ fn parse_rule(rule_str: &str) -> Result<Rule> { |
175 | 175 | fn build_rules(args: &Args) -> Result<Vec<Rule>> { |
176 | 176 | let mut rules = Vec::new(); |
177 | 177 |
|
178 | | - // Parse rules in the exact order specified |
| 178 | + // Load rules from config file if provided |
| 179 | + if let Some(config_path) = &args.config { |
| 180 | + let contents = std::fs::read_to_string(config_path) |
| 181 | + .with_context(|| format!("Failed to read config file: {}", config_path))?; |
| 182 | + for line in contents.lines() { |
| 183 | + let line = line.trim(); |
| 184 | + if line.is_empty() || line.starts_with('#') { |
| 185 | + continue; |
| 186 | + } |
| 187 | + rules.push(parse_rule(line)?); |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + // Parse command line rules in the exact order specified |
179 | 192 | for rule_str in &args.rules { |
180 | 193 | rules.push(parse_rule(rule_str)?); |
181 | 194 | } |
@@ -501,4 +514,45 @@ mod tests { |
501 | 514 | Action::Allow |
502 | 515 | )); |
503 | 516 | } |
| 517 | + |
| 518 | + #[test] |
| 519 | + fn test_build_rules_from_config_file() { |
| 520 | + use std::io::Write; |
| 521 | + use tempfile::NamedTempFile; |
| 522 | + |
| 523 | + let mut file = NamedTempFile::new().unwrap(); |
| 524 | + writeln!( |
| 525 | + file, |
| 526 | + "allow-get: google\\.com\n# comment\ndeny: yahoo.com\n\nallow: .*" |
| 527 | + ) |
| 528 | + .unwrap(); |
| 529 | + |
| 530 | + let args = Args { |
| 531 | + rules: vec![], |
| 532 | + config: Some(file.path().to_str().unwrap().to_string()), |
| 533 | + dry_run: false, |
| 534 | + log_only: false, |
| 535 | + no_tls_intercept: false, |
| 536 | + interactive: false, |
| 537 | + weak: false, |
| 538 | + verbose: 0, |
| 539 | + timeout: None, |
| 540 | + no_jail_cleanup: false, |
| 541 | + cleanup: false, |
| 542 | + command: vec![], |
| 543 | + }; |
| 544 | + |
| 545 | + let rules = build_rules(&args).unwrap(); |
| 546 | + assert_eq!(rules.len(), 3); |
| 547 | + |
| 548 | + // First rule should be allow for GET method only |
| 549 | + assert!(matches!(rules[0].action, Action::Allow)); |
| 550 | + assert!(rules[0].methods.as_ref().unwrap().contains(&Method::GET)); |
| 551 | + |
| 552 | + // Second rule should be deny |
| 553 | + assert!(matches!(rules[1].action, Action::Deny)); |
| 554 | + |
| 555 | + // Third rule allow all |
| 556 | + assert!(matches!(rules[2].action, Action::Allow)); |
| 557 | + } |
504 | 558 | } |
0 commit comments