use rpki::ccr::{decode_content_info, verify::verify_content_info, verify_against_report_json_path, verify_against_vcir_store_path}; #[derive(Debug, Default, PartialEq, Eq)] struct Args { ccr_path: Option, report_json: Option, db_path: Option, } fn usage() -> &'static str { "Usage: ccr_verify --ccr [--report-json ] [--db ]" } fn parse_args(argv: &[String]) -> Result { let mut args = Args::default(); let mut i = 1usize; while i < argv.len() { match argv[i].as_str() { "--help" | "-h" => return Err(usage().to_string()), "--ccr" => { i += 1; let v = argv.get(i).ok_or("--ccr requires a value")?; args.ccr_path = Some(v.into()); } "--report-json" => { i += 1; let v = argv.get(i).ok_or("--report-json requires a value")?; args.report_json = Some(v.into()); } "--db" => { i += 1; let v = argv.get(i).ok_or("--db requires a value")?; args.db_path = Some(v.into()); } other => return Err(format!("unknown argument: {other}\n{}", usage())), } i += 1; } if args.ccr_path.is_none() { return Err(format!("--ccr is required\n{}", usage())); } Ok(args) } fn main() -> Result<(), String> { let args = parse_args(&std::env::args().collect::>())?; let ccr_path = args.ccr_path.as_ref().unwrap(); let bytes = std::fs::read(ccr_path).map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?; let ci = decode_content_info(&bytes).map_err(|e| e.to_string())?; let summary = verify_content_info(&ci).map_err(|e| e.to_string())?; if let Some(report_json) = args.report_json.as_ref() { verify_against_report_json_path(&ci, report_json).map_err(|e| e.to_string())?; } if let Some(db_path) = args.db_path.as_ref() { verify_against_vcir_store_path(&ci, db_path).map_err(|e| e.to_string())?; } println!("{}", serde_json::to_string_pretty(&summary).map_err(|e| e.to_string())?); Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn parse_args_accepts_all_flags() { let argv = vec![ "ccr_verify".to_string(), "--ccr".to_string(), "a.ccr".to_string(), "--report-json".to_string(), "report.json".to_string(), "--db".to_string(), "db".to_string(), ]; let args = parse_args(&argv).expect("parse"); assert_eq!(args.ccr_path.as_deref(), Some(std::path::Path::new("a.ccr"))); assert_eq!(args.report_json.as_deref(), Some(std::path::Path::new("report.json"))); assert_eq!(args.db_path.as_deref(), Some(std::path::Path::new("db"))); } #[test] fn parse_args_rejects_missing_required_ccr() { let argv = vec!["ccr_verify".to_string()]; let err = parse_args(&argv).unwrap_err(); assert!(err.contains("--ccr is required"), "{err}"); } }